前提:数据正态性是诸如回归分析、方差分析等进行前需要进行的判断。
1. 所有方法:
首先最常用的方法是图示法,包括正态图和P-P/Q-Q图。正态图看一下是不是“钟形”分布曲线;P-P是查看实际数据累积比例与对应正态分布累积比例的散点图;Q-Q是查看实际数据与对应正态分布分位数的符合程度。
其次是正态性检验方法,利用观测数据判断总体是否服从正态分布的检验称为正态性检验,它是统计判决中重要的一种特殊的拟合优度假设检验。
最后是描述法(偏度-峰度检验法),即通过描述数据偏度和峰度系数来检验数据的正态性。参考正态分布的偏度为0,峰度为3(实际应用中通常将峰度值减去3,根据具体的软件需要注意)。一般现实数据是不可能达到这个要求的,所以如果峰度绝对值小于10并且偏度绝对值小于3,即可判定数据基本为正态分布。
几种方法对比。从上面介绍可以看出,正态性检验最为苛刻,而实际中可能存在样本不足的情况,此时如果数据的图示法基本符合正态分布也是可行的。同时,采用偏度峰度的判别方法也简单可行,但容易受到异常值的影响。
一般而言,如果原始数据不满足正态分布(比如偏态分布),通过取对数、开根号这种数据变换方法可使数据更接近正态性。
2. 正态性检验方法:
检验方法
- Shapiro-Wilktest(夏皮罗维尔克检验法,W检验):Shapiro-Wilk检验需要首先对数据进行排序,统计量可以看做是排序值与最佳无偏线性估计值之间的平方,值越高,代表样本与正态分布更匹配。W统计量计算公式参见Shapiro-Wilk。
- Kolmogorov-Smirnov(科尔莫戈罗夫检验法,K-S检验):Kolmogorov-Smirnov检验是基于累计分布函数的,单样本K-S检验可用于检测一个数据的观测值是否符合特定的理论分布(比如正态分布等);两样本的K-S检验可用于比较两个观测样本的经验函数是否存在显著差异。K-S检验是一种稳健的非参数化方法,不依赖于均值位置、适用范围广。K-S统计量的计算公式参见Kolmogorov-Smirnov。
检验思路【重点】
- 检验问题:W检验与K-S检验的原假设H0为:总体服从正态分布。
- 判断思路:因为原始假设为数据符合正态分布,所以如果得到的显著性值很小(小于设定的0.01,0.005,0.001等),那么原假设被推翻,说明数据不符合正态分布;反之,如果统计变量的显著性值大于设定的显著性水平,那么原假设成立,数据符合正态分布(简单来说,p>0.05是我们的目标,如果满足,即可说明数据满足正态性分布)。
方法对比
- 原理不同:上述可知两个方法的基本原理不一致。
- 样本量大小:在选择时,经常依据样本量的大小进行选择。对于W检验,适用于小样本,作者推荐样本量小于20的时候使用(参考Shapiro-Wilk),SPSS统计软件以及搜索资料发现,在样本量小于50时,推荐使用W检验;在样本量位于50-5000的情况下,可以同时考虑W检验和K-S检验;在样本量大于5000时,一般只使用K-S检验(SPSS在样本量大于5000时只显示K-S统计量)。
3. SPSS、R和Python语言代码实战
SPSS
- 采用SPSS进行分析的方法,直接一搜索能出来好多,很简单(可参见spss如何进行正态性检验)。
R语言
- 对于R语言,参见多组多个变量的正态性检验,可知基本函数如下。
# W 检验
shapiro.test(mydata$age)
# K-S检验采用nortest包中的lillie.test()函数来实现
library(ggplot2)
head(diamonds)
install.packages("nortest")
library(nortest)
lillie.test(diamonds$price)
Python语言
下面展示下用Python中的scipy包进行检验。
- W检验
函数形式:scipy.stats.shapiro(x)
官方链接:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.shapiro.html
主要参数:x为输入的样本数据。不管样本量如何,当原假设成立时,拒绝原假设的概率接近5%。
from scipy import stats
rng = np.random.default_rng()
x = stats.norm.rvs(loc=5, scale=3, size=100, random_state=rng)
shapiro_test = stats.shapiro(x)
shapiro_test
ShapiroResult(statistic=0.9813305735588074, pvalue=0.16855233907699585)
shapiro_test.statistic
0.9813305735588074
shapiro_test.pvalue
0.16855233907699585
- K-S检验
函数形式:scipy.stats.kstest(rvs, cdf, args=(), N=20, alternative='two-sided', mode='auto')
官方链接:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.kstest.html
主要参数:rvs为待检验的数组或列表;cdf为检验方法,如果是单样本检验,数值为'norm', 'expon', 'rayleigh', 'gamma'等,设置为'norm’即为正态性检验;默认是双边检验;N设置输入的rvs为变量生成函数时指定数组的长度;其他变量不解释了。
from scipy import stats
x = np.linspace(-15, 15, 9)
stats.kstest(x, 'norm')
# 输出:KstestResult(statistic=0.444356027159..., pvalue=0.038850140086...)
- 偏度-峰度检验
函数形式:scipy.stats.normaltest(a, axis=0, nan_policy='propagate')
官方链接:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.normaltest.html
主要参数:a,为包含待测试样本的数组;axis,计算测试所沿着的轴,默认值为0,如果为None,则计算整个数组a;nan_policy定义当输入包含nan时如何处理。
from scipy import stats
rng = np.random.default_rng()
pts = 1000
a = rng.normal(0, 1, size=pts)
b = rng.normal(2, 1, size=pts)
x = np.concatenate((a, b))
k2, p = stats.normaltest(x)
4 完结
从应用角度来看很简单,在Python下,就是stats.normaltest(x)、stats.kstest(x, 'norm')以及stats.shapiro(x)三个的调用,后两者在样本量为50和5000时进行区分调用。
其他参考资料:
https://zhuanlan.zhihu.com/p/70755099
https://www.statsref.com/HTML/index.html
https://www.51xxziyuan.com/58/1287.html