第8章 高等统计学

[toc]

8.1 点估计

我们在上一章中提到,获得总体参数非常困难,甚至是难以实现的,所以我们通过计算样本的统计量得到总体参数。我们将通过以上方式估计参数值的方法,叫作**点估计(point estimates)**。

点估计指通过样本数据估计总体参数。

我们可以使用点估计的方法对总体均值、方差等统计量进行估计。为了得到估计值,我们只需将被计算对象由总体变为样本即可。比如,某公司有9000名员工,我们希望知道每位员工平均每天休息的时长。我们可以从9000人中抽取一个样本,计算样本的平均值。样本平均值就是我们的点估计。

下面我们通过Python模拟总体数据,规则如下。

(1)根据第6章“高等概率论”,如果已知事件的平均值,那么通常使用泊松随机变量(poisson random variable)对事件进行建模。因此,我们用泊松分布随机生成9000 个调查问卷的答案:你平均每天休息的时长是多少?

notes:请注意,总体的均值一般很难直接获取。本例计算总体的均值是为了将总体参数和样本做比较,以便你更深入地理解点估计。

(2)从总体中随机抽取100名员工组成样本(使用Python的随机抽样方法),计算样本均值(总体均值的点估计)。

(3)对比样本均值和全体均值。

notes:请注意,样本大小占总体的比例略高于1%。

下面是Python代码:

1
2
3
4
5
6
7
8
import pandas as pd
import numpy as np
import scipy.stats as stats
%matplotlib inline
np.random.seed(1234)

long_breaks=stats.poisson.rvs(loc=10,mu=60,size=3000)
# represents 3000 people who take about a 60 minute break

变量long_breaks代表3000名员工的调查问卷结果,他们的平均休息时长是60min。我们用直方图查看数据的分布情况:

1
pd.Series(long_breaks).hist()

如图8.1所示,平均值60位于分布的左侧,最高的柱子对应的人数在700~800。

image-20230429213749825

下面我们继续用泊松分布模拟另外6000名员工的调查问卷结果,他们的平均休息时长为15min,代码如下:

1
2
3
short_breaks=stats.poisson.rvs(loc=10,mu=15,size=6000)
# represents 6000 people who take about a 15 minute break
pd.Series(short_breaks).hist()

image-20230429214001122

我们分别有了平均休息时长较长(60 min)和较短(15 min)的两个分布,下面将它们合并在一起,得到总体。代码如下:

1
2
breaks=np.concatenate((long_breaks,short_breaks))
# put the two arrays together to get our "population" of 9000 people

变量breaks是long_breaks和short_breaks合并后的总体,它的分布情况如下:

1
pd.Series(breaks).hist()

图8.3中有两个隆起,左边隆起的柱子来自平均休息时长15min的员工,右边隆起的柱子来自平均休息时长60min的员工。

image-20230429214339933

1
2
breaks.mean()
# 39.99 minutes is our parameter

我们的总体是9000名员工,总体的参数是40min。

请记住,在现实世界中,多方面的原因导致我们没有足够资源调查每位员工的休息时长,所以才需要使用点估计的方法,对总体参数进行估计

下面我们随机抽取100人,计算他们的平均休息时长:

1
2
sample_breaks=np.random.choice(a=breaks,size=100)
# taking a sample of 100 employees

下面我们计算样本均值,并将它和全体均值相减,对比两者的差异:

1
2
breaks.mean()-sample_breaks.mean()
# difference between means is 4.09 minutes,not bad!

差异不大,这非常有意思!因为样本数量只占总体的1/9(100/9000),但估计的参数值和真实参数值的差异只有4min。

我们还可以用同样方法估计总体的比例(proportion)。比例指两个数值的比率。

假设公司有10000名员工,其中白人20%,黑人10%,西班牙人10%,亚洲人30%,剩余30%来自其他地方。我们随机选取由1000人组成的样本,对比总体和样本的种族比例是否接近。

1
2
3
4
import random
employee_races=(["white"]*2000)+(["black"]*1000)+\
(["hispanic"]*1000)+(["asian"]*3000)+\
(["other"]*3000)

下面从总体中随机选取1000人,代码如下:

1
2
3
4
5
6
demo_sample=random.sample(employee_races,1000)
#Sample 1000 values

for race in set(demo_sample):
print(race+" proportion estimate:")
print(demo_sample.count(race)/1000.)

输出结果如下:

1
2
3
4
5
6
7
8
9
10
hispanic proportion estimate:
0.103
white proportion estimate:
0.192
other proportion estimate:
0.288
black proportion estimate:
0.1
asian proportion estimate:
0.317

从以上结果可以看出,种族比例的估计值和总体的真实分布非常接近。比如,样本中西班牙人的比例是10.3%,总体中西班牙人的比例是10%。

8.2 抽样分布

在第7章中,我们提到有多喜欢呈正态分布的数据!其中一个重要原因是很多假设检验(包括本章使用的方法)都要求数据服从正态分布。遗憾的是现实世界中大部分数据并不服从正态分布(吃惊吗?)。以员工休息时长数据为例,你可能认为我是随机选取了泊松分布,但实际上我是刻意的——我希望得到非正态分布数据。

1
pd.DataFrame(breaks).hist(bins=50,range=(5,100))

从图8.4可以看出,数据不服从正态分布,看起来像是双峰分布(bi-modal),两个凸起点分别位于25min和70min附近。由于数据不呈正态分布,所以很多常用的统计检验都无法使用。但是,我们有办法将以上数据转换为正态分布!是不是认为我疯了?好吧,自己来看吧。

image-20230429220359870

首先,我们需要了解什么是抽样分布(sampling distribution)抽样分布是多个大小相同的样本的点估计的分布。我们通过以下方法模拟抽样分布:

抽样分布说的是对谁的分布?答案是样本统计量,比如样本均数或样本率。

(1)随机生成500个样本,每个样本大小为100;

(2)对以上500个点估计做直方图(看看它们的分布)。

虽然样本大小100是随意确定的,但它需要足够大,以体现总体的分布特征。样本数量500也是随意确定的,但它也需要足够大,以便能够生成正态分布。

1
2
3
4
5
6
7
8
9
10
point_estimates=[]

for x in range(500): # Generate 500 samples
sample=np.random.choice(a=breaks,size=100)
# take a sample of 100 points
point_estimates.append(sample.mean())
# add the sample mean to our list of point estimates

pd.DataFrame(point_estimates).hist()
# look at the distribution of our sample means

看到了吧!虽然我们的原始数据是双峰分布,但样本均值的抽样分布是正态分布。请注意,图8.5是500个随机样本的平均休息时间分析,每个样本含有100人。换句话说,抽样分布是多个点估计的分布。

image-20230429222550390

以样本均数为例,一般说样本均数的抽样分布如何如何,这里,样本均数被当成了一个随机变量来看待。这或许是最核心的要点:样本均数是一个随机变量

为何样本均数可以被当作一个随机变量?因为样本均数是依赖样本计算得出的:每抽取一组样本都可以计算出一个样本均数,而且这些样本均数或多或少都会有些差异。由此,样本均数会随着抽样的不同而随机变动。只是现实生活中我们一般只抽取一组样本,计算一个样本均数,因此,会觉得样本均数不变。

抽样分布之所以呈正态分布是因为中心极限定理(central limit theorem)

中心极限定理的逻辑:在任意总体中随机抽取一个样本量为n的样本,如果样本容量较大(通常大于等于30),那么通过这个样本计算的样本均数近似服从正态分布。

随着我们增大样本的数量,抽样分布(点估计的分布)将逐渐趋向正态分布。而且,随着样本数量越来越多,样本均值的分布将越来越接近真实的均值,如下所示:

1
2
breaks.mean()-np.array(point_estimates).mean()
# 0.047 minutes difference

这是一个非常有意思的结果。根据中心极限定理,我们通过多个点估计得到的值比单个点估计更接近真实值。

notes:通常来讲,随着我们增大样本的数量,估计值将逐渐接近真实值。

因为抽样分布概念的引入以及中心极限定理的应用,我们不再害怕原总体分布是否服从正态分布,只要样本量满足一定要求,根据样本计算的各种统计量几乎都服从正态分布,从而均能用正态分布的性质来进行研究。

对抽样分布的总结:抽样分布是针对样本统计量而言的,比如样本均数。在同一个总体中,重复多次抽取样本量为n的多组样本,每一组样本均可计算出一个样本均数,将这些样本均数汇集在一起就获得了所谓的样本均数的抽样分布。我们把样本均数看做一个新“随机变量”,可以对它再求平均数和标准差。

一个简单但非常实用的规律是,无论X的分布如何,如果X的总体均数是 图片 ,标准差是 图片 ,则其样本均数服从正态分布N( 图片图片)。需要注意的是,这里的样本要满足比较大的样本量。

参考文章:抽样好懂,抽样分布又在说啥

8.3 置信区间

参考资料:在概率论与数理统计全集(统计学)学习笔记内可以找到更多参考。

我认为原文讲的置信区间的内容不是很容易理解,推荐先看参考资料再看原文。

虽然点估计可以估算总体的参数和抽样分布,但仍然存在两个重要问题:

(1)单个点估计非常容易出错(由于样本偏差等原因);

(2)计算多个固定大小样本的抽样分布是不可行的,有时甚至比直接计算总体参数还难。

正因为如此,我们引入统计学中非常重要的一个概念——置信区间(confidence intervals)。置信区间是一个区间值,是指在给定置信水平下,该区间将包含总体参数。

所有的科学实验和测量都无法避免误差。所以科学实验中总是会在测量结果上加一个误差范围。比如,经过测量,马云的智商是100,测量误差是±5,即[100-5,100+5]

置信水平是高等统计学最重要的概念之一,它经常被误解。非正式地说,置信水平并不是结果“正确的概率”,相反,它表示结果“准确的频率”。比如,假设我们希望每一次点估计都能以95%的概率得到准确的总体参数,那么置信水平需要设置为95%。

notes:较高的置信水平将导致置信区间变得更广。

置信水平(confidence level)Y%:置信区间包含总体平均值的概率P(a<样本平均值<b)=Y%

我们选择[a,b]这个置信区间,目的是为了让“a和b之间包含总体平均值”这一结果具有特定的概率,这个概率就是置信水平。

为了得到置信区间,我们需要找到点估计和误差幅度(margin of error)。误差幅度指我们能接受的点估计的误差范围,它依赖于置信区间、数据的方差和样本大小。有很多方法可以计算置信区间,为了简单起见,我们将用最简单的方法计算总体均值的置信区间。

为了计算置信区间,我们需要:

  • 点估计,比如样本的平均休息时长。

  • 总体标准差的估计值,它表示数据的离散程度。

    通过样本标准差除以总体大小的平方根计算。
    
  • 自由度(样本大小减1)。

以上数据可能看起来有点随意,但请相信我,这都是有原因的。我将用Python内置的模块计算置信区间,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sample_size=100
# the size of the sample we wish to take
sample=np.random.choice(a=breaks,size=sample_size)
# a sample of sample_size taken from the 9000 breaks population from before

sample_mean=sample.mean()
# the sample mean of the break lengths sample

sample_stdev=sample.std()
# sample standard deviation

sigma=sample_stdev/math.sqrt(sample_size)
# population standard deviation estimate

stats.t.interval(alpha=0.95, # Confidence level 95%
df=sample_size-1, # Degrees of freedom
loc=sample_mean, # Sample mean
scale=sigma) # Standard deviation
# (36.36,45.44)

再次强调,区间36.36至45.44是置信水平为95%时,平均休息时长的置信区间。我们知道总体的参数是39.99。显然,置信区间包含了总体的参数。

我们之前曾经说置信水平不是区间准确的百分比,而是区间包含总体参数的概率。

为了更好地理解置信水平,下面我们计算10000个置信区间,然后计算总体参数包含在置信区间的概率。首先,我们创建一个生成置信区间的函数,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# function to make confidence interval
def makeConfidenceInterval():
sample_size=100
sample=np.random.choice(a=breaks,size=sample_size)

sample_mean=sample.mean()
# sample mean

sample_stdev=sample.std()
# sample standard deviation

sigma=sample_stdev/math.sqrt(sample_size)
# population standard deviation estimate

return stats.t.interval(alpha=0.95,df=sample_size-1,loc=sample_mean,scale=sigma)

然后再通过一段程序,检验该置信区间包含总体参数39.99的概率:

(1)生成10000个样本的置信区间;

(2)计算置信区间包含总体参数的次数;

(3)用置信区间包含总体参数的次数除以10000。

1
2
3
4
5
6
7
8
times_in_interval=0
for i in range(10000):
interval=makeConfidenceInterval()
if 39.99>=interval[0] and 39.99<=interval[1]:
# if 39.99 falls in the interval
times_in_interval+=1
print(times_in_interval/10000)
# 0.9455

成功啦!结果显示,接近95%的置信区间都包含了总体均值,说明通过点估计和置信区间估计总体参数是一个相对简单和有效的统计推理。

下面我们来看随着置信水平的改变,置信区间大小如何变化。我们将计算不同置信水平对应的置信区间大小的差异。我们预期随着置信水平的提高,置信区间将随之增大,以提高包含总体参数的概率。

1
2
3
4
5
6
7
8
for confidence in (.5,.8,.85,.9,.95,.99):
confidence_interval=stats.t.interval(alpha=confidence,
df=sample_size-1,
loc=sample_mean,
scale=sigma)
length_of_interval=round(confidence_interval[1]-confidence_interval[0],2)
# the length of the confidence interval
print("confidence {0} has a interval of size {1}".format(confidence,length_of_interval))

输出结果为:

1
2
3
4
5
6
confidence 0.5 has an interval of size 2.56
confidence 0.8 has an interval of size 4.88
confidence 0.85 has an interval of size 5.49
confidence 0.9 has an interval of size 6.29
confidence 0.95 has an interval of size 7.51
confidence 0.99 has an interval of size 9.94

从以上结果可以看到,随着置信水平的提高,置信区间确实逐渐增大了。

接下来,我们将用置信区间研究假设检验,一方面扩大这个话题,另一方面用它进行更强大的统计推理。

8.4 假设检验

参考资料:在概率论与数理统计全集(统计学)学习笔记内可以找到更多参考。

假设检验(hypothesis tests)是统计学中应用最广泛的检验方法之一。它有多种形式,但目的都是一致的。

假设检验是一种统计学检验,用来确定对于总体中给定的样本,我们是否能够接受某一特定假设。本质上,假设检验是一种关于总体的某种假设的检验。检验的结果将告诉我们是否可以信任原假设,或拒绝原假设,接受备择假设。

你也可以认为,假设检验的核心是确定样本数据的特征是否背离了总体。这项工作现在听起来很难,幸运的是Python能拯救我们,它内置的包可以轻松地完成这些检验。

假设检验通常有两个相反的假设,我们称之为原假设(null hypothesis)备择假设(alternative hypothesis)。原假设是被检验的假设,也是默认正确的假设,它是实验的出发点。备择假设通常是与原假设相反的假设。假设检验结果将告诉我们哪个假设值得信任,哪个假设需要被拒绝。

假设检验根据样本数据,决定是否应该拒绝原假设。我们通常基于p值(依赖于置信水平)做出决定。

notes:一个常见的错误想法是统计学的假设检验被设计用来从两个相似的假设中做选择。这是不正确的。假设检验默认原假设是正确的,除非有足够的数据支持备择假设。

以下是几个可以用假设检验进行回答的问题:

  • 平均休息时长是否不等于40min?
  • 使用网页A的用户和使用网页B的用户是否存在差异(A/B测试)?
  • 样本咖啡豆的味道和总体咖啡豆的味道是否有显著差异?
8.4.1 实施假设检验

假设检验有多种不同的方法,它们的实施方式和指标也各不相同。尽管如此,所有的假设检验都包含以下5个最基本步骤。

(1)明确假设

  • 我们在这一步形成两个假设:原假设和备择假设。

  • 我们通常用符号$H_0$表示原假设,符号$H_α$表示备择假设。

(2)决定被检验样本的大小

  • 样本大小取决于被选择的检验类型。样本大小必须合适,并服从中心极限定理和数据正态性假设。

(3)选择置信水平(通常叫作阿尔法,符号a)

  • 通常用0.05的显著性水平。

(4)收集数据

  • 收集检验所需的样本数据。

(5)决定是否接受或拒绝原假设

  • 这一步取决于假设检验的类型。最终结果可能是接受原假设,也可能是放弃原假设,接受备择假设。

本章中,我们将介绍以下3种类型的假设检验:

  • 单样本t检验(one sample t-tests)
  • 卡方拟合度检验(Chi-square test for goodness of fit test)
  • 卡方相关性/独立性检验(Chi-square test for association/independence)

实际上,还有更多假设检验方法,但以上3种是最常用的方法。在选择检验方法时,最需要考虑的因素是被检验数据的类型——连续型数据,还是分类数据。为了让你真正看到假设检验的效果,我们将直接进入案例。

首先,对于连续型数据,我们选择t检验。

8.4.2 单样本t检验

单样本t检验是一种用于检验样本(数值型)是否和另一个数据集(总体或其他样本)具有显著性差异的统计检验方法。我们继续平均每天休息时长案例,用以下代码模拟工程部的平均休息时长:

1
2
3
4
5
6
7
8
9
import numpy as np
from scipy import stats
long_breaks_in_engineering=stats.poisson.rvs(loc=10,mu=55,size=100)
short_breaks_in_engineering=stats.poisson.rvs(loc=10,mu=15,size=300)
engineering_breaks=np.concatenate((long_breaks_in_engineering,short_breaks_in_engineering))
print(breaks.mean())
# 39.99
print(engineering_breaks.mean())
# 34.825

其中:

  • 此次生成的泊松分布样本较小,只模拟了工程部的400人;
  • 参数mu被设置为55而不是之前的60,以确保工程部的平均休息时长和整个公司不一致。

我们从代码的运行结果很容易看出,工程部的平均休息时长和整个公司有显著差异。但是请你注意,在真实场景下,我们通常无法获取总体和总体参数。为了更好地讲解,本书特意模拟和计算了总体参数,以便我们能够看出样本和总体的差异。

现在,假设我们对总体参数一无所知,需要依靠统计检验方法验证两者是否存在显著性差异。

案例:单样本t检验

我们的目标是验证总体(全公司)的平均休息时长是否和工程部门的平均休息时长存在显著性差异。

我们在95%置信水平上进行单样本t检验。理论上说,检验结果将告诉我们样本和总体是否有相同的分布特征。

单样本t检验的假设

在实施假设检验之前,我们有必要先了解t检验需要满足的条件:

  • 总体要满足正态分布,或样本大小至少大于30;
  • 总体大小至少是样本大小的10倍,以确保样本是独立随机样本。

请注意,t检验要求要么总体呈正态分布(我们知道这是不现实的),要么样本含有的数据点超过30个,这些条件都是为了确保数据的正态性。同时,t检验还要求样本独立,这可以通过取少量样本实现。总之,t检验的基本要求是,样本既要足够大以保持正态性,又要相对总体足够小以保持独立性。这听起来不可思议,不是吗?

下面,我们按照之前介绍的5个步骤进行t检验。

(1)明确假设。

我们假设$H_0$=工程部平均休息时长和公司平均休息时长相同。

请注意,$H_0$是我们的原假设(null hypothesis)。它是我们在没有数据作支撑时认为成立的假设。与之相对应,我们还有备择假设(alternative hypothesis)

我们有多个备择假设可以选择。比如,我们可以认为工程部的平均值低于或高于公司的平均值,或者不等于公司的平均值。

  • 如果我们想知道工程部的平均值是否不等于公司的平均值,这属于双尾检验(two-tailed test),此时的备择假设如下:

$$
H_α=工程部平均休息时长不等于公司平均休息时长
$$

  • 如果我们想知道工程部的平均值低于或高于公司的平均值,这属于单尾检验(one-tailed test),此时的备择假设如下:

$$
H_α=工程部平均休息时长低于公司平均休息时长
\
H_α=工程部平均休息时长高于公司平均休息时长
$$

单尾检验和双尾检验的区别在于得到的结果是否需要除以2。除此之外,两者的检验过程完全一致。本例中,我们选择双尾检验,我们希望知道工程部平均休息时长是否等于公司平均休息时长。

notes:假设检验结果有两种可能:要么接受原假设,也就是说没有足够的证据支持我们拒绝原假设;要么拒绝原假设,接受备择假设,即工程部平均休息时长不等于公司平均休息时长。

(2)决定被检验样本的大小。

大多数检验方法(包括本例)都要求数据呈正态分布,或者样本具有合适的大小:

样本至少含有30个数据点(本例中样本有400人);

样本占总体的比例低于10%(本例中总体有9000人)。o

(3)选择显著性水平(通常用α表示)。

我们选择显著性水平95%,这意味着α值等于1-0.95=0.05

(4)收集数据。

这一步已经提前完成!我们用两个泊松分布生成了数据。

(5)决定是否接受或拒绝原假设。

正如之前所说,最后一步随假设检验类型的不同而不同。对于单样本 t 检验,我们需要计算两个值:检验统计量和p值。幸运的是在Python中,只需要一行代码即可完成这项工作。

检验统计量是根据样本数据计算的一个数值,我们通常根据它决定是否应该拒绝原假设。检验统计量也用于将观测值和原假设预期得到的结果进行比较。

p值是观测值出现的概率,它通常和检验统计量一起使用。

当有强烈的证据拒绝原假设时,检验统计量通常非常大(正负皆可),p值通常非常小。这意味着检验结果非常可靠,而不是随机出现的结果。

对于本例使用的t检验,t值就是我们的检验统计量,Python代码如下:

1
2
3
t_statistic,p_value=stats.ttest_lsamp(a=engineering_breaks,popmean=breaks.mean())
t_statistic==-5.742
p_value==.00000018

检验结果显示t值等于-5.742,它表示原假设中样本均值的偏离程度。p值用于体现检查结果是否可靠,它是我们最终做出结论的依据。对于本例,如果p值等于0.06,说明我们有6%的概率得到这个结果,也就是说,有6%的样本可以得出这样的结果。

我们需要将p值和显著性水平进行对比:

  • 如果p值低于显著性水平,则拒绝原假设;
  • 如果p值高于显著性水平,则接受原假设。

在本例中,我们的p值低于显著性水平0.05,因此我们拒绝原假设,接受备择假设,即工程部的平均休息时长不等于公司平均休息时长。

notes:对p值的使用存在一些争议。很多出版物已经禁止用p值表示显著性,主要原因是p值的含义。假设p值等于0.04,那么数据恰好得出该结果的概率是4%,而不是任何情况下的显著性水平. 4%不是一个可以忽略的小数!正因为如此,很多人转向使用其他检验统计量。然而这并不意味着p值毫无用处,只说明我们必须谨慎地使用p值,弄清楚它究竟意味着什么。

还有其他类型的t检验,比如单尾检验、配对检验(paired test)和双样本t检验。它们的具体操作过程可以在其他统计学资料中查看。现在,我们应该看看另一个重要的事情——如果假设检验结果出错会发生什么?

8.4.3 I型错误和II型错误

我们在介绍二元分类器时曾介绍过I型错误(type I errors)和Ⅱ型错误(type Ⅱ errors),它们也同样适用于假设检验。

当原假设正确,但我们却拒绝了原假设时称为I型错误,或假阳性(false positive)错误。I型错误率等于显著性水平α,这意味着如果我们设置了较高的置信水平,比如99%,那么出现假阳性错误的概率等于1%。

当原假设错误,但我们没有拒绝原假设时称为Ⅱ型错误,或假阴性(false negative)错误。我们设置的置信水平越高,越容易遇到假阴性错误。

8.4.4 分类变量的假设检验

t检验(包括其他几种检验方法)适用于定量数据。下面我们将介绍两种新的检验方法,它们适用于定性数据。这两种检验方法都属于卡方检验(chi-square tests),主要用于:

  • 检验样本中的分类变量是否来自某个特定总体(和t检验类似);
  • 检验两个分类变量是否彼此影响。

卡方拟合度检验

t检验用于检验样本均值是否等于总体均值。卡方拟合度检验(chi-square goodness of fit test)和t检验类似,用于检验样本分布是否符合预期。两者最大的区别在于卡方检验的对象是分类变量。

比如,卡方拟合度检验可以检测你们公司雇员的种族分布是否和美国人口的种族分布一致,或者检验你们的网站用户是否和整个互联网的用户具有相同特征。

当我们处理分类数据时要特别小心,因为诸如”男性(male)””女性(female)”和”其他(other)”之类的分类信息没有任何数学含义。因此我们需要对变量进行计数,而不仅仅是变量本身的含义。

通常情况下,卡方拟合度检验用于:

  • 分析总体中的某个分类变量;
  • 分析某个分类变量是否符合预期的分布。

对于卡方检验,我们将观察到的结果和希望得到的结果做对比。

卡方拟合度检验的假设条件

卡方拟合度检验需满足以下两个条件:

  • 期望频数(expected counts)不低于5个;
  • 每个观测值都是独立的,且总体大小至少是样本的10倍。

第2个条件和t检验的要求类似,第1个条件则看起来比较陌生。

在定义原假设和备择假设时,我们会考虑分类变量的默认分布。比如,假设有一个模具,我们希望知道被检验对象是否来自同一个模具,那么原假设可能是:
$$
H_0=分类变量符合特定分布
\
p1=1/6,p2=1/6,p3=1/6,p4=1/6,p5=1/6,p6=1/6
$$
备择假设:
$$
H_α=分类变量不符合特定分布(至少有1个概率值不正确)
$$
在t检验中,我们用t值作为检验统计量并计算相应的p值。对于卡方检验,我们的检验统计量是卡方(chi-square):
$$
x^2=遍历分类变量所有的值
\
自由度(degrees of freedom)=k-1
$$
为了便于理解,我们用一个例子进行演示。

案例:卡方拟合度检验

疾控中心(以下简称CDC)将成年人的身体质量指数(以下简称BMI)分为4类:过轻/正常、过重、肥胖和非常肥胖。2009年的一项调查显示,美国成年人的BMI分别是31.2%、33.1%、29.4%和6.3%。我们随机抽取500名成年人,记录他们的BMI分类。

请问新的调查结果和2009年的调查结果是否有显著差异?假设显著性水平是0.05。

首先,我们计算每个分类的预期值,如表8.1所示。

BMI分类 过轻/正常 过重 肥胖 非常肥胖 总计
观测值 102 178 186 34 500
预期值 156 165.5 147 31.5 500

image-20230430213117592

我们可以用好帮手Python计算,如下所示:

1
2
3
4
5
6
7
observed=[102,178,186,34]
expected=[156,165.5,147,31.5]

chi_squared,p_value=stats.chisquare(f_obs=observed,f_exp=expected)

chi_squared,p_value
# (30.1817679275599,1.26374310311106e-06)

p值低于0.05,因此我们拒绝原假设,接受备择假设,即目前的BMI分布和2009年的BMI分布不同。

卡方相关性/独立性检验

在概率论中,独立性(independence)指变量间互不影响。比如,你出生的国家和出生的月份是互相独立的。但是,你使用的手机类型则可能暴露你的选择偏好,因此这两个变量就不具有独立性。

卡方相关性/独立性检验用于检验两个分类变量是否互相独立。该检验通常用来判断教育水平或税率等级是否受人口统计学的影响,比如性别、种族和宗教信仰等。下面我们回看上一章介绍的A/B测试案例。

在A/B测试案例中,我们让一半的用户使用网页A登录,另一半用户使用网页B登录,分别统计了两个网页的注册数,如表8.2所示。

未注册 注册
网页A 134 54
网页B 110 48

我们可以计算网页的转化率,但我们真正想知道的是以下两个变量是否存在相关性:用户使用哪个网页登录?是否进行了注册?我们将使用卡方检验进行验证。

卡方独立性检验的假设条件

卡方独立性检验需满足以下两个条件:

  • 每个分类的频数至少为5;
  • 每个观测值都是独立的,且总体大小至少是样本大小的10倍。

事实上,这两个条件和卡方拟合度检验相同。

下面我们定义原假设和备择假设:

  • $H_0$:两个分类变量没有相关性。
  • $H_0$:两个分类变量是互相独立的。
  • $H_α$:两个分类变量具有相关性。
  • $H_α$:两个分类变量非互相独立的。

你可能注意到我们遗漏了一个关键信息,期望频数(expected count)在哪里?在之前的检验中,我们会将先验分布和观测到的结果进行比较,但现在却没有这一步。为了完成这一步,我们需要新生成一些信息,用以下公式计算每个观测对象对应的期望值:
$$
期望频数=计算卡方检验的检验统计量和自由度
\
检验统计量:x^2=∑{(观测值_{r,c}-预期值_{r,c})^2\over 预期值_{r,c}}
\
自由度=(r-1)×(c-1)
$$
其中r表示行数,c表示列数。和之前类似,我们还可以计算p值,当p值低于显著性水平时拒绝原假设。我们同样使用Python内置的方法快速计算结果。

1
2
3
4
5
6
7
observed=np.array([[134,54],[110,48]])
# built a 2×2 matrix as seen in the table above

chi_squared,p_value,degrees_of_freedom,matrix=stats.chi2_contingency(observed= observed)

chi_squared,p_value
# (0.04762692369491045,0.82724528704422262)

结果显示p值非常大,因此我们无法拒绝原假设,也就是说,没有足够证据显示网页类型对用户注册率有影响,两个变量之间没有相关性。