卡方检验(两个类别变量是否独立)以及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

 

 

 

 

 

 

posted on 2020-12-16 17:46  小小喽啰  阅读(12826)  评论(0编辑  收藏  举报