# source:trunk/yat/statistics/Fisher.h@3455

Last change on this file since 3455 was 3455, checked in by Peter, 7 years ago

• Property svn:eol-style set to native
• Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line
1#ifndef _theplu_yat_statistics_fisher_
2#define _theplu_yat_statistics_fisher_
3
4// $Id: Fisher.h 3455 2015-12-10 06:57:14Z peter$
5
6/*
7  Copyright (C) 2004, 2005 Peter Johansson
8  Copyright (C) 2006, 2007, 2008 Jari Häkkinen, Peter Johansson
9  Copyright (C) 2009, 2011, 2013, 2014, 2015 Peter Johansson
10
11  This file is part of the yat library, http://dev.thep.lu.se/yat
12
13  The yat library is free software; you can redistribute it and/or
14  modify it under the terms of the GNU General Public License as
15  published by the Free Software Foundation; either version 3 of the
17
18  The yat library is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  General Public License for more details.
22
23  You should have received a copy of the GNU General Public License
24  along with yat. If not, see <http://www.gnu.org/licenses/>.
25*/
26
27#include <yat/utility/deprecate.h>
28
29namespace theplu {
30namespace yat {
31namespace statistics {
32
33  /**
34     @brief Fisher's exact test.
35
36     Fisher's Exact test is a procedure that you can use for data
37     in a two by two contingency table: \f[ \begin{tabular}{|c|c|}
38     \hline a&b \tabularnewline \hline c&d \tabularnewline \hline
39     \end{tabular} \f] Fisher's Exact Test is based on exact
40     probabilities from a specific distribution (the hypergeometric
41     distribution). There's really no lower bound on the amount of
42     data that is needed for Fisher's Exact Test. You do have to
43     have at least one data value in each row and one data value in
44     each column. If an entire row or column is zero, then you
45     don't really have a 2 by 2 table. But you can use Fisher's
46     Exact Test when one of the cells in your table has a zero in
47     it. Fisher's Exact Test is also very useful for highly
48     imbalanced tables. If one or two of the cells in a two by two
49     table have numbers in the thousands and one or two of the
50     other cells has numbers less than 5, you can still use
51     Fisher's Exact Test. For very large tables (where all four
52     entries in the two by two table are large), your computer may
53     take too much time to compute Fisher's Exact Test. In these
54     situations, though, you might as well use the Chi-square test
55     because a large sample approximation (that the Chi-square test
56     relies on) is very reasonable. If all elements are larger than
57     10 a Chi-square test is reasonable to use.
58
59     @note The statistica assumes that each column and row sum,
60     respectively, are fixed. Just because you have a 2x2 table, this
61     assumtion does not necessarily match you experimental setup. See
62     e.g. Barnard's test for alternative.
63  */
64
65  class Fisher
66  {
67
68  public:
69    ///
70    /// Default Constructor.
71    ///
72    /// \param yates if true Yates's correction is used for
73    /// chi-squared calculation
74    ///
75    Fisher(bool yates=false);
76
77    ///
78    /// Destructor
79    ///
80    virtual ~Fisher(void);
81
82
83    /**
84       The Chi2 score is calculated as \f$\sum 85 \frac{(O_i-E_i)^2}{E_i}\f$ where \a E is expected value and \a
86       O is observed value.
87
88       If indicated in constructor, Yates's correction is used, i.e.,
89       Chi2 is calculated as \f$\frac{(|O_i-E_i|-0.5)^2}{E_i} \f$
90
91
92       \see expected(double&, double&, double&, double&)
93
94       \return Chi2 score
95    */
96    double Chi2(void) const;
97
98    /**
99       Calculates the expected values under the null hypothesis.
100       \f$a' = \frac{(a+c)(a+b)}{a+b+c+d} \f$,
101       \f$b' = \frac{(a+b)(b+d)}{a+b+c+d} \f$,
102       \f$c' = \frac{(a+c)(c+d)}{a+b+c+d} \f$,
103       \f$d' = \frac{(b+d)(c+d)}{a+b+c+d} \f$,
104    */
105    void expected(double& a, double& b, double& c, double& d) const;
106
107    ///
108    /// If all elements in table is at least minimum_size(), a Chi2
109    /// approximation is used for p-value calculation.
110    ///
111    /// @return reference to minimum_size
112    ///
113    unsigned int& minimum_size(void);
114
115    ///
116    /// If all elements in table is at least minimum_size(), a Chi2
117    /// approximation is used for p-value calculation.
118    ///
119    /// @return const reference to minimum_size
120    ///
121    const unsigned int& minimum_size(void) const;
122
123    /**
124       Calculates probability to get oddsratio (or smaller).
125
126       If all elements in table is at least minimum_size(), a Chi2
127       approximation is used.
128
129       \since New in yat 0.11
130     */
131    double p_left(void) const;
132
133    /**
134       Calculates probability to get oddsratio (or greater).
135
136       If all elements in table is at least minimum_size(), a Chi2
137       approximation is used.
138
139       \since New in yat 0.11
140     */
141    double p_right(void) const;
142
143    /**
144       If all elements in table is at least minimum_size(), a Chi2
145       approximation is used.
146
147       Otherwise a two-sided p-value is calculated using the
148       hypergeometric distribution
149       \f$\sum_k P(k) \f$ where summation runs over \a k such that
150       \f$P(k) \le P(a) \f$.
151
152       \return two-sided p-value
153    */
154    double p_value(void) const;
155
156    ///
157    /// One-sided p-value is probability to get larger (or equal) oddsratio.
158    ///
159    /// If all elements in table is at least minimum_size(), a Chi2
160    /// approximation is used.
161    ///
162    /// @return One-sided p-value
163    ///
164    /// \deprecated Provided for backward compatibility with the 0.10
165    /// API. Use p_right() instead.
166    ///
167    double p_value_one_sided() const YAT_DEPRECATE;
168
169    /**
170       Function calculating odds ratio from 2x2 table
171       \f[ \begin{tabular}{|c|c|}
172       \hline a&b \tabularnewline \hline c&d \tabularnewline \hline
173       \end{tabular} \f] as \f$\frac{ad}{bc} \f$
174
175       Object will remember the values of \a a, \a b, \a c, and \a d.
176
177       @return odds ratio.
178
179       @throw If table is invalid a runtime_error is thrown. A table
180       is invalid if a row or column sum is zero.
181    */
182    double oddsratio(const unsigned int a, const unsigned int b,
183                     const unsigned int c, const unsigned int d);
184
185    /**
186       \return oddsratio loaded via oddsratio(4)
187
188       \since New in yat 0.8
189     */
190    double oddsratio(void) const;
191
192  private:
193    bool calculate_p_exact(void) const;
194
195    // two-sided
196    double p_value_approximative(void) const;
197    // two-sided
198    double p_value_exact(void) const;
199    // calculate two-sided p-value to get k (or fewer) wins when
200    // drawing t samples out of of a population of n1 wins and n2 losses
201    double p_value_exact(unsigned int k, unsigned int n1, unsigned int n2,
202                         unsigned int t) const;
203
204    double lower_tail(unsigned int k, unsigned int n1, unsigned int n2,
205                      unsigned int t) const;
206
207    // return P(X=k+1) / P(X=k)
208    double hypergeometric_ratio(unsigned int k, unsigned int n1,
209                                unsigned int n2, unsigned int t) const;
210    double choose_ratio(unsigned int n, unsigned int k) const;
211
212    double p_left_exact(void) const;
213    double p_right_exact(void) const;
214
215    double yates(unsigned int o, double e) const;
216
217    unsigned int a_;
218    unsigned int b_;
219    unsigned int c_;
220    unsigned int d_;
221    unsigned int minimum_size_;
222    double oddsratio_;
223    bool yates_;
224  };
225
226}}} // of namespace statistics, yat, and theplu
227
228#endif
Note: See TracBrowser for help on using the repository browser.