扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
为什么要叫“卡方”?因为原名是“chi-squared”,一半是音译,一半是意译。其中,chi 是希腊字母 的读音,其实读音更像是“开”,而不是“卡”。square表示平方,因此在英语中,卡方分布写作 distribution。
创新互联建站主营会泽网站建设的网络公司,主营网站建设方案,手机APP定制开发,会泽h5成都微信小程序搭建,会泽网站营销推广欢迎会泽等地区企业咨询
在理解卡方检验之前,应当理解卡方分布。卡方分布是一种连续概率分布。
如果一个随机变量 服从标准正态分布,即 ,那么 就服从自由度为1的卡方分布。记作 或者
而如果 都服从标准正态分布,那么它们的平方和服从自由度为 的卡方分布,记作:
或者写作 。
对于非负自变量 的自由度为 的卡方分布的概率密度函数 (简称"pdf"):
(1)为什么 非负?因为根据定义,卡方分布的自变量是一个平方和。
(2)这里的 是一个函数。关于这个函数具体是什么,以及上门的概率密度函数如何推导,这里不展开,只需要知道有这么个函数即可。实在是好奇的,可以 参考这里 。
(3)卡方分布的均值为 ,而标准差为 。
(4)自由度越大,该函数图像越对称。
(5)为什么这里 需要正态分布,我的理解是,如果零假设为真,那么观测值和期望值之间的波动程度,应该是正态分布的,或者说“噪声”应该是正态分布的。
卡方检验有两个用途:
拟合优度检验 chi-squared test goodness of fit
独立性检验 chi-squared test of independence
某新闻说某个篮球明星的原地两连投的单次命中率是0.8,根据历次比赛的数据汇总得到下面的表格:
意思是说,在比赛中,有5次两连投是一次都没中,有82次是在两连投中命中1次。现在,我们来用卡方检验验证新闻说的0.8的命中率是否正确。零假设如下:
:两连投的成功次数符合二项分布,且概率为
(1)先根据零假设计算“期望”的命中次数分布:
由于总的观察次数为 ,于是在 成立的前提下,可以计算每种两连投结果的期望次数:
0次命中:
1次命中:
2次命中:
显然,期望的观察次数和实际的观察次数是有偏差的,那么问题在于这个偏差是否大到具有统计显著性,进而可以否定零假设。
(2)我们来构造卡方检验统计量(chi-squared test statistic):
这个值是把表里每个格子的实际值和期望值进行对比。为什么要用平方?目的在于规避正负号的影响。为什么要除以期望值?目的在于消除数量绝对值的影响。例如你预算3块钱的水,商家加价50元,那么这个波动是你无法忍受的,而你预算20万的车,商家加价50元,则变得可以忍受。也就是说,除以期望值目的在于聚焦于变化率,而不是变化量。
之后,把这些“变化率”加总得到 。而计算自由度有一个公式:
其中 R 表示行数,C 表示列数。对于本例:
从另一个角度解释为什么 :前面的定义是如果是 个符合标准正态分布的 相加,则自由度是 ,但是这里自有两个格子可以自由变化,第三个格子可以用总观察数减出来,例如 。
因此,真正自由的只有2个格子,所以自由度是2。
好了,将格子的数据代入,求出检验统计量:
(3)根据自由度为2的卡方分布,找到检验统计量对应的位置:
不难理解,随着统计量增大,表示预期的分布和实际的分布的差异也就越来越大。
另外,由于通常意义上,p值是越小越能推翻零假设,那么显然我们需要用右侧的面积来表示p值,这里用Python计算来代替查表:
输出:statistic: 17.26, pvalue: 0.0002
由于p值很小(假设我们的显著性水平的0.05),那么我们可以推翻零假设。
进一步的,我们来探索下,该运动员的两连投的成功次数分数是否真的符合二项分布。零假设:
:两连投的成功次数符合二项分布。
既然符合二项分布,那么我们需要先估算一下最合理的 概率,那当然是用总命中数除以总投篮数来计算了:
然后,用该概率值重复之前的计算,也就是先计算出一个期望的表格:
注意,这里的 ,这是因为,我们每从数据估计一个参数,那么我们就损失一个自由度。这里用了一个平均命中的概率,因此自由度只有 。
这时候,在使用 Python 进行计算时,注意调整默认的自由度:
这里的 ddof 就是额外损失的自由度,本意是“delta degree of freedom”
输出:statistic: 0.34, pvalue: 0.56
可以看到p值很大,因此不足以推翻零假设,也就是说该运动员的投篮命中次数可能真的是二项分布。
下面表格表示喝酒频率和与警察发生麻烦的频数。
以第一列为例,表示从不喝酒的人中,4992人不发生麻烦,71人会发生麻烦。
现在的问题是,能否从以下数据推断说喝酒频率和与警察发生麻烦这两个事件相互独立?
我们的零假设应该如何设计?如果要说明两者相互独立,那么上表的分布应该满足乘法公式。也就是说两个独立事件一起发生的概率等于分别发生的概率之积。
于是我们有:
发生麻烦的总人数除以总人数
不喝酒的总人数除以总人数
进一步,根据总人数算出不喝酒而发生麻烦的人数的期望(下标表示零假设):
用类似的算法,计算每一个格子在零假设成立的情况下的值,写在原表数据下的括号里:
仔细观察可以看出,其实每个格子就是对应的:
另外可以看到,零假设下的各个格子的行列之和与原来相同。这不是偶然的,我们用字母代替计算一下就知道了:
于是第一列的两个格子应该是:
对于其他格子、行的总和,都一样,这里不多说了。
好,继续分析。我们直接用上表计算卡方统计量和p值:
这部分计算方法和拟合优度是一样的,就不赘述了。计算发现这个p值非常小,接近0,因此我们可以推翻零假设。也就是说,喝酒的频率和被警察找麻烦的并不是独立的,而是相关的。
关于独立性检验,有一个比卡方检验更精准的检验,叫 fisher's exact test。它通过直接计算否定零假设的概率,也就直接得到了一个准确的p值。有一个经典的女士品茶的统计学故事。有一个女士号称可以区分出一杯茶是先倒入了奶还是先倒入了茶。统计学家 Fisher 为了验证她的说法,做了一个实验。拿了8杯茶,4杯是先茶后奶,4杯是先奶后茶。
实验结果是全部说对了。那么问题是,这是否具有统计显著性呢?比如说一个人猜对了一次硬币,他的预测能力靠谱吗?
我们假设女士的判断是完全随机的,这个是我们的零假设。那么8杯里面抽中4杯全对的概率是:
如果显著性水平是0.01,那么我们不能推翻零假设,即不敢确定这位女士真有这个识别能力。如果显著性水平定在0.05,则我们可以认为她确实有这个识别能力。
如果让实验结果有更大的说服力呢?一个简单的办法就是增加茶的数量,比如我们设定为两种茶各10杯,要求10杯都判断正确,那么p值为多少呢?
这个算起来比较麻烦,这里我写一个 python 脚本来计算:
计算结果:
这个p值就小得很夸张了,基本可以断定零假设不成立了。
那么,回到实验本身,如果女士只选对了三杯,那么在零假设的前提下,这个发生的概率是多少?
这个概率比较大了,原大于通常使用的显著性水平 0.05,因此我们没有办法推翻零假设。为什么要这样 乘 呢?这个是因为一共有这么多种取法。你把所有可能的取法罗列处理,就是16种,然后除以总的取法数,就是随机取到这样结果的概率。
比较 Fisher's exact test 和 chi-squared test,可以 参考这篇文章 。
一般来说,两者都适用的情况下,应该优先选择 Fisher's exact test,因为它是精确值。如果实验观察的数量很小(小于10),应该不使用 chi-squared test。
下面使用一个脚本来计算:
1、python中使用pow函数求n的n方根。首先打开python的编辑器,新建一个python 3的文件:
2、pow函数的用法很简单,只要传入待开方的数,以及要开几次方就可以了。比如演示里是3开3次方:
3、然后需要编译运行,点击菜单栏上run下面的run命令,执行编译运行:
4、在下方的结果中即可看到运算的结果尾27,说明是是正确的。以上就是python中开N次方的操作方法:
若n个相互独立的随机变量 ,均服从标准正态分布(也称独立同分布于标准正态分布),则这n个服从标准正态分布的随机变量的平方和
构成一新的随机变量,其卡方分布规律称为 分布(chi-square distribution),其中参数 称为自由度,正如正态分布中均值或方差不同就是另一个正态分布一样,自由度不同就是另一个分布。卡方分布是由正态分布构造而成的一个新的分布,当自由度 很大时, 分布近似为正态分布。 对于任意正整数 , 自由度为 的卡方分布是一个随机变量 的机率分布。
8个超好用内置函数set(),eval(),sorted(),reversed(),map(),reduce(),filter(),enumerate()
python中有许多内置函数,不像print那么广为人知,但它们却异常的强大,用好了可以大大提高代码效率。
这次来梳理下8个好用的python内置函数
1、set()
当需要对一个列表进行去重操作的时候,set()函数就派上用场了。
用于创建一个集合,集合里的元素是无序且不重复的。集合对象创建后,还能使用并集、交集、差集功能。
2、eval()之前有人问如何用python写一个四则运算器,输入字符串公式,直接产生结果。用eval()来做就很简单:eval(str_expression)作用是将字符串转换成表达式,并且执行。
3、sorted()在处理数据过程中,我们经常会用到排序操作,比如将列表、字典、元组里面的元素正/倒排序。这时候就需要用到sorted() ,它可以对任何可迭代对象进行排序,并返回列表。对列表升序操作:
对元组倒序操作:
使用参数:key,根据自定义规则,按字符串长度来排序:
根据自定义规则,对元组构成的列表进行排序:
4、reversed()如果需要对序列的元素进行反转操作,reversed()函数能帮到你。reversed()接受一个序列,将序列里的元素反转,并最终返回迭代器。
5、map()做文本处理的时候,假如要对序列里的每个单词进行大写转化操作。这个时候就可以使用map()函数。
map()会根据提供的函数,对指定的序列做映射,最终返回迭代器。也就是说map()函数会把序列里的每一个元素用指定的方法加工一遍,最终返回给你加工好的序列。举个例子,对列表里的每个数字作平方处理:
6、reduce()前面说到对列表里的每个数字作平方处理,用map()函数。那我想将列表里的每个元素相乘,该怎么做呢?这时候用到reduce()函数。
reduce()会对参数序列中元素进行累积。第一、第二个元素先进行函数操作,生成的结果再和第三个元素进行函数操作,以此类推,最终生成所有元素累积运算的结果。再举个例子,将字母连接成字符串。
你可能已经注意到,reduce()函数在python3里已经不再是内置函数,而是迁移到了functools模块中。这里把reduce()函数拎出来讲,是因为它太重要了。
7、filter()一些数字组成的列表,要把其中偶数去掉,该怎么做呢?
filter()函数轻松完成了任务,它用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象。filter()函数和map()、reduce()函数类似,都是将序列里的每个元素映射到函数,最终返回结果。我们再试试,如何从许多单词里挑出包含字母w的单词。
8、enumerate()这样一个场景,同时打印出序列里每一个元素和它对应的顺序号,我们用enumerate()函数做做看。
enumerate翻译过来是枚举、列举的意思,所以说enumerate()函数用于对序列里的元素进行顺序标注,返回(元素、索引)组成的迭代器。再举个例子说明,对字符串进行标注,返回每个字母和其索引。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流