如果我们想确定两个独立分类数据组的统计显着性,会发生什么?这是卡方检验独立性有用的地方。
Chi-Square检验
我们将在1994年查看人口普查数据。具体来说,我们对“性别和“每周工作时间”之间的关系感兴趣。在我们的案例中,每个人只能有一个“性别”,且只有一个工作时间类别。为了这个例子,我们将使用pandas将数字列'每周小时'转换为一个分类列。然后我们将'sex'和'hours_per_week_categories'分配给新的数据帧。
代码语言:javascript复制# -*- coding: utf-8 -*-
"""
Created on Sun Feb 3 19:24:55 2019
@author: czh
"""
# In[*]
import matplotlib.pyplot as plt
import numpy as np
import math
import seaborn as sns
import pandas as pd
%matplotlib inline
import os
os.chdir('D:\train')
# In[*]
cols = ['age', 'workclass', 'fnlwg', 'education', 'education-num',
'marital-status','occupation','relationship', 'race','sex',
'capital-gain', 'capital-loss', 'hours-per-week', 'native-country', 'income']
data = pd.read_csv('census.csv', names=cols,sep=', ')
# In[*]
#Create a column for work hour categories.
def process_hours(df):
cut_points = [0,9,19,29,39,49,1000]
label_names = ["0-9","10-19","20-29","30-39","40-49","50 "]
df["hours_per_week_categories"] = pd.cut(df["hours-per-week"],
cut_points,labels=label_names)
return df
# In[*]
data = process_hours(data)
workhour_by_sex = data[['sex', 'hours_per_week_categories']]
workhour_by_sex.head()
代码语言:javascript复制 sex hours_per_week_categories
0 Male 40-49
1 Male 10-19
2 Male 40-49
3 Male 40-49
4 Female 40-49
查看
代码语言:javascript复制workhour_by_sex['sex'].value_counts()
Out[31]:
Male 21790
Female 10771
Name: sex, dtype: int64
代码语言:javascript复制workhour_by_sex['hours_per_week_categories'].value_counts()
Out[33]:
40-49 18336
50 6462
30-39 3667
20-29 2392
10-19 1246
0-9 458
Name: hours_per_week_categories, dtype: int64
- 原假设 回想一下,我们有兴趣知道'sex'和'hours_per_week_categories'之间是否存在关系。 为此,我们必须使用卡方检验。 但首先,让我们陈述我们的零假设和另类假设。
H0:性别与每周工作小时数没有统计学上的显着关系.H0:性别与每周工作小时数之间没有统计学上的显着关系。 H1:性别和每周工作小时数之间存在统计学上的显着关系.
下一步是将数据格式化为频率计数表。 这称为列联表,我们可以通过在pandas中使用pd.crosstab()函数来实现。
代码语言:javascript复制contingency_table = pd.crosstab(
workhour_by_sex['sex'],
workhour_by_sex['hours_per_week_categories'],
margins = True
)
contingency_table
Out[34]:
hours_per_week_categories 0-9 10-19 20-29 30-39 40-49 50 All
sex
Female 235 671 1287 1914 5636 1028 10771
Male 223 575 1105 1753 12700 5434 21790
All 6462 1246 18336 3667 458 2392 32561
该表中的每个单元表示频率计数。 例如,表格中“男性”行和“10 -19”列的交集将表示从我们的样本数据集中每周工作10-19小时的男性人数。 “全部”行和“50 ”列的交叉点表示每周工作50小时以上的人员总数。
代码语言:javascript复制# In[*]
#Assigns the frequency values
malecount = contingency_table.iloc[0][0:6].values
femalecount = contingency_table.iloc[1][0:6].values
#Plots the bar chart
fig = plt.figure(figsize=(10, 5))
sns.set(font_scale=1.8)
categories = ["0-9","10-19","20-29","30-39","40-49","50 "]
p1 = plt.bar(categories, malecount, 0.55, color='#d62728')
p2 = plt.bar(categories, femalecount, 0.55, bottom=malecount)
plt.legend((p2[0], p1[0]), ('Male', 'Female'))
plt.xlabel('Hours per Week Worked')
plt.ylabel('Count')
plt.show()
image.png
上图显示了人口普查中的样本数据。如果性别与每周工作小时数之间确实没有关系。然后,数据将显示每个时间类别的“男性”和“女性”之间的均匀比率。例如,如果5%的女性工作50 小时,我们预计工作50小时以上的男性的百分比相同。
使用Scipy进行卡方检验
现在我们已经完成了所有计算,现在是时候寻找捷径了。
代码语言:javascript复制f_obs = np.array([contingency_table.iloc[0][0:6].values,
contingency_table.iloc[1][0:6].values])
f_obs
from scipy import stats
stats.chi2_contingency(f_obs)[0:3]
Out[38]: (2287.190943926107, 0.0, 5)
p值= ~0,自由度= 5。
结论
如果p值<0.05,我们可以拒绝零假设。 “性别”和“每周工作时间”之间肯定存在某种关系。 我们不知道这种关系是什么,但我们知道这两个变量并不是彼此独立的。