Module stikpetP.tests.test_mod_log_likelihood_ind
Expand source code
import pandas as pd
from math import log
from scipy.stats import chi2
from ..other.table_cross import tab_cross
def ts_mod_log_likelihood_ind(field1, field2, categories1=None, categories2=None, cc=None):
'''
Mod-Log Likelihood Test of Independence
-------------------------------------------------
This test is similar as a Pearson Chi-Square test of independence, but approaches it from a likelihood-ratio approach (see Monica, 2015).
If the significance of this test is below 0.05 (or another pre-defined threshold), the two nominal variables have a significant association.
The test compares the observed counts of the cross table with the so-called expected counts. The expected values are the number of respondents you would expect if the two variables would be independent. See the Pearson Chi-Square test of independence for more details on expected counts.
One problem though is that the test should only be used if not too many cells have a so-called expected count, of less than 5, and the minimum expected count is at least 1. So you will also have to check first if these conditions are met. Most often ‘not too many cells’ is fixed at no more than 20% of the cells. This is often referred to as 'Cochran conditions', after Cochran (1954, p. 420). Note that for example Fisher (1925, p. 83) is more strict, and finds that all cells should have an expected count of at least 5 .
Parameters
----------
field1 : list or pandas series
the first categorical field
field2 : list or pandas series
the first categorical field
categories1 : list or dictionary, optional
order and/or selection for categories of field1
categories2 : list or dictionary, optional
order and/or selection for categories of field2
cc : {None, "yates", "pearson", "williams"}, optional
method for continuity correction
Returns
-------
A dataframe with:
* *n*, the sample size
* *n rows*, number of categories used in first field
* *n col.*, number of categories used in second field
* *statistic*, the test statistic (chi-square value)
* *df*, the degrees of freedom
* *p-value*, the significance (p-value)
* *min. exp.*, the minimum expected count
* *prop. exp. below 5*, proportion of cells with expected count less than 5
* *test*, description of the test used
Notes
-----
The formula used:
$$G=2\\times\\sum_{i=1}^{r}\\sum_{j=1}^c\\left(E_{i,j}\\times ln\\left(\\frac{E_{i,j}}{F_{i,j}}\\right)\\right)$$
$$df = \\left(r - 1\\right)\\times\\left(c - 1\\right)$$
$$sig. = 1 - \\chi^2\\left(G,df\\right)$$
With:
$$n = \\sum_{i=1}^r \\sum_{j=1}^c F_{i,j}$$
$$E_{i,j} = \\frac{R_i\\times C_j}{n}$$
$$R_i = \\sum_{j=1}^c F_{i,j}$$
$$C_j = \\sum_{i=1}^r F_{i,j}$$
Unclear what the original source is of the formula, but the one shown is taken from Cressie and Read (1984, p. 441).
The **Yates** correction uses \\(F_{i,j}'\\) instead of \\(F_{i,j}\\), defined as (Yates, 1934, p. 222):
$$F_{i,j}' = \\begin{cases} F_{i,j}-\\frac{1}{2} & \\text{ if } F_{i,j}> E_{i,j} \\\\ F_{i,j}+\\frac{1}{2} & \\text{ if } F_{i,j}< E_{i,j} \\\\ F_{i,j} & \\text{ if } F_{i,j}= E_{i,j} \\end{cases} $$
The **Williams** correction, adjusts the Pearson chi-square value:
$$\\chi_{wil}^2 = \\frac{G}{q}$$
With:
$$q = 1+\\frac{\\left(n\\times\\left(\\sum_{i=1}^r \\frac{1}{R_i}\\right) - 1\\right)\\times \\left(n\\times\\left(\\sum_{j=1}^c \\frac{1}{C_i}\\right) - 1\\right)}{6\\times n \\times\\left(r - 1\\right)\\times\\left(c - 1\\right)}$$
The formula is probably from Williams (1976, p. 36) but the one shown here is taken from McDonald (1976, p. 36).
The **Pearson** correction also adjusts the G value with (E.S. Pearson, 1947, p. 157):
$$\\chi_{epearson}^2 = \\frac{n - 1}{n}\\times G$$
References
----------
Cochran, W. G. (1954). Some methods for strengthening the common χ2 tests. *Biometrics, 10*(4), 417. doi:10.2307/3001616
Fisher, R. A. (1925). *Statistical methods for research workers*. Oliver and Boyd.
McDonald, J. H. (2014). *Handbook of biological statistics* (3rd ed.). Sparky House Publishing.
Monica, gung-R. (2015, April 2). Answer to “Why do my p-values differ between logistic regression output, chi-squared test, and the confidence interval for the OR?” Cross Validated. https://stats.stackexchange.com/a/144608
Pearson, E. S. (1947). The choice of statistical tests illustrated on the Interpretation of data classed in a 2 × 2 table. *Biometrika, 34*(1/2), 139–167. doi:10.2307/2332518
Williams, D. A. (1976). Improved likelihood ratio tests for complete contingency tables. *Biometrika, 63*(1), 33–37. doi:10.2307/2335081
Yates, F. (1934). Contingency tables involving small numbers and the chi square test. *Supplement to the Journal of the Royal Statistical Society, 1*(2), 217–235. doi:10.2307/2983604
Author
------
Made by P. Stikker
Companion website: https://PeterStatistics.com
YouTube channel: https://www.youtube.com/stikpet
Donations: https://www.patreon.com/bePatron?u=19398076
'''
testUsed = "Mod-Log Likelihood test of independence"
if cc == "yates":
testUsed = testUsed + ", with Yates continuity correction"
#create the cross table
ct = tab_cross(field1, field2, categories1, categories2, totals="include")
#basic counts
nrows = ct.shape[0] - 1
ncols = ct.shape[1] - 1
n = ct.iloc[nrows, ncols]
#determine the expected counts & chi-square value
chi2Val = 0
expMin = -1
nExpBelow5 = 0
expC = pd.DataFrame()
for i in range(0, nrows):
for j in range(0, ncols):
expC.at[i, j] = ct.iloc[nrows, j] * ct.iloc[i, ncols] / n
#add or remove a half in case Yates correction
if cc=="yates":
if ct.iloc[i,j] > expC.iloc[i,j]:
ct.iloc[i,j] = ct.iloc[i,j] - 0.5
elif ct.iloc[i,j] < expC.iloc[i,j]:
ct.iloc[i,j] = ct.iloc[i,j] + 0.5
chi2Val = chi2Val + expC.iloc[i, j]*log(expC.iloc[i, j]/ct.iloc[i, j])
#check if below 5
if expMin < 0 or expC.iloc[i,j] < expMin:
expMin = expC.iloc[i,j]
if expC.iloc[i,j] < 5:
nExpBelow5 = nExpBelow5 + 1
chi2Val= 2*chi2Val
nExpBelow5 = nExpBelow5/(nrows*ncols)
#Degrees of freedom
df = (nrows - 1)*(ncols - 1)
#Williams and Pearson correction
if cc == "williams":
testUsed = testUsed + ", with Williams continuity correction"
rTotInv = 0
for i in range(0, nrows):
rTotInv = rTotInv + 1 / ct.iloc[i, ncols]
cTotInv = 0
for j in range(0, ncols):
cTotInv = cTotInv + 1 / ct.iloc[nrows, j]
q = 1 + (n * rTotInv - 1) * (n * cTotInv - 1) / (6 * n * df)
chi2Val = chi2Val / q
elif cc == "pearson":
testUsed = testUsed + ", with E.S. Pearson continuity correction"
chi2Val = chi2Val * (n - 1) / n
#The test
pvalue = chi2.sf(chi2Val, df)
#Prepare the results
colNames = ["n", "n rows", "n col.", "statistic", "df", "p-value", "min. exp.", "prop. exp. below 5", "test"]
testResults = pd.DataFrame([[n, nrows, ncols, chi2Val, df, pvalue, expMin, nExpBelow5, testUsed]], columns=colNames)
pd.set_option('display.max_colwidth', None)
return testResults
Functions
def ts_mod_log_likelihood_ind(field1, field2, categories1=None, categories2=None, cc=None)-
Mod-Log Likelihood Test of Independence
This test is similar as a Pearson Chi-Square test of independence, but approaches it from a likelihood-ratio approach (see Monica, 2015).
If the significance of this test is below 0.05 (or another pre-defined threshold), the two nominal variables have a significant association.
The test compares the observed counts of the cross table with the so-called expected counts. The expected values are the number of respondents you would expect if the two variables would be independent. See the Pearson Chi-Square test of independence for more details on expected counts.
One problem though is that the test should only be used if not too many cells have a so-called expected count, of less than 5, and the minimum expected count is at least 1. So you will also have to check first if these conditions are met. Most often ‘not too many cells’ is fixed at no more than 20% of the cells. This is often referred to as 'Cochran conditions', after Cochran (1954, p. 420). Note that for example Fisher (1925, p. 83) is more strict, and finds that all cells should have an expected count of at least 5 .
Parameters
field1:listorpandas series- the first categorical field
field2:listorpandas series- the first categorical field
categories1:listordictionary, optional- order and/or selection for categories of field1
categories2:listordictionary, optional- order and/or selection for categories of field2
cc:{None, "yates", "pearson", "williams"}, optional- method for continuity correction
Returns
A dataframe with:
- n, the sample size
- n rows, number of categories used in first field
- n col., number of categories used in second field
- statistic, the test statistic (chi-square value)
- df, the degrees of freedom
- p-value, the significance (p-value)
- min. exp., the minimum expected count
- prop. exp. below 5, proportion of cells with expected count less than 5
- test, description of the test used
Notes
The formula used: G=2\times\sum_{i=1}^{r}\sum_{j=1}^c\left(E_{i,j}\times ln\left(\frac{E_{i,j}}{F_{i,j}}\right)\right) df = \left(r - 1\right)\times\left(c - 1\right) sig. = 1 - \chi^2\left(G,df\right)
With: n = \sum_{i=1}^r \sum_{j=1}^c F_{i,j} E_{i,j} = \frac{R_i\times C_j}{n} R_i = \sum_{j=1}^c F_{i,j} C_j = \sum_{i=1}^r F_{i,j}
Unclear what the original source is of the formula, but the one shown is taken from Cressie and Read (1984, p. 441).
The Yates correction uses F_{i,j}' instead of F_{i,j}, defined as (Yates, 1934, p. 222): F_{i,j}' = \begin{cases} F_{i,j}-\frac{1}{2} & \text{ if } F_{i,j}> E_{i,j} \\ F_{i,j}+\frac{1}{2} & \text{ if } F_{i,j}< E_{i,j} \\ F_{i,j} & \text{ if } F_{i,j}= E_{i,j} \end{cases}
The Williams correction, adjusts the Pearson chi-square value: \chi_{wil}^2 = \frac{G}{q}
With: q = 1+\frac{\left(n\times\left(\sum_{i=1}^r \frac{1}{R_i}\right) - 1\right)\times \left(n\times\left(\sum_{j=1}^c \frac{1}{C_i}\right) - 1\right)}{6\times n \times\left(r - 1\right)\times\left(c - 1\right)}
The formula is probably from Williams (1976, p. 36) but the one shown here is taken from McDonald (1976, p. 36).
The Pearson correction also adjusts the G value with (E.S. Pearson, 1947, p. 157): \chi_{epearson}^2 = \frac{n - 1}{n}\times G
References
Cochran, W. G. (1954). Some methods for strengthening the common χ2 tests. Biometrics, 10(4), 417. doi:10.2307/3001616
Fisher, R. A. (1925). Statistical methods for research workers. Oliver and Boyd.
McDonald, J. H. (2014). Handbook of biological statistics (3rd ed.). Sparky House Publishing.
Monica, gung-R. (2015, April 2). Answer to “Why do my p-values differ between logistic regression output, chi-squared test, and the confidence interval for the OR?” Cross Validated. https://stats.stackexchange.com/a/144608
Pearson, E. S. (1947). The choice of statistical tests illustrated on the Interpretation of data classed in a 2 × 2 table. Biometrika, 34(1/2), 139–167. doi:10.2307/2332518
Williams, D. A. (1976). Improved likelihood ratio tests for complete contingency tables. Biometrika, 63(1), 33–37. doi:10.2307/2335081
Yates, F. (1934). Contingency tables involving small numbers and the chi square test. Supplement to the Journal of the Royal Statistical Society, 1(2), 217–235. doi:10.2307/2983604
Author
Made by P. Stikker
Companion website: https://PeterStatistics.com
YouTube channel: https://www.youtube.com/stikpet
Donations: https://www.patreon.com/bePatron?u=19398076Expand source code
def ts_mod_log_likelihood_ind(field1, field2, categories1=None, categories2=None, cc=None): ''' Mod-Log Likelihood Test of Independence ------------------------------------------------- This test is similar as a Pearson Chi-Square test of independence, but approaches it from a likelihood-ratio approach (see Monica, 2015). If the significance of this test is below 0.05 (or another pre-defined threshold), the two nominal variables have a significant association. The test compares the observed counts of the cross table with the so-called expected counts. The expected values are the number of respondents you would expect if the two variables would be independent. See the Pearson Chi-Square test of independence for more details on expected counts. One problem though is that the test should only be used if not too many cells have a so-called expected count, of less than 5, and the minimum expected count is at least 1. So you will also have to check first if these conditions are met. Most often ‘not too many cells’ is fixed at no more than 20% of the cells. This is often referred to as 'Cochran conditions', after Cochran (1954, p. 420). Note that for example Fisher (1925, p. 83) is more strict, and finds that all cells should have an expected count of at least 5 . Parameters ---------- field1 : list or pandas series the first categorical field field2 : list or pandas series the first categorical field categories1 : list or dictionary, optional order and/or selection for categories of field1 categories2 : list or dictionary, optional order and/or selection for categories of field2 cc : {None, "yates", "pearson", "williams"}, optional method for continuity correction Returns ------- A dataframe with: * *n*, the sample size * *n rows*, number of categories used in first field * *n col.*, number of categories used in second field * *statistic*, the test statistic (chi-square value) * *df*, the degrees of freedom * *p-value*, the significance (p-value) * *min. exp.*, the minimum expected count * *prop. exp. below 5*, proportion of cells with expected count less than 5 * *test*, description of the test used Notes ----- The formula used: $$G=2\\times\\sum_{i=1}^{r}\\sum_{j=1}^c\\left(E_{i,j}\\times ln\\left(\\frac{E_{i,j}}{F_{i,j}}\\right)\\right)$$ $$df = \\left(r - 1\\right)\\times\\left(c - 1\\right)$$ $$sig. = 1 - \\chi^2\\left(G,df\\right)$$ With: $$n = \\sum_{i=1}^r \\sum_{j=1}^c F_{i,j}$$ $$E_{i,j} = \\frac{R_i\\times C_j}{n}$$ $$R_i = \\sum_{j=1}^c F_{i,j}$$ $$C_j = \\sum_{i=1}^r F_{i,j}$$ Unclear what the original source is of the formula, but the one shown is taken from Cressie and Read (1984, p. 441). The **Yates** correction uses \\(F_{i,j}'\\) instead of \\(F_{i,j}\\), defined as (Yates, 1934, p. 222): $$F_{i,j}' = \\begin{cases} F_{i,j}-\\frac{1}{2} & \\text{ if } F_{i,j}> E_{i,j} \\\\ F_{i,j}+\\frac{1}{2} & \\text{ if } F_{i,j}< E_{i,j} \\\\ F_{i,j} & \\text{ if } F_{i,j}= E_{i,j} \\end{cases} $$ The **Williams** correction, adjusts the Pearson chi-square value: $$\\chi_{wil}^2 = \\frac{G}{q}$$ With: $$q = 1+\\frac{\\left(n\\times\\left(\\sum_{i=1}^r \\frac{1}{R_i}\\right) - 1\\right)\\times \\left(n\\times\\left(\\sum_{j=1}^c \\frac{1}{C_i}\\right) - 1\\right)}{6\\times n \\times\\left(r - 1\\right)\\times\\left(c - 1\\right)}$$ The formula is probably from Williams (1976, p. 36) but the one shown here is taken from McDonald (1976, p. 36). The **Pearson** correction also adjusts the G value with (E.S. Pearson, 1947, p. 157): $$\\chi_{epearson}^2 = \\frac{n - 1}{n}\\times G$$ References ---------- Cochran, W. G. (1954). Some methods for strengthening the common χ2 tests. *Biometrics, 10*(4), 417. doi:10.2307/3001616 Fisher, R. A. (1925). *Statistical methods for research workers*. Oliver and Boyd. McDonald, J. H. (2014). *Handbook of biological statistics* (3rd ed.). Sparky House Publishing. Monica, gung-R. (2015, April 2). Answer to “Why do my p-values differ between logistic regression output, chi-squared test, and the confidence interval for the OR?” Cross Validated. https://stats.stackexchange.com/a/144608 Pearson, E. S. (1947). The choice of statistical tests illustrated on the Interpretation of data classed in a 2 × 2 table. *Biometrika, 34*(1/2), 139–167. doi:10.2307/2332518 Williams, D. A. (1976). Improved likelihood ratio tests for complete contingency tables. *Biometrika, 63*(1), 33–37. doi:10.2307/2335081 Yates, F. (1934). Contingency tables involving small numbers and the chi square test. *Supplement to the Journal of the Royal Statistical Society, 1*(2), 217–235. doi:10.2307/2983604 Author ------ Made by P. Stikker Companion website: https://PeterStatistics.com YouTube channel: https://www.youtube.com/stikpet Donations: https://www.patreon.com/bePatron?u=19398076 ''' testUsed = "Mod-Log Likelihood test of independence" if cc == "yates": testUsed = testUsed + ", with Yates continuity correction" #create the cross table ct = tab_cross(field1, field2, categories1, categories2, totals="include") #basic counts nrows = ct.shape[0] - 1 ncols = ct.shape[1] - 1 n = ct.iloc[nrows, ncols] #determine the expected counts & chi-square value chi2Val = 0 expMin = -1 nExpBelow5 = 0 expC = pd.DataFrame() for i in range(0, nrows): for j in range(0, ncols): expC.at[i, j] = ct.iloc[nrows, j] * ct.iloc[i, ncols] / n #add or remove a half in case Yates correction if cc=="yates": if ct.iloc[i,j] > expC.iloc[i,j]: ct.iloc[i,j] = ct.iloc[i,j] - 0.5 elif ct.iloc[i,j] < expC.iloc[i,j]: ct.iloc[i,j] = ct.iloc[i,j] + 0.5 chi2Val = chi2Val + expC.iloc[i, j]*log(expC.iloc[i, j]/ct.iloc[i, j]) #check if below 5 if expMin < 0 or expC.iloc[i,j] < expMin: expMin = expC.iloc[i,j] if expC.iloc[i,j] < 5: nExpBelow5 = nExpBelow5 + 1 chi2Val= 2*chi2Val nExpBelow5 = nExpBelow5/(nrows*ncols) #Degrees of freedom df = (nrows - 1)*(ncols - 1) #Williams and Pearson correction if cc == "williams": testUsed = testUsed + ", with Williams continuity correction" rTotInv = 0 for i in range(0, nrows): rTotInv = rTotInv + 1 / ct.iloc[i, ncols] cTotInv = 0 for j in range(0, ncols): cTotInv = cTotInv + 1 / ct.iloc[nrows, j] q = 1 + (n * rTotInv - 1) * (n * cTotInv - 1) / (6 * n * df) chi2Val = chi2Val / q elif cc == "pearson": testUsed = testUsed + ", with E.S. Pearson continuity correction" chi2Val = chi2Val * (n - 1) / n #The test pvalue = chi2.sf(chi2Val, df) #Prepare the results colNames = ["n", "n rows", "n col.", "statistic", "df", "p-value", "min. exp.", "prop. exp. below 5", "test"] testResults = pd.DataFrame([[n, nrows, ncols, chi2Val, df, pvalue, expMin, nExpBelow5, testUsed]], columns=colNames) pd.set_option('display.max_colwidth', None) return testResults