对总体分布的假设检验是一种非参数检验,所谓非参数假设检验,即在不确定总体分布的数学形式下,对总体的各种一般性推断。例如,“X服从正态分布”,“X1,X2,…,Xn”同分布等都是非参数假设。对总体分布假设检验的一般形式:设x1,x2,…,xn,来自总体X的样本,据此样本需要检验假设
H0 :
H1 :X的***不是
掷一颗骰子240次,得点数的频数(观测频数)如下,是否服从均匀分布?
出现点数 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
观测频数 | 45 | 36 | 31 | 48 | 42 | 38 |
解:设X表示掷这颗骰子一次出现的点数,其有6种可能取值,若X服从均匀分布,则p(x=i)=1/6,i=1,2,…,6。所以原假设可以写作如下形式:
H0 :X服从均匀分布,即
H0 :P(X=i)=p, i=1,2,…,6;p=1/6
计算卡方统计量公式如下,
分别计算每种取值的观测频数和期望频数(理论频数),得到卡方值,然后查表得到P值,通过P值与置信水平α来判断是否接受原假设,P值越大越容易接受原假设,即认为样本服从均匀分布。
随机抽取到一部分样本x,x为连续数据,问X是否服从正态分布?
解:假设x的概率密度函数为
f ( x ) = 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 f(x) =\frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} f(x)=2πσ21e−2σ2(x−μ)2
其中μ和σ未知,可以通过极大似然方法对样本估计得到均值和方差的估计值。
有了概率密度函数,就可以设置原假设为:
H0 :X服从正态分布,即
H0 :X具有概率密度函数:
f ( x ) = 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 f(x) =\frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} f(x)=2πσ21e−2σ2(x−μ)2,
对于连续数据,计算卡方统计量时,需将原数据分箱处理,即转换为分组数据,然后分别计算每组的观测频数和期望频数(理论频数),得到卡方值,查表得到P值,通过P值与置信水平α来判断是否接受原假设,P值越大越容易接受原假设,即认为样本服从正态分布。
卡方检验是非参数假设检验方法,使用的统计量是卡方。例如做正态性假设检验时,需先根据现有样本,使用极大似然的方法估计出概率密度函数的参数:均值和方差,得到正态分布的概率密度函数f(x)的函数形式,从而可以计算概率值,进而可以计算期望频数(np)来计算卡方统计量,以及P值,通过P值和置信水平的大小比较来判断原假设是是否成立。
步骤:
P值越大越容易接受原假设,即样本否从某种分布。
normaltest、kstest、shapiro三者的原假设均可以为X服从正态分布,P值越小,越容易拒绝原假设,即认为数据不服从正态分布。
有如下数据,
import scipy
import numpy as np
rng = np.random.default_rng()
a = rng.normal(0, 1, size=3000)
b = rng.normal(10, 20, size=3000)
c = np.concatenate((a, b))
k2, p = stats.normaltest(b)
注意:
scipy.stats.normaltest是非参数假设检验总体分布,使用的统计量是卡方。先根据现有样本,使用极大似然的方法估计出均值和方差,得到正态分布的概率密度函数f(x),原假设为H0:概率密度函数=f(x)。而ktest也是非参数检验方法,但是参数估计值默认是均值=0,方差=1或者需要手动输入均值和方差参数。所以,对于同一数据(非标准正态分布),normaltest(估计样本得到参数)和ktest(使用默认参数)得到的结果自然不一样,甚至相反也很正常。也因此,做正态性假设检验时,最好对原数据z-score处理一下,不容易出错。
import numpy as np
import pandas as pd
a = rng.normal(0, 1, size=100)
b = rng.normal(10, 6, size=100)
c = np.concatenate((a, b))
d = rng.normal(0, 1, size=6000)
e = rng.normal(10, 5, size=10000)
x=[a,b,c,d,e]
p_list=[]
for da in x:
_,p1=scipy.stats.shapiro(da)
_,p2= scipy.stats.kstest(rvs=da,cdf='norm',args=(da.mean(),da.std()))
_,p3 = stats.normaltest(da)
p_list.append([p1,p2,p3])
df =pd.DataFrame(p_list,index=['a','b','c','d','e'],columns=['shapiro','kstest','normaltest'])
df>0.05