【假设检验之卡方检验】

您所在的位置:网站首页 差异显著性检验怎么判断 【假设检验之卡方检验】

【假设检验之卡方检验】

2023-03-27 13:06| 来源: 网络整理| 查看: 265

假设检验系列文章

1、假设检验与中心极限定理

2、假设检验之t检验、f检验

前两章主要讲了假设检验背后的原理和思想,以及常见的t检验和f检验,本章主要讲另外一种假设检验,卡方检验。

卡方检验的基本原理:统计样本的实际观测值与理论推断值之间的偏离程度,通过偏离程度来判断两组数据在构成上是否存在差异。卡方检验主要是针对类别变量。

在具体讲解卡方检验前,有几个概念我们需要先熟悉了解。

类别变量,也可以叫分类变量,特点是可以全部列出来的。比如性别,男性或女性;

期望频次,在理想情况下,对应类的数量,比如某个地区男女比例是6:4,那100人中,男女期望频次就是60:40

实际频次,即在实际抽样中统计对应类的数量,比如随机抽100人,实际上男女数量分别是48、52

了解这些基本概念后,我们就可以进入主题。常见的卡方检验的有两种,卡方拟合优度检验卡方独立性检验,下面结合案例,通过代码讲解两种卡方检验的区别。

卡方拟合优度检验

适用于1个类别变量的检验,从实际出发,一般检验我们所观察到的类别构成比例与理论上是否存在差异,卡方指的是统计量,用 \chi 表示,拟合优度指的是跟理论情况的差距大小,合起来理解便是,卡方值越大,跟理论差距就越大,就越能说明观察到的结果与理论上存在差异。

那么多大的差距才算大呢,这就回到了我们之前讲解t检验的流程。同理的,我们需要构建一个与理论情况无差异的卡方值分布,然后算出卡方分布的临界值,如果实际观察所统计的卡方值大于临界值,则说明两者存在差异,这就是卡方拟合优度检验。而卡方值的计算公式为

\chi^{2}=\sum_{i}^{n}{\frac{(O_{i}-E_{i})^{2}}{E_{i}}}

公式讲解: O_{i} 代表类别变量中每一类所观察到的频次, E_{i} 代表对应该类在理论情况上的频次,以上面男女比例案例为例,卡方值\chi^{2}=\sum_{i}^{n}{\frac{(O_{i}-E_{i})^{2}}{E_{i}}}= \frac{(48-60)^{2}}{60} + \frac{(52-40)^{2}}{40} =6

下面通过一个案例来阐述说明(以下案例纯属个人编造);

某个游戏活动抽盲盒,称抽到特等奖概率是5%,一等奖概率是10%,二等奖概率是20%,三等奖概率30%,四等奖概率是35%,现在该活动奖品数有10000份,小明很喜欢特等奖,于是他花了一大笔钱抽了100份,结果是特等奖0份,一等奖15份,二等奖23份,三等奖29份,四等奖33份,小明觉得活动说的特等奖概率5%肯定是骗人的,那么通过卡方拟合优度检验怎么帮助他证明呢?

根据情况,我们可以做出如下假设:

H0:活动奖品的中奖比例跟主办方公布的是一样的

H1:活动奖品的中奖比例跟主办方分布的不一样的

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #先生成一个奖品清单 a=['特等奖']*500 b=['一等奖']*1000 c=['二等奖']*2000 d=['三等奖']*3000 e=['四等奖']*3500 data=a+b+c+d+e data=pd.Series(data) #生成抽取100份的期望频次,打印出来看下 data_E=data.value_counts(ascending=True)*0.01#对奖品做重复1万次抽样,每次抽取100份奖品并记录不同奖项的频次 chi_square=[] #创建卡方列表,用于储存每次抽样得到的卡方值 for i in range(10000): sample=data.sample(100) sample=sample.value_counts() sample=(sample-data_E)**2/data_E chi_square.append(sample.sum()) sns.distplot(chi_square)

如上图所示,其卡方值分布情况呈现一种偏态分布,有点类似我们上一篇讲到的f分布,但本质上是有区别的,卡方分布最小值为0,如果卡方值越小,代表其实际频越接近期望频次,即样本越不极端,所以,拒绝域只在右边,卡方值越靠近右边,代表其实际频次与期望频次差距越大,越有可能拒绝H0。

#生成小明花钱买了100份奖品的清单 test_b=['一等奖']*15 test_c=['二等奖']*23 test_d=['三等奖']*29 test_e=['四等奖']*33 test=test_b+test_c+test_d+test_e test=pd.Series(test).value_counts() test.loc['特等奖'] = 0 #需要把特等奖加入,要不然后面计算为忽略这一项 test_chi_square=(test-data_E)**2/data_E #这就是pandas的强大之处,根据索引做一一相减,不需要考虑实际批次的数据和期望频次的数据是完全对应 #算出卡方统计值 test_value=test_chi_square.sum() #算下P值 chi_square=pd.Series(chi_square) chi_square[chi_square>test_value].count()/10000 结果: 8.097619047619048 P值0.0805

P值大于0.05,不能拒绝原假设,所以小明抽100份没拿到特等奖,也是比较正常的,当然了从概率上看,0.0808已经很接近0.05了,如果我们显著性水平用0.1的话,P值小于0.1,就可以做出拒绝原假设,接受备注假设的判断。

#我们用python的卡方函数,直接验证下数据是不是一样的 stats.chisquare([0,15,23,29,33],[5,10,20,30,35]) 第一个列表传入实际频次数据,第二个列表传入期望频次 结果: Power_divergenceResult(statistic=8.097619047619048, pvalue=0.08806703032900631)

算出来的统计值跟我们通过卡方公式算出来的一致,算出来的P值也大致相同。

卡方独立性检验

适用于两个类别变量的检验,主要是验证两个类别变量间是否存在关系,比如性别与购物直接是否有关系(是否有偏好)、不同地区与瓷砖的选择是否有关系(是否有偏好)、不同职业与不同口味咖啡是否有关系(是否有偏好)等。

思路还是一样,主要是把卡方分布算出来,然后再计算观测数据的卡方值,做对比即可。为了计算卡方值,这里需要用到一种称为列联表的表格来进行分析。

什么是列联表呢,你可以这样理解下,就是两个类别变量分别放在行或列上,然后统计对应行列的值,很常见的就是excel里的数据透视,把一个类别变量拉到行,把另一个类别变量拉到列,然后统计值,这样的表就是列联表。

下面还是举例子来说明,本例子出自CSDN社区(作者:易烊千玺铁粉,若侵权请联系我删除)

以上就是一个很标准的列联表,下面的合计叫做列总计,右边的合计叫做行总计。

为了更清晰了解如何通过列联表分析计算出卡方值,这里先用excel做演示

如上,本次调查职工共500人,其中IT330人,行政125人,工程45人。我们先计算下每个职业,购买不同口味的咖啡占比情况,从数据可知,IT行业职工中,购买卡布奇诺的占比达67.6%,跟工程和行政有很大区别。

问题来了,是不是这样就能说明不同职业对不同口味的咖啡存在偏好呢?

还不一定,因为我们这次抽查是随机的,不排除我们这次抽查到是特例,实际情况是职业对不同口味咖啡有一样的偏好,对吧,那怎么去排除这种可能呢,答案就是假设检验。

我们先假设总体中不同职业对不同口味的咖啡有一样的偏好,注意注意!!!重点来了!!!

有一样的偏好是什么意思,是指不同职业对不同口味的咖啡的偏爱都一样吗?如下图,那就大错特错了。这只是其中的一种特殊情况而已。

以下才是不同职业对不同口味的咖啡有一样的偏好,即不同职业在选择不同口味的占比表现是一致的。

好的继续,我们知道如果要进行假设检验,就要根据理论统计值构建一个分布,然后通过计算调查数据的统计值,与理论值对比,并做出拒绝或接受的判断。

回到我们最初的问题,我们觉得实际情况是不同职业对不同口味的咖啡有着一样的偏好,那我们就依此做出假设

H0:不同职业,对不同口味的咖啡有一样的偏好

那这个偏好具体怎么算呢,很简单,直接忽略不同职业这个因素,计算每一种口味的咖啡人数,不同种咖啡的人数比就是总体的偏好。不好理解是吧,换个思路想想。

我们现在是假设不同职业对不同口味的咖啡有一样的偏好,对吧,从里面从500个职工做调查,我们不就是怀疑抽取的时候,某个职业抽多了,某个职业少抽了,导致算出来的占比是不具备代表性的吗,对吧,但是不管是哪个职业的,都是来自这个总体吧,我们把职业这个因素去掉,那抽到喜欢不同口味咖啡的人,是不是应该跟总体是一样的呢?

所以,不同口味咖啡的占比情况,就是对应咖啡的人数比,即

美式:拿铁:卡布奇诺=56:200:244

好了,有了不同口味咖啡的占比,我们就可以算出随机抽500名职工,其理论上购买不同咖啡的分布情况。

以IT,美式咖啡为例,抽取样本中有330名IT员工,因为偏好美式咖啡比例是11.2%,所以理论上330名IT员工里,就有330*11.2%≈37名员工,喜欢美式咖啡。以此类推,计算其他数据。用数据公式概括下:

期望频次 E_{ij}=\frac{行总计*列总计}{样本量}=\frac{O_{i}*O_{j}}{N}

其中 O_{i} 代表i职业的列总计, O_{j} 代表j口味咖啡的行总计,N代表样本量

期望频次和观测频次都有了,接下来就是计算两者的差距,回想下前面说的卡方拟合优度检验,即

\chi^{2}=\sum_{i}^{n}{\frac{(O_{i}-E_{i})^{2}}{E_{i}}} ,算出来卡方值等于138.2

因为excel没办法演示抽样情况,我们可以去查卡方分布表,按显著性水平0.05,自由度=(3-1)*(3-1)=4,去查临界值是9.49,计算卡方值远远大于临界值,所以拒绝原假设,接受备择假设,不同职业对不同口味咖啡有不同偏好。

当然excel里也有计算卡方检验的函数,计算临界值函数CHISQ.INV.RT(显著性水平,自由度),算出来是9.487729,跟我们查表的基本一致。

下面我们通过python模拟,先搭建一个卡方分布,然后就做卡方检验。

#我们先把期望频次导入 data=pd.read_excel(r'C:\Users\83687\Desktop\test.xlsx')

我们需要用这个期望频次,来搭建一个总体,将这个数据乘以20倍,我们就可以得到一个有10000的总体,这样的总体就可以代表H0,然后我们从这个总体中每次抽样500个职工,统计对应的卡方值,重复操作10000次,这样就可以得到一个卡方值分布。

#先构建一个总体 total=(data.set_index('口味')).reset_index() total=pd.melt(total,id_vars='口味',var_name='职业',value_name='用户数') Total=pd.DataFrame() for i in range(len(total)): a=total.loc[i] b=pd.DataFrame(a).T Total=Total.append([b]*total['用户数'][i]*20) Total['用户数']=1 #构建卡方分布 chi=[] for i in range(10000): sample=Total.sample(500) sample=pd.pivot_table(sample,index='口味',columns='职业',values='用户数',aggfunc=np.sum) value=((sample-data.set_index('口味'))**2/data.set_index('口味')).sum().sum() chi.append(value) chi=pd.Series(chi) sns.distplot(chi)

如上图,我们通过抽样也构建了一个卡方分布,我们上面通过excel函数算出来随机抽500职工的卡方值是138.2,当然也可以通过python再求一遍

#读取抽样分布数据 test=pd.read_excel(r'C:\Users\83687\Desktop\test.xlsx') ((test.set_index('口味')-data.set_index('口味'))**2/data.set_index('口味')).sum().sum() 结果:138.4201471766404 #跟excel算出来的结果差不多,主要是因为excel理论分布是小数,我导入python用的是整数

然后通过数据,我们很明显能看出138.4在坐标轴右边,属于拒绝域内,所以可以拒绝原假设,接受【不同职业对不同口味的咖啡有不同偏好】的假设。当然,我们可以直接通过python自带的卡方检验函数计算。

observed=np.array(test.set_index('口味')) #将抽样数据转为二维数组 from scipy.stats import chi2_contingency statistic, p_value, dof, expected = chi2_contingency(observed) print('卡方检验统计量为:', statistic) print('p值为:', p_value) print('自由度为:', dof) print('期望频数为:\n', expected)

计算的结果也和excel算出来的一样,包括理论频次的分布。

总算讲完了,还是一样,在敲代码和结合理论分析的过程中,还是会遇到疑难点,有大神路过的也可以帮忙解答下。

通过随机抽样的分布,实际上应该不符合自由度是(n-1)*(m-1)的分布,因为如果你根据自由度是4,显著性水平为.05去查表,我们发现临界值是9.49,但是我们可以对抽样得到的卡方分布,看大于9.49的样本量。

chi[chi>9.49].count() #结果是2637,P值远远大于0.05

一开始我以为是因为抽样的误差所带来的,因此试过几次随机,但是结果都差不多,所以后面觉得,通过上述方式的抽样得到的卡方分布,严格意义上是不符合自由度是(n-1)*(m-1)的分布,某种程度上来说,我们可以把它看成是一个拟合优度检验,变量是职业&口味,共有9种组合,自由度为8,按照这个去查卡方分布表,得到的临界值是15.507。

chi[chi>15.507].count() #结果是392,P值为0.0392,很接近0.05

所以,不知道我这样理解对不对呢,哈哈哈哈。

写到最后:

太不容易了,终于把假设检验三部曲写完了,感觉学会是一回事,自己拿出来分享又是一回事,有些东西你学会了,但实际上不一定能理解,当你要分享的时候,你会把整个逻辑都梳理一遍,代码敲一遍,然后就会发现其实你之前的理解还是不够透彻,学习之路漫漫啊。

最后,其实实际业务分析中,用假设检验的不算多,可能在ABtest上用到会相对多的,其他地方如建模,其实更多的是模型有自己的评估体系,不需要通过假设检验来判断测试前后的数据是否来自一个总体等。但是呢,个人觉得,假设检验真的挺有意思的,哈哈哈,也可能正是因为有意思,才愿意把它写下来分享给大家吧。

共勉~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3