Gentle Introduction to Chi-Square Test for Independence | by Shinichi Okada | Towards Data Science

Table of contentsIntroduction 1. Prerequisite 2. SciPy package 3. Setup 4. Python indexing 5. chi2_contingency 6. Expected values 7. χ2 value 8. Side note about Latex 9. p-value10. Degree of freedom11. Importing data12. Pandas.DataFrame.transpose()13. Critical values14. The null and alternative hypothesesConclusion
The Chi-square test for independence is also called Pearson’s chi-square test. Chi-square test for independence is used in science, economics, marketing, or other various fields. There are three ways to use the Chi-square. The Chi-square test for independence shows how two sets of data are independent of each other. Chi-square of the Goodness-of-fit test shows how different your data to the expected value. The test for homogeneity determines if two or more populations have the same distribution of a single categorical variable.
In this article, we are going to explore the Chi-square test for independence with the Jupyter Notebook. Oh by the way we pronounce “Chi” as “kai” like “kite”, NOT “chi” in “Chili”. χ is a Greek letter for “Chi”, so χ2 reads Chi-square.
Even though this article is aimed at beginners who have little experience with coding, reading “Beginner’s Guide to Jupyter Notebook From” will help you how to get started.
towardsdatascience.com
In order to find Chi-square, we are going to use the SciPy package. SciPy is a Python-based open-source software for mathematics, science, and engineering. scipy.stats.chi2_contingency is a useful tool for the Chi-square test for independence. There is another one called scipy.stats.chisquare which is used for Chi-square of Goodness of fit test.
Start Anaconda and launch Jupyter Notebook.
Create a file by clicking New > Python 3.
Rename the file to “Chi-square test for independence”.
In the first cell, we are going to import chi2_contingency , pandas and numpy libraries.
from scipy.stats import chi2_contingencyimport pandas as pdimport numpy as np
When you run code in Jupyter Notebook, you press SHIFT + RETURN.
We are going to create sample data. Let’s say we collected data on the favorite color of T-shirts for men and women. We want to find out whether color and gender are independent or not. We create a small sample data using the Pandas dataframe and we will store our data in a variable called tshirts.
Pandas index and columns are used to name rows and columns. In order to print what's in our tshirts variable, we just write tshirts at the end and enter SHIFT + RETURN.
tshirts = pd.DataFrame(    [        [48,22,33,47],        [35,36,42,27]    ],    index=["Male","Female"],    columns=["Balck","White","Red","Blue"])tshirts
You can find what the labels in the columns are by using columns.
tshirts.columns
Similarly, you can use the index to find out what indexes are.
Python uses zero-based indexing. That means, the first element has an index 0, the second has index 1, and so on. If you want to access the fourth value in the chi2_contingency(tshirts) you need to use [3].
SciPy’s chi2_contingency() returns four values, χ2 value, p-value, degree of freedom and expected values.
chi2_contingency(tshirts)
You can find the expected values at the forth in the returned value. It is in an array form. Let’s print the expected values in a friendly way. We again use the Pandas dataframe. We are going to add index and column values and round the values to the two decimal places round(2).
df=chi2_contingency(tshirts)[3]pd.DataFrame(    data=df[:,:],     index=["Male","Female"],    columns=["Black","White","Red","Blue"]).round(2)
The above table is called a contingency table. You calculate the expected values from the observed data using the following equation.
You can find the χ2 value in the first returned value from chi2_contingency. But how do you find the χ2 manually? The formula for the Chi-square is:
The χ2 equation tells us to find the square of the difference between the actual value and expected value and divide it by the expected value. Then add all together to find the χ2 value.
This is what chi2_contingency is doing behind the scene. Since Python is 0 based index, in order to print the χ2 we need to use [0] which is the first value.
chisquare=chi2_contingency(tshirts)[0]chisquare
I used Latex, pronounce ‘lah-teck’ to write the above equation in Jupyter Notebook. The cell you are writing must be Markdown and this is what you need to type in the cell.
\begin{equation}\chi^2=\Sigma\frac{(O-E)^2}{E} \\\text{where O is the actual value and E is the expected value.}\end{equation}
You can find the p-value at the second in the returned value. p-value measures the probability of seeing the effect when the null hypothesis is true. So, when the p-value is low enough, we reject the null hypothesis and conclude the observed effect holds. We will talk about the null hypothesis later in this article.
https://www.machinelearningplus.com/statistics/p-value/
https://statisticsbyjim.com/hypothesis-testing/hypothesis-tests-significance-levels-alpha-p-values/
https://www.analyticsvidhya.com/blog/2015/09/hypothesis-testing-explained/
pvalue=chi2_contingency(tshirts)[1]pvalue
You can find the degree of freedom in the third returned value. We are going to use this to find the critical value later. The way you find the degree of freedom (dof) for χ2 for independence is different from χ2 Goodness of fit.
For χ2 for independence:
For example, if your data has 4 rows x 3 columns, then the degree of freedom is:
For χ2 Goodness of fit, the categorical data has one dimension. And the degrees of freedom is:
In the returned value from the chi2_contingency, the third one is the degree of freedom. We use [2] which is the third one. The following will output 3.
dof=chi2_contingency(tshirts)[2]dof
towardsdatascience.com
Generally, you want to import data from a file. The first CSV file has data horizontally. By using pd.read_csv the data automatically changed to a Pandas dataframe.
The CSV file has the following data.
gender,Black,White,Red,BlueMale,48,12,33,57Female,35,46,42,27
Let’s store the data to a variable called tshirtshor. We add index_col="gender" to make the gender column as the index.
csvfile = 'https://raw.githubusercontent.com/shinokada/python-for-ib-diploma-mathematics/master/Data/tshirts-horizontal.csv'tshirtshor = pd.read_csv(csvfile,index_col='gender')tshirtshor
We run chi2_contingency on the tshirtshor.
chi2_contingency(tshirtshor)
We are going to use vertically laid out data. Let’s store the data to a variable called tshirtsver.
csvfile2 = 'https://raw.githubusercontent.com/shinokada/python-for-ib-diploma-mathematics/master/Data/tshirts-vertical.csv'tshirtsver = pd.read_csv(csvfile2,index_col='Color')tshirtsver
We run chi2_contingency on the tshirtsver. We get the same values as before except the expected values.
chi2_contingency(tshirtsver)
If you prefer horizontal data to vertical data, you can transpose data from vertical to horizontal by using Pandas.DataFrame.transpose() or T for short.
tshirtsver.T
Using chi2_contingency().
chi2_contingency(tshirtsver.T)
towardsdatascience.com
The level of significance and degree of freedom can be used to find the critical value. As I mentioned before you can find the degree of freedom from the array. In order to find critical values, you need to import chi2 from scipy.state and define probability from the level of significance, 1%, 5% 10%, etc.
from scipy.stats import chi2significance = 0.01p = 1 - significancedof = chi2_contingency(tshirtshor)[2]critical_value = chi2.ppf(p, dof)critical_value
When the degree of freedom is 3 and at the 1% level of significance the critical value is about 11.34. You can confirm with this value using cdf. The following will output 0.99.
p = chi2.cdf(critical_value, dof)p
Chi-square test requires to state the null hypothesis, H0, and the alternative hypothesis, H1. The null hypothesis is the statement that our two variables are independent. The alternative hypothesis is the statement that they are not independent.
subjects = pd.DataFrame(    [        [25,46,15],        [15,44,15],        [10,10,20]    ],    index=['Biology','Chemistry','Physics'],    columns=['Math SL AA','Math SL AI','Math HL'])subjects
If the calculated Chi-square is greater than the critical value we reject the null hypothesis.
chi, pval, dof, exp = chi2_contingency(subjects)print('p-value is: ', pval)significance = 0.05p = 1 - significancecritical_value = chi2.ppf(p, dof)print('chi=%.6f, critical value=%.6f\n' % (chi, critical_value))if chi > critical_value:    print("""At %.2f level of significance, we reject the null hypotheses and accept H1. They are not independent.""" % (significance))else:    print("""At %.2f level of significance, we accept the null hypotheses. They are independent.""" % (significance))
Alternatively, we can compare the p-value and the level of significance. If p-value < the level of significance, we reject the null hypothesis.
chi, pval, dof, exp = chi2_contingency(subjects)significance = 0.05print('p-value=%.6f, significance=%.2f\n' % (pval, significance))if pval < significance:    print("""At %.2f level of significance, we reject the null hypotheses and accept H1. They are not independent.""" % (significance))else:    print("""At %.2f level of significance, we accept the null hypotheses. They are independent.""" % (significance))
In this article, I explained the basics of the Chi-square test using the Jupyter Notebook. The null and alternative hypotheses, expected values, Chi-square values, p-value, degree of freedom, and critical value are required for the Chi-square test for independence.
Get full access to every story on Medium by becoming a member.