# Source code for simplestatistics.statistics.chi_squared_dist_table

"""
Implements chi_squared_dist_table() function.
"""

[docs]def chi_squared_dist_table(k=0, p=0):
"""
From Wikipedia <https://en.wikipedia.org/wiki/Chi-squared_distribution>_.

The p-value is the probability of observing a test statistic at least as
extreme in a chi-squared distribution. Accordingly, since the cumulative
distribution function (CDF) for the appropriate degrees of freedom (df)
gives the probability of having obtained a value less extreme than this
point, subtracting the CDF value from 1 gives the p-value. The table below
gives a number of p-values matching to :math:\\chi^2 for the first 10
degrees of freedom.

The chi_squared_dist_table function can either return the full table of
:math:\\chi^2 vs. *p* values, or it can perform a lookup for a certain value
if given *k* (degrees of freedom: df) or *k* and *p* values.

*k* has to be one of the following values:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 40, 50, 60, 70, 80, 90, 100

*p* has to be one of the following values:

.005, .01, .025, .05, .1, .5, .9, .95, .975, .99, .995

Args:
k: (optional) int of *k* representing degrees of freedom.
p: (optiona, but *k* is required) float of *p* representing probability.

Returns:
Entire table as dict where the key is degree of freedom and value is another dict of keys
representing *p* and values representing test statistic.
If only *k* is provided, the function returns a dict of *p*: test statistic pairs.
If both *k* and *p* are provided, the function will return the specific test statistic.

Examples:
>>> chi_squared_dist_table(5, .01)
15.09
>>> x = chi_squared_dist_table()
>>> sorted(x.keys()) # doctest: +ELLIPSIS
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ..., 100]

>>> k60 = chi_squared_dist_table(60)
>>> for p in sorted(k60.keys()): print({p: k60[p]})
{0.005: 91.95}
{0.01: 88.38}
{0.025: 83.3}
{0.05: 79.08}
{0.1: 74.4}
{0.5: 59.33}
{0.9: 46.46}
{0.95: 43.19}
{0.975: 40.48}
{0.99: 37.48}
{0.995: 35.53}

>>> chi_squared_dist_table(5, 0.4) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: If you provide a p value, it has to be one of 11 values...
>>> chi_squared_dist_table(95) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: If you are providing k and/or p values, they have to be chosen...

"""
chi_table = {
1: {
0.995: 0,
0.99: 0,
0.975: 0,
0.95: 0,
0.9: 0.02,
0.5: 0.45,
0.1: 2.71,
0.05: 3.84,
0.025: 5.02,
0.01: 6.63,
0.005: 7.88
},
2: {
0.995: 0.01,
0.99: 0.02,
0.975: 0.05,
0.95: 0.1,
0.9: 0.21,
0.5: 1.39,
0.1: 4.61,
0.05: 5.99,
0.025: 7.38,
0.01: 9.21,
0.005: 10.6
},
3: {
0.995: 0.07,
0.99: 0.11,
0.975: 0.22,
0.95: 0.35,
0.9: 0.58,
0.5: 2.37,
0.1: 6.25,
0.05: 7.81,
0.025: 9.35,
0.01: 11.34,
0.005: 12.84
},
4: {
0.995: 0.21,
0.99: 0.3,
0.975: 0.48,
0.95: 0.71,
0.9: 1.06,
0.5: 3.36,
0.1: 7.78,
0.05: 9.49,
0.025: 11.14,
0.01: 13.28,
0.005: 14.86
},
5: {
0.995: 0.41,
0.99: 0.55,
0.975: 0.83,
0.95: 1.15,
0.9: 1.61,
0.5: 4.35,
0.1: 9.24,
0.05: 11.07,
0.025: 12.83,
0.01: 15.09,
0.005: 16.75
},
6: {
0.995: 0.68,
0.99: 0.87,
0.975: 1.24,
0.95: 1.64,
0.9: 2.2,
0.5: 5.35,
0.1: 10.65,
0.05: 12.59,
0.025: 14.45,
0.01: 16.81,
0.005: 18.55
},
7: {
0.995: 0.99,
0.99: 1.25,
0.975: 1.69,
0.95: 2.17,
0.9: 2.83,
0.5: 6.35,
0.1: 12.02,
0.05: 14.07,
0.025: 16.01,
0.01: 18.48,
0.005: 20.28
},
8: {
0.995: 1.34,
0.99: 1.65,
0.975: 2.18,
0.95: 2.73,
0.9: 3.49,
0.5: 7.34,
0.1: 13.36,
0.05: 15.51,
0.025: 17.53,
0.01: 20.09,
0.005: 21.96
},
9: {
0.995: 1.73,
0.99: 2.09,
0.975: 2.7,
0.95: 3.33,
0.9: 4.17,
0.5: 8.34,
0.1: 14.68,
0.05: 16.92,
0.025: 19.02,
0.01: 21.67,
0.005: 23.59
},
10: {
0.995: 2.16,
0.99: 2.56,
0.975: 3.25,
0.95: 3.94,
0.9: 4.87,
0.5: 9.34,
0.1: 15.99,
0.05: 18.31,
0.025: 20.48,
0.01: 23.21,
0.005: 25.19
},
11: {
0.995: 2.6,
0.99: 3.05,
0.975: 3.82,
0.95: 4.57,
0.9: 5.58,
0.5: 10.34,
0.1: 17.28,
0.05: 19.68,
0.025: 21.92,
0.01: 24.72,
0.005: 26.76
},
12: {
0.995: 3.07,
0.99: 3.57,
0.975: 4.4,
0.95: 5.23,
0.9: 6.3,
0.5: 11.34,
0.1: 18.55,
0.05: 21.03,
0.025: 23.34,
0.01: 26.22,
0.005: 28.3
},
13: {
0.995: 3.57,
0.99: 4.11,
0.975: 5.01,
0.95: 5.89,
0.9: 7.04,
0.5: 12.34,
0.1: 19.81,
0.05: 22.36,
0.025: 24.74,
0.01: 27.69,
0.005: 29.82
},
14: {
0.995: 4.07,
0.99: 4.66,
0.975: 5.63,
0.95: 6.57,
0.9: 7.79,
0.5: 13.34,
0.1: 21.06,
0.05: 23.68,
0.025: 26.12,
0.01: 29.14,
0.005: 31.32
},
15: {
0.995: 4.6,
0.99: 5.23,
0.975: 6.27,
0.95: 7.26,
0.9: 8.55,
0.5: 14.34,
0.1: 22.31,
0.05: 25,
0.025: 27.49,
0.01: 30.58,
0.005: 32.8
},
16: {
0.995: 5.14,
0.99: 5.81,
0.975: 6.91,
0.95: 7.96,
0.9: 9.31,
0.5: 15.34,
0.1: 23.54,
0.05: 26.3,
0.025: 28.85,
0.01: 32,
0.005: 34.27
},
17: {
0.995: 5.7,
0.99: 6.41,
0.975: 7.56,
0.95: 8.67,
0.9: 10.09,
0.5: 16.34,
0.1: 24.77,
0.05: 27.59,
0.025: 30.19,
0.01: 33.41,
0.005: 35.72
},
18: {
0.995: 6.26,
0.99: 7.01,
0.975: 8.23,
0.95: 9.39,
0.9: 10.87,
0.5: 17.34,
0.1: 25.99,
0.05: 28.87,
0.025: 31.53,
0.01: 34.81,
0.005: 37.16
},
19: {
0.995: 6.84,
0.99: 7.63,
0.975: 8.91,
0.95: 10.12,
0.9: 11.65,
0.5: 18.34,
0.1: 27.2,
0.05: 30.14,
0.025: 32.85,
0.01: 36.19,
0.005: 38.58
},
20: {
0.995: 7.43,
0.99: 8.26,
0.975: 9.59,
0.95: 10.85,
0.9: 12.44,
0.5: 19.34,
0.1: 28.41,
0.05: 31.41,
0.025: 34.17,
0.01: 37.57,
0.005: 40
},
21: {
0.995: 8.03,
0.99: 8.9,
0.975: 10.28,
0.95: 11.59,
0.9: 13.24,
0.5: 20.34,
0.1: 29.62,
0.05: 32.67,
0.025: 35.48,
0.01: 38.93,
0.005: 41.4
},
22: {
0.995: 8.64,
0.99: 9.54,
0.975: 10.98,
0.95: 12.34,
0.9: 14.04,
0.5: 21.34,
0.1: 30.81,
0.05: 33.92,
0.025: 36.78,
0.01: 40.29,
0.005: 42.8
},
23: {
0.995: 9.26,
0.99: 10.2,
0.975: 11.69,
0.95: 13.09,
0.9: 14.85,
0.5: 22.34,
0.1: 32.01,
0.05: 35.17,
0.025: 38.08,
0.01: 41.64,
0.005: 44.18
},
24: {
0.995: 9.89,
0.99: 10.86,
0.975: 12.4,
0.95: 13.85,
0.9: 15.66,
0.5: 23.34,
0.1: 33.2,
0.05: 36.42,
0.025: 39.36,
0.01: 42.98,
0.005: 45.56
},
25: {
0.995: 10.52,
0.99: 11.52,
0.975: 13.12,
0.95: 14.61,
0.9: 16.47,
0.5: 24.34,
0.1: 34.28,
0.05: 37.65,
0.025: 40.65,
0.01: 44.31,
0.005: 46.93
},
26: {
0.995: 11.16,
0.99: 12.2,
0.975: 13.84,
0.95: 15.38,
0.9: 17.29,
0.5: 25.34,
0.1: 35.56,
0.05: 38.89,
0.025: 41.92,
0.01: 45.64,
0.005: 48.29
},
27: {
0.995: 11.81,
0.99: 12.88,
0.975: 14.57,
0.95: 16.15,
0.9: 18.11,
0.5: 26.34,
0.1: 36.74,
0.05: 40.11,
0.025: 43.19,
0.01: 46.96,
0.005: 49.65
},
28: {
0.995: 12.46,
0.99: 13.57,
0.975: 15.31,
0.95: 16.93,
0.9: 18.94,
0.5: 27.34,
0.1: 37.92,
0.05: 41.34,
0.025: 44.46,
0.01: 48.28,
0.005: 50.99
},
29: {
0.995: 13.12,
0.99: 14.26,
0.975: 16.05,
0.95: 17.71,
0.9: 19.77,
0.5: 28.34,
0.1: 39.09,
0.05: 42.56,
0.025: 45.72,
0.01: 49.59,
0.005: 52.34
},
30: {
0.995: 13.79,
0.99: 14.95,
0.975: 16.79,
0.95: 18.49,
0.9: 20.6,
0.5: 29.34,
0.1: 40.26,
0.05: 43.77,
0.025: 46.98,
0.01: 50.89,
0.005: 53.67
},
40: {
0.995: 20.71,
0.99: 22.16,
0.975: 24.43,
0.95: 26.51,
0.9: 29.05,
0.5: 39.34,
0.1: 51.81,
0.05: 55.76,
0.025: 59.34,
0.01: 63.69,
0.005: 66.77
},
50: {
0.995: 27.99,
0.99: 29.71,
0.975: 32.36,
0.95: 34.76,
0.9: 37.69,
0.5: 49.33,
0.1: 63.17,
0.05: 67.5,
0.025: 71.42,
0.01: 76.15,
0.005: 79.49
},
60: {
0.995: 35.53,
0.99: 37.48,
0.975: 40.48,
0.95: 43.19,
0.9: 46.46,
0.5: 59.33,
0.1: 74.4,
0.05: 79.08,
0.025: 83.3,
0.01: 88.38,
0.005: 91.95
},
70: {
0.995: 43.28,
0.99: 45.44,
0.975: 48.76,
0.95: 51.74,
0.9: 55.33,
0.5: 69.33,
0.1: 85.53,
0.05: 90.53,
0.025: 95.02,
0.01: 100.42,
0.005: 104.22
},
80: {
0.995: 51.17,
0.99: 53.54,
0.975: 57.15,
0.95: 60.39,
0.9: 64.28,
0.5: 79.33,
0.1: 96.58,
0.05: 101.88,
0.025: 106.63,
0.01: 112.33,
0.005: 116.32
},
90: {
0.995: 59.2,
0.99: 61.75,
0.975: 65.65,
0.95: 69.13,
0.9: 73.29,
0.5: 89.33,
0.1: 107.57,
0.05: 113.14,
0.025: 118.14,
0.01: 124.12,
0.005: 128.3
},
100: {
0.995: 67.33,
0.99: 70.06,
0.975: 74.22,
0.95: 77.93,
0.9: 82.36,
0.5: 99.33,
0.1: 118.5,
0.05: 124.34,
0.025: 129.56,
0.01: 135.81,
0.005: 140.17
}
}

krange = list(range(1, 30)) + list(range(30, 110, 10))
prange = [.005, .01, .025, .05, .1, .5, .9, .95, .975, .99, .995]

if k == 0 and p == 0:
return(chi_table)
elif k in krange:
if p != 0 and p in prange:
return(chi_table[k][p])
elif p == 0:
return(chi_table[k])
else:
raise ValueError("If you provide a p value, it has to be one of 11 "