Skip to content

Commit 84dff7a

Browse files
committed
Add chi-square independence test
1 parent a02d76b commit 84dff7a

20 files changed

Lines changed: 1773 additions & 0 deletions

File tree

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2020 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# Chi-square independence test
22+
23+
> Perform a chi-square independence test.
24+
25+
<section class="usage">
26+
27+
## Usage
28+
29+
```javascript
30+
var chi2test = require( '@stdlib/stats/chi2test' );
31+
```
32+
33+
#### chi2test( x\[, opts] )
34+
35+
Computes a chi-square independence test for the **null hypothesis** that the joint distribution of the cell counts in two-dimensional `ndarray` or `array` of `arrays` `x` is the product of the row and column marginals, i.e. that the row and column variables are independent.
36+
37+
```javascript
38+
// 2x2 table
39+
var x = [
40+
[ 20, 30 ],
41+
[ 30, 20 ]
42+
];
43+
44+
var out = chi2test( x );
45+
/* returns
46+
{
47+
'rejected': false,
48+
'alpha': 0.05,
49+
'pValue': ~0.072,
50+
'df': 1,
51+
'statistic': 3.24,
52+
...
53+
}
54+
*/
55+
```
56+
57+
The function accepts the following `options`:
58+
59+
- **alpha**: significance level of the hypothesis test. Must be on the interval `[0,1]`. Default: `0.05`.
60+
- **correct**: `boolean` indicating whether to use Yates' continuity correction when provided a 2x2 contingency table. Default: `true`.
61+
62+
By default, the test is performed at a significance level of `0.05`. To adjust the significance level, set the `alpha` option.
63+
64+
```javascript
65+
var x = [
66+
[ 20, 30 ],
67+
[ 30, 20 ]
68+
];
69+
var opts = {
70+
'alpha': 0.1
71+
};
72+
var out = chi2test( x, opts );
73+
/* returns
74+
{
75+
'rejected': true,
76+
'alpha': 0.1,
77+
'pValue': ~0.072,
78+
'df': 1,
79+
'statistic': 3.24,
80+
...
81+
}
82+
*/
83+
```
84+
85+
For 2x2 contingency tables, the function by default applies Yates' continuity correction. To disable the continuity correction, set `correct` to `false`.
86+
87+
```javascript
88+
var x = [
89+
[ 20, 30 ],
90+
[ 30, 20 ]
91+
];
92+
var opts = {
93+
'correct': false
94+
};
95+
var out = chi2test( x, opts );
96+
/* returns
97+
{
98+
'rejected': true,
99+
'alpha': 0.05,
100+
'pValue': ~0.046,
101+
'df': 1,
102+
'statistic': 4,
103+
...
104+
}
105+
*/
106+
```
107+
108+
The function returns an `object` having the following properties:
109+
110+
- **alpha**: significance level.
111+
- **rejected**: `boolean` indicating the test decision.
112+
- **pValue**: test p-value.
113+
- **statistic**: test statistic.
114+
- **df**: degrees of freedom.
115+
- **expected**: expected cell counts.
116+
- **method**: test name.
117+
- **print**: method for printing formatted test output.
118+
119+
To print formatted test output, invoke the `print` method. `print` accepts a `digits` option that controls the number of decimal digits displayed for the outputs and a `decision` option, which when set to `false` will hide the test decision.
120+
121+
<!-- run-disable -->
122+
123+
```javascript
124+
var x = [
125+
[ 20, 30 ],
126+
[ 30, 20 ]
127+
];
128+
var out = chi2test( x );
129+
console.log( out.print() );
130+
/* =>
131+
* Chi-square independence test
132+
*
133+
* Null hypothesis: the two variables are independent
134+
*
135+
* pValue: 0.0719
136+
* statistic: 3.24
137+
* degrees of freedom: 1
138+
*
139+
* Test Decision: Fail to reject null in favor of alternative at 5% significance level
140+
*/
141+
142+
console.log( out.print({
143+
'digits': 6
144+
}) );
145+
/* =>
146+
* Chi-square independence test
147+
*
148+
* Null hypothesis: the two variables are independent
149+
*
150+
* pValue: 0.071861
151+
* statistic: 3.24
152+
* degrees of freedom: 1
153+
*
154+
* Test Decision: Fail to reject null in favor of alternative at 5% significance level
155+
*/
156+
```
157+
158+
</section>
159+
160+
<!-- /.usage -->
161+
162+
<section class="notes">
163+
164+
## Notes
165+
166+
- The chi-square approximation may be incorrect if the observed or expected frequencies in each category are too small. Common practice is to require frequencies greater than five. The Yates' continuity correction is enabled by default for 2x2 tables to account for this, although it tends to over-correct.
167+
168+
</section>
169+
170+
<!-- /.notes -->
171+
172+
<section class="examples">
173+
174+
## Examples
175+
176+
<!-- eslint no-undef: "error" -->
177+
178+
```javascript
179+
var array = require( '@stdlib/ndarray/array' );
180+
var chi2test = require( '@stdlib/stats/chi2test' );
181+
182+
var table;
183+
var out;
184+
185+
/*
186+
* Data from students in grades 4-6 on whether good grades, athletic ability, or popularity are most important to them:
187+
*
188+
* Source: Chase, M.A and Dummer, G.M. (1992), "The Role of Sports as a Social Determinant for Children"
189+
*/
190+
table = array([
191+
/* Grades Popular Sports */
192+
[ 63, 31, 25 ], // 4th
193+
[ 88, 55, 33 ], // 5th
194+
[ 96, 55, 32 ] // 6th
195+
]);
196+
197+
// Assess whether the grade level and the students' goals are independent of each other:
198+
out = chi2test( table );
199+
// returns {...}
200+
201+
console.log( out.print() );
202+
```
203+
204+
</section>
205+
206+
<!-- /.examples -->
207+
208+
<section class="links">
209+
210+
</section>
211+
212+
<!-- /.links -->
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var array = require( '@stdlib/ndarray/array' );
25+
var isObject = require( '@stdlib/assert/is-object' );
26+
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
27+
var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
28+
var max = require( '@stdlib/math/base/special/max' );
29+
var pkg = require( './../package.json' ).name;
30+
var chi2test = require( './../lib' );
31+
32+
33+
// MAIN //
34+
35+
bench( pkg, function benchmark( b ) {
36+
var result;
37+
var len;
38+
var x;
39+
var i;
40+
41+
// Generate contingency table:
42+
len = 100;
43+
x = new Array( len );
44+
for ( i = 0; i < x.length; i++ ) {
45+
x[ i ] = discreteUniform( 10, 50 );
46+
}
47+
x = array( x, {
48+
'shape': [ 10, 10 ]
49+
});
50+
51+
b.tic();
52+
for ( i = 0; i < b.iterations; i++ ) {
53+
x.data[ i % x.data.length ] += max( discreteUniform( -1, 1 ), 0 );
54+
result = chi2test( x );
55+
if ( typeof result !== 'object' ) {
56+
b.fail( 'should return an object' );
57+
}
58+
}
59+
b.toc();
60+
if ( !isObject( result ) ) {
61+
b.fail( 'should return an object' );
62+
}
63+
b.pass( 'benchmark finished' );
64+
b.end();
65+
});
66+
67+
bench( pkg+':print', function benchmark( b ) {
68+
var digits;
69+
var result;
70+
var output;
71+
var x;
72+
var i;
73+
74+
x = array([
75+
/* Grades Popular Sports */
76+
[ 63, 31, 25 ], // 4th
77+
[ 88, 55, 33 ], // 5th
78+
[ 96, 55, 32 ] // 6th
79+
]);
80+
result = chi2test( x );
81+
82+
b.tic();
83+
for ( i = 0; i < b.iterations; i++ ) {
84+
digits = ( i % 8 ) + 1;
85+
output = result.print({
86+
'digits': digits
87+
});
88+
if ( typeof output !== 'string' ) {
89+
b.fail( 'should return a string' );
90+
}
91+
}
92+
b.toc();
93+
if ( !isString( output ) ) {
94+
b.fail( 'should return a string' );
95+
}
96+
b.pass( 'benchmark finished' );
97+
b.end();
98+
});
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
2+
{{alias}}( x[, options] )
3+
Performs a chi-square independence test.
4+
5+
For a two-way contingency table `x` (represented as a two-dimensional
6+
`ndarray` or `array` of `arrays`), the null hypothesis that the joint
7+
distribution of the cell counts is the product of the row and column
8+
marginals is tested, i.e. whether the row and column variables are
9+
independent.
10+
11+
The function returns an object containing the test statistic, p-value, and
12+
decision.
13+
14+
Parameters
15+
----------
16+
x: (MatrixLike|Array<Array>)
17+
Two-way table of cell counts.
18+
19+
options: Object (optional)
20+
Options.
21+
22+
options.alpha: number (optional)
23+
Significance level of the hypothesis test. Must be on the interval
24+
[0,1]. Default: 0.05.
25+
26+
options.correct: boolean (optional)
27+
Boolean indicating whether to use Yates' continuity correction when
28+
provided a 2x2 contingency table. Default: true.
29+
30+
Returns
31+
-------
32+
out: Object
33+
Test result object.
34+
35+
out.alpha: number
36+
Significance level.
37+
38+
out.rejected: boolean
39+
Test decision.
40+
41+
out.pValue: number
42+
Test p-value.
43+
44+
out.statistic: number
45+
Test statistic.
46+
47+
out.df: number
48+
Degrees of freedom.
49+
50+
out.expected: ndarray
51+
Expected cell counts.
52+
53+
out.method: string
54+
Test name.
55+
56+
out.print: Function
57+
Function to print formatted output.
58+
59+
Examples
60+
--------
61+
// Provide expected probabilities...
62+
> var x = [ [ 20, 30 ], [ 30, 20 ] ];
63+
> var out = {{alias}}( x )
64+
{ 'rejected': false, 'pValue': ~0.072, 'statistic': 3.24, ... }
65+
> out.print()
66+
67+
// Set significance level...
68+
> var opts = { 'alpha': 0.1 };
69+
> out = {{alias}}( x, opts )
70+
{ 'rejected': true, 'pValue': ~0.072, 'statistic': 3.24, ... }
71+
> out.print()
72+
73+
// Disable Yates' continuity correction (primarily used with small counts):
74+
> opts = { 'correct': false };
75+
> out = {{alias}}( x, opts )
76+
{...}
77+
78+
See Also
79+
--------
80+

0 commit comments

Comments
 (0)