不管是在练习项目还是实际工作中,我们基本上是抽样获取数据,通过一定的抽样设置得到一定数据量,然后从样本数据推断总体分布。但是不同情景下的数据分布是不同的,为了数据分析和后期模型建立,我们需要了解数据的实际分布。
一 . 数据分布检验
1. 判断一组数据是否服从正态分布
# python
import scipy.stats as stats
# Shapiro-Wilk test, x 为待检测数据,返回统计量和P值,适合样本量小于50
stats.shapiro(x)
# Kolmogorov–Smirnov,K-S 检验,样本量适合50~300,x 待检测数据,cdf为待检验分布,norm可检验正态,返回统计量和P值
stats.kstest (x, cdf, args = ( ), alternative ='two-sided', mode ='approx')stats.anderson (x, dist ='norm' ) # x 为待检测数据,dist为待检测分布,可以正态、指数、二项等
stats.normaltest (a, axis=0) # 样本量大于300
2. 判断两组数据是否服从同一分布-- K-S检验
统计量为各阶段两组数据的累计概率分布差值的最大值
stats.ks_2samp(x, y)
3. 方差齐性检验--F检验
比较两组数据方差是否存在显著性差异,适用于两样本t检验之前。
# 正态分布 F 检验
p = stats.f.sf(var1, var2, n1-1, n2-1)
# 非正态分布
stats.bartlett(*args) # Bartlett's test 球状检验 ,输入为array_like的sample1,sample2, sample3 ...,返回统计量和P值
stats.levene(*args) # Levene's test 参数同上,对于显著非正常人群,鲁棒性强
二. 总体推断
- 一个总体参数检验--单样本检验
a. 总体均值
① 总体方差已知 or(总体方差未知 and 样本量大)
② 总体方差未知 and 样本量小
b. 总体比例
c. 总体方差(正态分布)
2、两个总体参数检验--两样本检验
a. 两总体均值是否相等
① 总体方差已知 or(总体方差未知 and 样本量大)
② 总体方差未知 and 总体方差相等 and 样本量小
③ 总体方差未知 and 总体方差不等 and 样本量小
自由度
b. 两总体比例是否相等
c. 两总体方差是否相等(正态分布)
自由度(n1-1, n2-1)
import scipy.stats as stats
import numpy as np
np.random.seed(7653567)
x = stats.norm.rvs(loc=2, scale=10, size=100)
y = stats.norm.rvs(loc=2, scale=10, size=100)
z = stats.norm.rvs(loc=2, scale=10, size=100)
# 单样本========================================================================
# 单样本z检验
from statsmodels.stats.weightstats import ztest
ztest(x, value=20) # 判断总体均值是否是20
# 单样本 t检验
stats.ttest_1samp(x, 2.0)
# 单因素方差分析 ANOVA
stats.f_oneway(x, y, z) # x,y,z 是同一个自变量3个类别分别对应的样本观察值(因变量),样本量可不等
# 单样本K-S 检验(Kolmogorov–Smirnov test),检验是否服从某个分布
stats.kstest(x, 'norm')
# 单样本Wilcoxon检验--符号秩检验,检验样本中位数
import statsmodels
statsmodels.stats.descriptivestats.sign_test(x, mu0=0) # mu0 通常为中位数
# 二项分布检验
stats.binom_test(x, n=None, p=0.5, alternative='two-sided') # 检验x成功率与p是否有显著差异,n是抽样次数
# 游程检验,判断总体变量值是否随机
from statsmodels.sandbox.stats.runs import runstest_1samp
runstest_1samp(x,cutoff='median'/'mean')
# =============================================================================
# 两独立样本=====================================================================
# 两独立样本t检验
stats.ttest_ind(x, y, equal_var=True) # equal_var:方差齐性
# Mann-Whitney检验,假设总体其它参数相同,检验总体均值是否有差异,样本量可不同
stats.mannwhitneyu(x, y)
# K-S检验,检验两总体分布是否相同,在信用评级模型中可以验证模型对违约对象的区分能力
stats.ks_2samp(x, y)
# 两样本游程检验,即 Wald-Wolfowitz检验,检验俩总体是否相同
from statsmodels.sandbox.stats.runs import runstest_2samp
runstest_2samp(x, y)
# Moses极端反应检验, 检验总体分布是否相同,对全体样本混合求秩分,根据两端的极端秩分值确定其差异性。
# =============================================================================
# 配对样本=======================================================================
# 配对样本t检验
stats.ttest_rel(x, y)
# 配对wilcoxon检验,检验俩样本中位数是否有显著差异,要求样本量相等
# correction表示小样本时,计算z统计量用0.5校正,alternative:two-sided,greater 针对H1假设大于
stats.wilcoxon(x,y,correction=True,alternative='greater') # 样本量n>20
# McNemar检验,配对卡方检验,是基于两次测量差值情况的检验方法。
# 即把样本的两次测量值相减,记录差值,然后通过校验公式处理后,求取卡方值
from statsmodels.sandbox.stats.runs import mcnemar
import numpy as np
mcnemar(x, y) # If y is None, then x can be a 2 by 2 contingency table
x = np.array([[80, 110], [75, 90]])
mcnemar(x)
# =============================================================================
# 多样本========================================================================
# KrusKal-Wallis检验,设两个分布的样本中位数相等,用于检验样本是否来源于相同的分布
stats.kruskal(x, y) # 样本量可不同, 可比较多个样本
# 有序备择检验J-T检验 适用备择假设有上升或下降的趋势,大样本时趋于正态分布
# Friedman 秩和检验,适用于算法模型的性能比较,基本思想是先对样本的K个检验量进行降序求秩分,然后按照秩分做方差分析。
"""
构造降序排序矩阵
"""
def rank_matrix(matrix):
cnum = matrix.shape[1]
rnum = matrix.shape[0]
## 升序排序索引
sorts = np.argsort(matrix)
for i in range(rnum):
k = 1
n = 0
flag = False
nsum = 0
for j in range(cnum):
n = n+1
## 相同排名评分序值
if j < 3 and matrix[i, sorts[i,j]] == matrix[i, sorts[i,j + 1]]:
flag = True;
k = k + 1;
nsum += j + 1;
elif (j == 3 or (j < 3 and matrix[i, sorts[i,j]] != matrix[i, sorts[i,j + 1]])) and flag:
nsum += j + 1
flag = False;
for q in range(k):
matrix[i,sorts[i,j - k + q + 1]] = nsum / k
k = 1
flag = False
nsum = 0
else:
matrix[i, sorts[i,j]] = j + 1
continue
return matrix
"""
Friedman检验
参数:数据集个数n, 算法种数k, 排序矩阵rank_matrix(k x n)
函数返回检验结果(对应于排序矩阵列顺序的一维数组)
"""
def friedman(n, k, rank_matrix):
# 计算每一列的排序和
sumr = sum(list(map(lambda x: np.mean(x) ** 2, rank_matrix.T)))
result = 12 * n / (k * ( k + 1)) * (sumr - k * (k + 1) ** 2 / 4)
result = (n - 1) * result /(n * (k - 1) - result)
return result
# friedman example
matrix = np.array([sample1, sample2, sample3, sample4])
matrix_r = rank_matrix(matrix.T)
Friedman = friedman(n, k, matrix_r) # n 是每组样本大小,k是k组样本
# Kendall 协同系数检验,先计算K个观测量卡方值和协同系数W,然后判断其观测值的分布是否一致。
# W表示被检验变量的秩分之间的差异程度。协同系数W的取值在0~1,W越接近于1,表示变量的组件差异越大
stats.kendalltau(x, y)
# Cochran Q检验,分析K各关联样本是否来自同一总体或者具有相同的分布
from statsmodels.sandbox.stats.runs import cochrans_q
cochrans_q(x) # x 是n*k矩阵,k组n样本大小
三、其它检验
- Permutation test 置换检验
基于大量计算,利用样本的全排列推断总体。适用于总体未知的小样本检验。比较两组方案的样本观测值,推断总体是否存在差异,两组样本量可不同。具体操作是混合两组样本,重复抽样两组与原样本量相同的样本,计算均值差分布,根据原始样本均值差在此分布中的概率,并根据显著性水平判断是否存在差异。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
def permutation_test(x, y, n):
m, k = len(x), 0
diff = np.abs(np.mean(x)-np.mean(y))
z = np.concatenate([x, y])
lst = np.empty(n)
for j in range(n):
np.random.shuffle(z)
lst[j] = np.abs(np.mean(z[:m])-np.mean(z[m:]))
k += diff<lst[j]
p = k/n
return lst, p
x = np.array([24,43,58,67,61,44,67,49,59,52,62,50])
y = np.array([42,43,65,26,33,41,19,54,42,20,17,60,37,42,55,28])
lst, p = permutation_test(x, y, 999)
print(p) # p=0.013
sns.set_palette("hls")
sns.distplot(lst,color="g",bins=40,kde=True)
plt.title('Permutation Test')
plt.xlabel('difference')
plt.ylabel('distribution')
plt.show()
2. Mann-kendall检验
判断变量,随着时间变化,是否有单调上升或下降的趋势。可替代参数线性回归分析,MK检验是非参数检验(不要求服从任何分布),允许少量缺失值和异常值。在气候诊断和预测的场景使用较多。
前提要求:无趋势时样本是独立同分布的。样本是无偏,有效。
stats.kendalltau(x,y) # 输出corelation 和p,判断x, y是否显著相关
stats.mstats.theilslopes(y, x=None, alpha=0.95)[source] # 输出斜率,alpha是置信度