卡方检验(两个类别变量是否独立)以及chi2_contingency
百度百科的解释:
卡方检验:
就是用来验证两个类别变量是否独立,还是相关
就是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,如果卡方值越大,二者偏差程度越大;反之,二者偏差越小;若两个值完全相等时,卡方值就为0,表明理论值完全符合。
例子:
男
|
女
|
||
化妆
|
15(55)
|
95(55)
|
110
|
不化妆
|
85(45)
|
5(45)
|
90
|
100
|
100
|
200
|
如果性别和化妆与否没有关系,四个格子应该是括号里的数(期望值,用极大似然估计55=100*110/200,其中110/200可理解为化妆的概率,乘以男人数100,得到男人化妆概率的似然估计),这和实际值(括号外的数)有差距,理论和实际的差距说明这不是随机的组合。
应用拟合度公式
=
129.3>10.828
显著相关,作此推论成立的概率p>0.999,即99.9%。
至于这个10.828,不重要,我们只需要看p值,p值需要查表。
python 卡方检验:
scipy.stats.chi2_contingency 列联表中变量独立性的卡方检验
chi2_contingency(observed, correction=True, lambda_=None)
参数:
observed:列联表,可有pd.crosstab,生成
correction :如果为True,并且自由度为1,则应用Yates校正以保持连续性。校正的效果是将每个观察值向相应的期望值调整0.5
lambda_ :float或str,可选。默认情况下,此测试中计算的统计量是Pearson的卡方统计量。 lambda_允许使用Cressie-Read功率散度族的统计量来代替。有关power_divergence详细信息,请参见 。
返回:
chi2:float,卡方值
p:float,p值
dof:int,自由程度
expected:ndarray,预期频率,基于表的边际总和
官网例子:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.chi2_contingency.html#r564
from scipy.stats import chi2_contingency obs = np.array([[10, 10, 20], [20, 20, 20]]) chi2_contingency(obs) ''' obs 输出: array([[10, 10, 20], [20, 20, 20]]) 卡方检验输出: (2.7777777777777777, 0.24935220877729622, 2, array([[12., 12., 16.], [18., 18., 24.]])) '''
我们也可以写函数处理
def chi_test(x, y): """皮尔逊卡方独立检验: 衡量特征的区分度 \n 参数: ----------- x: array-like, 一维,离散型特征变量 \n y: array-like,一维,另一个离散型特征变量。当 y 为目标变量时,此检验可以衡量特征区的分度 \n 返回值: ---------- chi_result: dict, 卡方检验结果, 其中: \n 键'Value'是卡方值, \n 键'Prob'是检验的 p 值,值越小, x 与 y 之间的关联性越强/ 区分度越大 \n 键'LLP'是 -log(Prob),值越大, x 与 y 之间的关联性越强 \n 键'DF'是卡方值的自由度. """ from scipy.stats import chi2_contingency tab = pd.crosstab(x, y).fillna(0) chi_value, p_value, def_free, _ = chi2_contingency(tab) return {'DF': def_free, 'Value': chi_value, 'Prob': p_value, 'LLP': -np.log(p_value)}
当类别型变量特别多的时候,我们需要写一个for循环去处理
#main_people是装有类别变量明细数据的表 chi_df_1 = pd.DataFrame(columns=['name1','name2','chi_value','chi_p','DF','LLP']) #首先创造一个空的表,用于下面的append使用 for i in range(2,17): #这个是类别变量位置 for j in range(i+1,17): #主要为了不重复计算 chi_df = pd.DataFrame() #临时存放数据,打工的 chi_df['name1'] = [list(main_people.columns)[i]] #记住要lis,不能是string chi_df['name2'] = [list(main_people.columns)[j]] chi_result = pc.chi_test(main_people.iloc[:,i].values,main_people.iloc[:,j].values) chi_df['chi_value'] = [chi_result['Value']] chi_df['chi_p'] = [chi_result['Prob']] chi_df['chi_DF'] = [chi_result['DF']] chi_df['chi_LLP'] = [chi_result['LLP']] chi_df_1 = chi_df_1.append(chi_df) chi_df_1