某城市过滤水系统生产公司,有A、B、C3种方式进行过滤水系统的装配,该公司为了研究三种装配方式生产的过滤系统数量是否有差异,从全体装配工人中抽取了15名工人,然后随机地指派一种装配方式,这样每个装配方式就有5个工人。在指派装配方法和培训工作都完成后,一周内对每名工人的装配过滤系统数量进行统计如下:
某公司营销中心为了提升销量,针对某产品设计了3种不同金额的优惠,想测试三种优惠方式对于用户的购买转化率是否有显著影响,先收集到了三种不同方式在6个月内的转化率数据
P < 0.05 拒绝原假设,倾向于支持不同优惠金额购买率不一样的备择假设。认为不同优惠金额会对购买率产生影响 P > 0.05无法拒绝原假设。认为不同优惠金额不会对购买率产生影响
火箭的射程与燃料的种类和推进器的型号有关,现对四种不同的燃料与三种不同型号的推进器进行试验,每种组合各发射火箭两次,测得火箭的射程如表(以海里计)(设显著性水平为0.05)
在等重复实验中,我们为了检验实验中两个因素的交互作用,针对每对组合至少要做2次以上实验,才能够将交互作用与误差分离开来,在处理实际问题时候,如果我们一直不存在交互作用,或者交互作用对实验指标影响极小,则可以不考虑交互作用,此时每对组合只做一次实验,类似下方例子中的表中数据:
7. 相关性分析前面的假设检验、方差分析基本上都是围绕差异性分析,不论是单个总体还是两个总体及以上,总之都是属于研究“区别”,从本节开始,我们关注“联系”,变量之间的关系分为函数关系和相关关系。 本节这里重点探讨的是不同类型变量之间的相关性,千万记住一点相关性不代表因果性。除表中列出的常用方法外,还有Tetrachoric、 相关系数等。
变量类型 变量类型 相关系数计算方法 示例 连续型变量 连续型变量 Pearson(正态)/Spearman(非正态) 商品曝光量和购买转化率
二分类变量(无序) 连续型变量 Point-biserial 性别和疾病指数 无序分类变量 连续型变量 方差分析 不同教育水平的考试成绩 有序分类变量 连续型变量 连续指标离散化后当做有序分类 商品评分与购买转化率 二分类变量 二分类变量 数学公式: 检验 联合 Cramer's V 性别和是否吸烟 二分类变量(有序) 连续型变量 Biserial 乐器练习时间与考级是否通过 无序分类变量 无序分类变量 数学公式: 检验 / Fisher检验 手机品牌和年龄段 有序分类变量 无序分类变量 数学公式: 检验 满意度和手机品牌 有序分类变量 有序分类变量 Spearman /Kendall Tau相关系数 用户等级和活跃程度等级
连续型变量 vs 连续型变量 : Pearson / Spearmanr
PearsonPearson相关系数度量了两个连续变量之间的线性相关程度;
import random import numpy as np import pandas as pd np.random.seed(10) df = pd.DataFrame({'商品曝光量' :[1233,1333,1330,1323,1323,1142,1231,1312,1233,1123], '购买转化率' :[0.033,0.034,0.035,0.033,0.034,0.029,0.032,0.034,0.033,0.031]}) df
pd.Series.corr(df['商品曝光量' ], df['购买转化率' ],method = 'pearson' ) # pearson相关系数 # 0.885789300493948
import scipy.stats as stats# 假设有两个变量X和Y X = df['商品曝光量' ] Y = df['购买转化率' ]# 使用spearmanr函数计算斯皮尔曼相关系数和p值 corr, p_value = stats.pearsonr(X, Y)print ("Pearson相关系数:" , corr)print ("p值:" , p_value)# Pearson相关系数: 0.8857893004939478 # p值: 0.0006471519603654732
Spearman等级相关系数Spearman等级相关系数可以衡量非线性关系变量间的相关系数,是一种非参数的统计方法,可以用于定序变量或不满足正态分布假设的等间隔数据;
import random import numpy as np import pandas as pd np.random.seed(10) df = pd.DataFrame({'品牌知名度排位' :[9,4,3,6,5,8,1,7,10,2], '售后服务质量评价排位' :[8,2,5,4,7,9,1,6,10,3]}) df
pd.Series.corr(df['品牌知名度排位' ], df['售后服务质量评价排位' ],method = 'spearman' ) # spearman秩相关 # 0.8787878787878788
import scipy.stats as stats# 假设有两个变量X和Y X = df['品牌知名度排位' ] Y = df['售后服务质量评价排位' ]# 使用spearmanr函数计算斯皮尔曼相关系数和p值 corr, p_value = stats.spearmanr(X, Y)print ("斯皮尔曼相关系数:" , corr)print ("p值:" , p_value)# 斯皮尔曼相关系数: 0.8787878787878788 # p值: 0.0008138621117322101
结论 :p = 0.0008<0.05
,表明两变量之间的正向关系很显著。
二分类变量(自然)vs 连续型变量 :Point-biserial假设我们想要研究性别对于某种疾病是否存在影响。我们有一个二元变量“性别”(男、女)和一个连续型变量“疾病指数”。我们想要计算性别与疾病指数之间的相关系数,就需要用到Point-biserial相关系数。
import scipy.stats as stats# 创建一个列表来存储数据 gender = [0, 1, 0, 1, 1, 0] disease_index = [3.2, 4.5, 2.8, 4.0, 3.9, 3.1]# 使用pointbiserialr函数计算Point-biserial相关系数和p值 corr, p_value = stats.pointbiserialr(gender, disease_index)print ("Point-biserial相关系数:" , corr)print ("p值:" , p_value)# Point-biserial相关系数: 0.9278305692406299 # p值: 0.007624695507848026
结论 :p = 0.007<0.05
,表明两变量之间的正向关系很显著。即性别与疾病指数正相关
无序分类变量 vs 连续型变量 :ANOVA假设我们想要比较不同教育水平的学生在CDA考试成绩上是否存在显著差异。我们有一个无序分类变量“教育水平”(高中、本科、研究生)和一个连续型变量“考试成绩”。
import pandas as pd import statsmodels.api as sm from statsmodels.formula.api import ols# 创建一个DataFrame来存储数据 data = pd.DataFrame({ '教育水平' : ['高中' , '本科' , '本科' , '研究生' , '高中' , '本科' , '研究生' ], '考试成绩' : [80, 90, 85, 95, 75, 88, 92] })# 使用ols函数创建一个线性模型 model = ols('考试成绩 ~ C(教育水平)' , data=data).fit()# 使用anova_lm函数进行方差分析 anova_table = sm.stats.anova_lm(model, typ=2) anova_table
结论 :p = 0.0102<0.05
,拒绝原假设,表明两变量之间的正向关系很显著。教育水平与考试成绩正相关
有序分类变量 vs 连续型变量将连续型变量离散化后当做有序分类,然后用 有序分类变量 VS 有序分类变量的方法
二分类变量 vs 二分类变量 : 检验 联合 Cramer's V一项研究调查了不同性别的成年人对在公众场合吸烟的态度,结果如表所示。那么,性别与对待吸烟的态度之间的相关程度
import numpy as np from scipy.stats import chi2_contingency observed = np.array([[15, 10], [10, 26]]) observed chi2, p, dof, expected = chi2_contingency(observed,correction =False) # correction =False # 卡方值 # P值 # 自由度: # 与原数据数组同维度的对应期望值 chi2, p#(6.3334567901234555, 0.011848116168529757)
结论 :p = 0.0118<0.05
,拒绝原假设,表明两变量之间的正向关系很显著。
phi = np.sqrt(chi2/n)print ("phi's V:" , phi)# phi's V: 0.3222222222222222
卡方检验时有多种指标可表示效应量,可结合数据类型及交叉表格类型综合选择
第二:如果是33,或 4 4表格,建议使用列联系数 ; 第三:如果是n*n(n>4)表格,建议使用校正列联系数 ; 第四:如果是m*n(m不等于n)表格,建议使用Cramer V指标 ; 这里只列出 指标 和 Cramer V指标 的计算,其他计算方式请读者自行研究。
# 计算Cramer's V contingency_table = observed n = contingency_table.sum().sum() phi_corr = np.sqrt(chi2 / (n * min(contingency_table.shape) - 1)) v = phi_corr / np.sqrt(min(contingency_table.shape) - 1)print ("Cramer's V:" , v)# Cramer's V: 0.22878509151645754
二分类变量(有序) 连续型变量:Biserialimport numpy as np from scipy.stats import pearsonr# 生成随机的二元变量 binary_variable = np.random.choice([0, 1], size=100)# 生成随机的连续变量 continuous_variable = np.random.normal(loc=0, scale=1, size=100)# 注:此处的代码未经严格考证,请谨慎使用 def biserial_correlation(binary_variable, continuous_variable): binary_variable_bool = binary_variable.astype(bool) binary_mean = np.mean(binary_variable_bool) binary_std = np.std(binary_variable_bool) binary_variable_norm = (binary_variable_bool - binary_mean) / binary_std corr, _ = pearsonr(binary_variable_norm, continuous_variable) biserial_corr = corr * (np.std(continuous_variable) / binary_std) return biserial_corr# 计算Biserial相关系数 biserial_corr = biserial_correlation(binary_variable, continuous_variable)print ("Biserial相关系数:" , biserial_corr) Biserial相关系数: -0.2061772328681707
无序分类变量 vs 无序分类变量参考
检验
有序分类变量 vs 无序分类变量参考 检验
有序分类变量 vs 有序分类变量 Kendall秩相关系数Kendall秩相关系数也是一种非参数的等级相关度量,类似于Spearman等级相关系数。
import random import numpy as np import pandas as pd np.random.seed(10) df = pd.DataFrame({'品牌知名度排位' :[9,4,3,6,5,8,1,7,10,2], '售后服务质量评价排位' :[8,2,5,4,7,9,1,6,10,3]}) df
pd.Series.corr(df['品牌知名度排位' ], df['售后服务质量评价排位' ],method = 'kendall' ) # Kendall Tau相关系数 # 0.7333333333333333
from scipy.stats import kendalltau# 两个样本数据 x = df['品牌知名度排位' ] y = df['售后服务质量评价排位' ]# 计算Kendall Tau相关系数 correlation, p_value = kendalltau(x, y)print ("Kendall Tau相关系数:" , correlation)print ("p值:" , p_value)# Kendall Tau相关系数: 0.7333333333333333 # p值: 0.002212852733686067
浮生皆纵,恍如一梦,让我们只争朝夕,不负韶华!
下期将为大家带来《统计学极简入门》之 再看t检验、F检验、 检验
8. 再看t检验、F检验、
检验前面在假设检验的部分经学过t检验、F检验、 检验,之所以再看,是想通过纵向对比这几个检验统计量以加深理解:
t检验针对不同的场景,主要分为单样本T检验、独立样本T检验、配对样本T检验:
单样本的t检验主要用于分析一组定量数据 与指定值 的差异,例如检验食盐的实际称重是否不够标重的份量。
单样本T检验需要满足正态分布的假设,若不满足可采用单样本Wilcoxon检验 。
例5.2 检验汽车实际排放是否低于其声称的排放标准
汽车厂商声称其发动机排放标准的一个指标平均低于20个单位。在抽查了10台发动机之后,得到下面的排放数据:17.0 21.7 17.9 22.9 20.7 22.4 17.3 21.8 24.2 25.4
该样本均值为21.13.究竟能否由此认为该指标均值超过20?
分析过程:由于厂家声称指标平均低于20个单位,因此原假设为总体均值等于20个单位(被怀疑对象总是放在零假设)。而且由于样本均值大于20(这是怀疑的根据),把备择假设设定为总体均值大于20个单位
于是我们有了原假设和备择假设
: :
读取数据如下
data = [17.0 , 21.7 , 17.9 , 22.9 , 20.7 , 22.4 , 17.3 , 21.8 , 24.2 , 25.4 ]
分步骤计算过程如下:
步骤一 :计算样本均值
=(17+21.7+...+25.4)/10=21.13
用Python:
x_bar = np.array(data).mean() x_bar# 21.13
步骤二 :计算样本标准差
用Python计算:
s = np.sqrt(((data-x_bar)**2).sum()/len(data)) s# 2.7481084403640255
步骤三 :计算统计量
,其中 为整体均值20,自由度n-1为9
t = (x_bar - 20)/(s/np.sqrt(len(data)-1)) t# 1.2335757753252794
步骤四 :查表或用软件查询p值与
p_value = scipy.stats.t.sf(t,len(data)-1 ) p_value # 0.1243024777589817
结论: 选择显著性水平 0.01 的话,P=0.1243 > 0.05
, 故无法拒绝原假设。具体来说就是该结果无法支持指标均值超过20的备则假设。说明发动机排放指标是不合格的。
对于以上过程,我们也可以用scipy.stats.ttest_1samp
函数,一步到位进行t检验,直接返回的就是t统计量和p值:
import scipy.stats t, pval = scipy.stats.ttest_1samp(a = data, popmean=20,alternative = 'greater' )# 说明 # 单一样本的t检验,检验单一样本是否与给定的均值popmean差异显著的函数,第一个参数为给定的样本,第二个函数为给定的均值popmean,可以以列表的形式传输多个单一样本和均值。 # a 为给定的样本数据 # popmean 为给定的总体均值 # alternative 定义备择假设。以下选项可用(默认为“two-sided”): # ‘two-sided’:样本均值与给定的总体均值(popmean)不同 # ‘less’:样本均值小于给定总体均值(popmean) # ‘greater’:样本均值大于给定总体均值(popmean) print (t, pval)# ''' # P= 0.004793 < 5%, 拒绝原假设,接受备择假设样本 # '''
结论: 选择显著性水平 0.01 的话,P=0.1243 > 0.05
, 故无法拒绝原假设。具体来说就是该结果无法支持指标均值超过20的备则假设。
独立样本的t检验主要用于分析定量数据 和定类数据(2组) 的差异。原理是推论差异发生的概率,从而比较两个平均数的差异是否显著。通俗的说就是用样本均数和已知总体均数进行比较,来观察此组样本与总体的差异性。
例如有一个班的学生身高数据,如果学生的身高服从正态分布,想要研究身高和性别的关系,这个时候就相当于是两个独立样本。
独立样本的T检验也需要满足正态分布 的假设,如果不满足可采用Wilcoxon检验(也称MannWhitney检验); 如果满足但方差不等可采用Welch T检验
计算公式如下:
、 代表两组数据的均值,
、 代表样本数,
、
代表两组数组的方差。
从计算公式能看出来,t越小则两组数据差异性越小。具体多小就根据置信度和自由度查表对比理论统计量的大小得出两组数据差异性是否显著。
例5.6(数据:drug.txt) 检验某药物在实验组的指标是否低于对照组
为检测某种药物对情绪的影响,对实验组的100名服药者和对照组的150名非服药者进行心理测试,得到相应的某指标。需要检验实验组指标的总体均值 是否大于对照组的指标的总体均值 。这里假定两个总体独立地服从正态分布。相应的假设检验问题为:
分析过程:由于目标是检验实验组指标的总体均值 是否大于对照组的指标的总体均值 ,因此选择上侧检验
于是我们有了原假设和备择假设
: :
data = pd.read_table("./t-data/drug.txt" ,sep = ' ' ) data.sample(5 )
ah id 4.4 2 6.8 2 9.6 2 4.8 2 13.2 1
a = data[data['id' ]==1 ]['ah' ] b = data[data['id' ]==2 ]['ah' ]''' H0: 实验组的均值等于对照组 H1: 实验组的均值大于对照组 ''' t, pval = scipy.stats.ttest_ind(a,b,alternative = 'greater' )# 独立样本的T检验,检验两个样本的均值差异,该检验方法假定了样本的通过了F检验,即两个独立样本的方差相同 # 另一个方法是: # stats.ttest_ind_from_stats(mean1, std1, nobs1, mean2, std2, nobs2, equal_var=True) # 检验两个样本的均值差异(同上),输出的参数两个样本的统计量,包括均值,标准差,和样本大小:直接输入样本的描述统计量(均值,标准差,样本数)即可 print(t,pval)# 0.9109168350628888 0.18161186154576608
结论: 选择显著性水平 0.05 的话,p = 0.1816 > 0.05
,无法拒绝H0,具体来说就是该结果无法支持实验组均值大于对照组的备则假设。
配对样本t检验主要用于分析配对定量数据 的差异。
常见的使用场景有:
①同一对象处理前后的对比(同一组人员采用同一种减肥方法前后的效果对比);
②同一对象采用两种方法检验的结果的对比(同一组人员分别服用两种减肥药后的效果对比);
③配对的两个对象分别接受两种处理后的结果对比(两组人员,按照体重进行配对,服用不同的减肥药,对比服药后的两组人员的体重)。
例如,假设一个班上男女生的成绩不存在差异,显著性水平为0.05,可理解为只有5%的概率会出现“男女生成绩差异显著”的情况,若计算出的检验p值若小于0.05,则可以拒绝原假设。反之不能拒绝原假设。
此外,t检验注意事项
①无论哪种t检验、都要数据服从正态或者近似正态分布。正态性的检验方法有:正态图、正态性检验、P-P图/Q-Q图等。
②两个独立样本的t检验,通常需要先进行F检验(方差齐次检验),检验两个独立样本的方差是否相同,若两总体方差相等,则直接用t检验,若不等,可采用t’检验或变量变换或秩和检验等方法。
例5.7(数据: diet.txt) 检验减肥前后的重量是否有显著性差异(是否有减肥效果)
这里有两列50对减肥数据。其中一列数据(变量名before)是减肥前的重量,另一列(变量名after)是减肥后的重量(单位: 公斤),人们希望比较50个人在减肥前和减肥后的重量。
分析过程:这里不能用前面的独立样本均值差的检验,这是因为两个样本并不独立。每一个人减肥后的重量都和自己减肥前的重量有关,但不同人之间却是独立的,所以应该用配对样本检验。同时,由于研究的是减肥前后的重量变化,期望减肥前的重量大于减肥后的重量,所以备择假设是期望减肥前的重量大于减肥后的重量
于是我们有了原假设和备择假设:
: :
步骤一 、计算两组样本数据差值d,即58-50,76-71,69-65,68-76,81-75
d = data['before' ] - data['after' ]
步骤二 、计算差值d的平均值 ,即(-1+0+1+0)/4=0
d_bar = ( d).sum()/len(data)
步骤三 、计算差值d的标准差 ,计算公式为
s_d = np.sqrt(((d -d_bar)**2).sum()/(len(data)-1)) s_d
步骤四 、计算统计量t,计算公式为
t = (d_bar)/(s_d/np.sqrt(len(data))) # 这里mu是0 t#
计算p值
p_value = scipy.stats.t.sf(t, len(data)-1) p_value # 0.0007694243254842176
其中 为理论总体差值均值0,n为样本数。
结论 选择显著性水平 0.05 的话,p = 0.0007 < 0.05
,故应该拒绝原假设。具体来说就是该结果倾向支持减肥前后的重量之差大于零(即减肥前重量大于减肥后,也就是有减肥效果)的备则假设。
同样的,我们用现成的函数stats.ttest_rel
,一步到位进行t检验,直接返回的就是t统计量和p值:
data = pd.read_table("./t-data/diet.txt" ,sep = ' ' ) data.sample(5 )
before after 58 50 76 71 69 65 68 76 81 75
a = data['before' ] b = data['after' ] stats.ttest_rel(a, b,alternative = 'greater' )# #配对T检验,检测两个样本的均值差异,输入的参数是样本的向量 # Ttest_relResult(statistic=3.3550474801424173, pvalue=0.000769424325484219)
结论 选择显著性水平 0.05 的话,p = 0.0007 < 0.05
,故应该拒绝原假设。具体来说就是该结果倾向支持减肥前后的重量之差大于零(即减肥前重量大于减肥后,也就是有减肥效果)的备则假设。
F检验F检验(F-test),最常用的别名叫做联合假设检验(英语:joint hypotheses test),此外也称方差比率检验、方差齐性检验。
用于: 判断两组数据方差是否存在显著差异。
步骤一:分别计算两组样本数据的均值
步骤二:分别计算两组样本数据的标准方差的平方
步骤三:计算两组样本数据标准方差的平方比
,把平方大的作为分子,小的作为分母。
得到F值后根据两组数据的自由度和置信度查表对比,同样的,F值也是越小越说明差异性不显著。
stats模块中虽然没有f检验的函数,但是却有着f分布的生成函数,可以利用其进行f检验:
import numpy as np from scipy.stats import f_oneway# 创建两个样本 sample1 = np.array([1, 2, 3, 4, 5]) sample2 = np.array([2, 4, 6, 8, 10])# 使用 f_oneway 函数进行 F 检验 f_statistic, p_value = f_oneway(sample1, sample2)# 打印检验结果 print ("F statistic:" , f_statistic)print ("p-value:" , p_value)#在上述示例中,我们创建了两个样本 sample1 和 sample2,每个样本包含五个观测值。然后,我们使用 f_oneway 函数对这两个样本进行F 检验。 #f_oneway 函数返回两个值,第一个是 F 统计量,第二个是对应的 p 值。我们可以根据 p 值来判断样本方差是否有显著差异。如果 p值小于设定的显著性水平(通常为 0.05),则可以拒绝原假设,认为样本方差存在显著差异。 #在上述示例中,我们可以得到 F 统计量为 4.0,p 值为 0.078。由于 p 值大于 0.05,我们不能拒绝原假设,即无法认为这两个样本的方差存在显著差异。 #需要注意的是,在使用 f_oneway 函数进行 F 检验时,输入的样本应该是一维数组或列表形式。如果有多个样本,可以将它们作为函数的参数传入。
也可以引入sklearn进行f检验
# 例子1 from sklearn.datasets import make_classification from sklearn.feature_selection import f_classif # 生成样本数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=42)# F检验 F, pval = f_classif(X, y) # 输出结果 print (F) print (pval)# 特征排序(如果不做机器学习可以忽略这一步) indices = np.argsort(F)[-10:] print (indices)#这里我们生成了一个包含10个特征的样本分类数据集,其中5个特征包含区分两类信息,5个特征冗余。 #使用f_classif函数可以计算每个特征的F-score和p值,F-score越高表示该特征越重要。 #最后通过argsort排序,输出最重要的特征索引。 #F检验通过计算每个特征对目标类别的区分能力,来对特征重要性进行评估和排序,是一种常用的过滤式特征选择方法。 # 例子2 import numpy as np from sklearn.feature_selection import f_regression# 创建特征矩阵 X 和目标向量 y X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) y = np.array([1, 2, 3])# 使用 f_regression 函数进行 F 检验 f_values, p_values = f_regression(X, y)# 打印 F 统计量和 p 值 print ("F values:" , f_values)print ("p-values:" , p_values)
例5.10(两总体方差之比的假设检验) 检验修完Python课程的学生是否比修完数据库课程的学生考CDA的成绩方差更大
某高校数据科学专业的学生,修完一门数据库课程的41名学生考CDA的方差
,修完Python课程的31名学生考CDA的方差是 ,这些数据是否表明,修完数据库的学生要比修完Python的学生CDA成绩的方差更大?
分析过程:由于目标是希望修完Python的学生CDA成绩的方差更大,因此选择上侧检验。两总体方差之比用F检验,将方差较大的数据库课程的考试成绩视为总体1
于是我们有了原假设和备择假设
: :
import numpy as np from scipy import stats def f_test_by_s_square(n1, n2, s1_square,s2_square, side ='two-sided' ): "" " 参数 n1 :样本1的数量 n2 :样本2的数量 s1_square:样本1的方差 s2_square:样本2的方差 # # F_value :F统计量的值 # p_value :对应的p值 " "" F_value = s1_square/s2_square F = stats.f(dfn = n1-1, dfd = n2-1) if side=='two-sided' : print ("two-sided" ) p_value = 2*min(F.cdf(F_value), 1-F.cdf(F_value)) return F_value,p_value elif side=='greater' : print ("greater" ) p_value = 1-F.cdf(F_value) return F_value,p_value f_statistic , p_value= f_test_by_s_square(n1=41, n2=31,s1_square=120,s2_square=80,side='greater' )# 打印检验结果 # 选择上侧检验所以side='greater' print ("F statistic:" , f_statistic)print ("p-value:" , p_value)
结论 选择显著性水平 0.05 的话,p = 0.1256 > 0.05,故无法原假设。结果无法支持修完数据库的学生要比修完Python的学生CDA成绩的方差更大的备则假设。
检验卡方检验(chi-square test),也就是χ2检验,是以 分布为基础的一种用途广泛的分析定性数据差异性的方法,通过频数进行检验。
之前假设检验一节中,我们知道卡方检验可以做指定方差和样本方差是否有差异
例5.5 检验某考试中心升级题库后考生分数的方差是否有显著变化
某数据分析师认证考试机构CDA考试中心,历史上的持证人考试分数的方差为 ,现在升级了题库,该考试中心希望新型考题的方差保持在原有水平上,为了研究该问题,收集到了30份新考题的考分组成的样本,样本方差是 ,在 的显著性水平下进行假设检验。
分析过程:由于目标是希望考试分数的方差保持原有水平,因此选择双侧检验
于是我们有了原假设和备择假设
: :
import numpy as np from scipy import stats def chi2test(sample_var, sample_num,sigma_square,side, alpha=0.05): '' ' 参数: sample_var--样本方差 sample_num--样本容量 sigma_square--H0方差 返回值: pval ' '' chi_square =((sample_num-1)*sample_var)/(sigma_square) p_value = None if side == 'two-sided' : p = stats.chi2(df=sample_num-1).cdf(chi_square) p_value = 2*np.min([p, 1-p]) elif side == 'less' : p_value = stats.chi2(df=sample_num-1).cdf(chi_square) elif side == 'greater' : p_value = stats.chi2(df=sample_num-1).sf(chi_square) return chi_square,p_value p_value = chi2test(sample_var = 162, sample_num = 30, sigma_square = 100,side='two-sided' )print ("p值:" , p_value)# p值: 0.07213100536907469
结论: 选择显著性水平 0.05 的话,P=0.0721 > 0.05
, 故无法拒绝原假设。具体来说就是不支持方差发生了变化的备则假设。换句话说新题型的方差依然保持在原有水平上
那么,卡方检验还有什么应用呢?
统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,如果卡方值越大,二者偏差程度越大;反之,二者偏差越小;若两个值完全相等时,卡方值就为0,表明理论值完全符合。
卡方值计算公式:
①卡方优度检验 对一列数据进行统计检验,分析单个分类变量实际观测的比例与期望的比例是否一致。
②配对卡方 研究实验过程中,用不同方法检测同一批人,看两个方法的效果是否有显著差异。
③ 交叉表卡方
研究两组分类变量的关系:如性别与看不看直播是否有关系。
例7.5(交叉表卡方):性别与对待吸烟的态度之间的相关性 一项研究调查了不同性别的成年人对在公众场合吸烟的态度,结果如表所示。那么,性别与对待吸烟的态度之间的相关程度
python中stats模块,同样有卡方检验的计算函数
from scipy.stats import chi2_contingency import numpy as np data = np.array([[15,10], [10,26]]) chi2, p, dof, expected = chi2_contingency(data,correction =False)print (f'卡方值={chi2}, p值={p}, 自由度={dof}' )# 卡方值=6.3334567901234555, p值=0.011848116168529757, 自由度=1
结论 :p = 0.0118<0.05
,拒绝原假设,表明两变量之间的正向关系很显著。
sklearn中的特征选择中也可以进行卡方检验。
from sklearn.feature_selection import chi2 import numpy as np# 假设我们有一个包含100个样本和5个特征的数据集 X = np.random.randint(0, 10, (40, 5)) y = np.random.randint(0, 2, 40)# 使用chi2函数计算特征变量与目标变量之间的卡方统计量和p值 chi2_stats, p_values = chi2(X, y)# 打印每个特征的卡方统计量和p值 for i in range(len(chi2_stats)): print (f"Feature {i+1}: chi2_stat = {chi2_stats[i]}, p_value = {p_values[i]}" )#在上面的例子中,我们生成了一个包含100个样本和5个特征的随机数据集。然后,我们使用chi2函数计算每个特征与目标变量之间的卡方统计量和p值。最后,我们打印出每个特征的卡方统计量和p值。 #根据卡方统计量和p值,我们可以判断每个特征与目标变量之间的关联程度。如果卡方统计量较大且p值较小,则说明特征与目标变量之间存在显著关联,可以考虑选择该特征作为重要的特征进行建模。
一文看懂A/B测试(含Python代码实现流程、假设检验原理及2个案例) 前面学完了统计学的基础内容,以及t检验、F检验、卡方检验等。本节我们尝试再用“MVP”的思路来梳理A/B测试:实施的流程、假设检验原理(z检验、t检验应用场景的区别)及分组的注意事项(设计AA分组对比原分组的分布以确保分组的科学性),最后用2个小案例结合Python代码来演示假设检验的过程。
AB测试是一种常用的实验设计方法,用于
比较两个或多个不同的版本(例如产品、网页设计、广告等)在某个指标上的表现差异 。而假设检验是AB测试的统计分析方法 ,用于判断这些差异是否具有统计学意义。
(2) 用均值之差 或者 比例之差作为检验统计量 z检验 或者 t检验,并计算统计量及p值 (1) H0假设:A组转化率等于B组转化率 H1假设:A组转化率不等于B组转化率 (2) 用均值之差t检验 或者 比例之差z检验; 并计算统计量及p值 (3) 判断p值是否小于显著性水平0.05,判断是否拒绝H0 案例9-1 使用基于均值的假设检验进行AB测试 # 随机生成两组样本数据 import numpy as npfrom scipy import stats# 假设有两个版本 A 和 B # 生成样本数据,这里使用正态分布作为例子 np.random.seed(0 ) sample_A = np.random.normal(loc=91 , scale=4 , size= 1000 ) sample_B = np.random.normal(loc=95 , scale=4 , size= 1000 )# 计算样本均值和标准差 mean_A = np.mean(sample_A) mean_B = np.mean(sample_B) std_A = np.std(sample_A) std_B = np.std(sample_B)
步骤1: 提出原假设H0和备择假设H1
H0:版本 A 和 B 在统计上存在显著差异
H2:版本 A 和 B 在统计上没有显著差异
步骤2: 使用均值之差的t检验,计算出t统计量的值和P值如下
# 假设零假设为版本 A 和 B 的均值相等 # 使用独立样本 t 检验进行假设检验 t_statistic, p_value = stats.ttest_ind(sample_A, sample_B) print(t_statistic, p_value)
-24.206499153286355 9.893622835346878e-114
步骤3: 进行假设检验
# 步骤5: 判断结果 alpha = 0.05 # 设置显著性水平 if p_value print("拒绝零假设(无差异),版本 A 和 B 在统计上存在显著差异" )else : print("接受零假设(无差异),版本 A 和 B 在统计上没有显著差异" )
拒绝零假设(无差异),版本 A 和 B 在统计上存在显著差异
值得注意的是,通常情况下我们在做AB测试前需要做AA测试,也就是从A里面通过不同的抽样方式选定一定样本AA,再与A进行测试
AA测试(简单随机抽样) # 简单随机抽样 sample_AA1 = np.random.choice(sample_A,int(len(sample_A)*0.2 ))
# 假设零假设为版本 A 和 B 的均值相等 # 使用独立样本 t 检验进行假设检验 t_statistic, p_value = stats.ttest_ind(sample_A, sample_AA1)# 步骤5: 判断结果 alpha = 0.05 # 设置显著性水平 if p_value print(f"p = {p_value} )else : print(f"p = {p_value} > 0.05,接受零假设(无差异),版本 A 和 AA1 在统计上没有显著差异" )
p = 0.8914256267444793 > 0.05,接受零假设(无差异),版本 A 和 AA1 在统计上没有显著差异
import seaborn as snsimport matplotlib.pyplot as plt# 绘制 sample_A 和 sample_AA, 的分布曲线图 plt.figure(figsize=(10
, 6 )) sns.histplot(sample_A, kde=True , color='blue' , label='Sample A' ) sns.histplot(sample_AA1, kde=True , color='orange' , label='Sample AA1' ) plt.xlabel('Value' ) plt.ylabel('Frequency' ) plt.title('Distribution of Sample A and Sample AA' ) plt.legend() plt.show()
AA测试(分层抽样) ## 分层抽样 layers = np.repeat(['A' ,'B' ,'C' ,'D' ,'E' ], 200 )# 在每个分层中抽样 s1 = np.random.choice(sample_A[layers=='A' ], size=40 ) s2 = np.random.choice(sample_A[layers=='B' ], size=40 ) s3 = np.random.choice(sample_A[layers=='C' ], size=40 ) s4 = np.random.choice(sample_A[layers=='D' ], size=40 ) s5 = np.random.choice(sample_A[layers=='E' ], size=40 ) sample_AA2 =np.concatenate([s1, s2, s3, s4, s5])
# 假设零假设为版本 A 和 B 的均值相等 # 使用独立样本 t 检验进行假设检验 t_statistic, p_value = stats.ttest_ind(sample_A, sample_AA2)# 步骤5: 判断结果 alpha = 0.05 # 设置显著性水平 if p_value print(f"p = {p_value} )else : print(f"p = {p_value} > 0.05,接受零假设(无差异),版本 A 和 AA2 在统计上没有显著差异" )
p = 0.6702407975402769 > 0.05,接受零假设(无差异),版本 A 和 AA2 在统计上没有显著差异
import seaborn as snsimport matplotlib.pyplot as plt# 绘制 sample_A 和 sample_AA, 的分布曲线图 plt.figure(figsize=(10 , 6 )) sns.histplot(sample_A, kde=True , color='blue' , label='Sample A' ) sns.histplot(sample_AA2, kde=True , color='orange' , label='Sample AA2' ) plt.xlabel('Value' ) plt.ylabel('Frequency' ) plt.title('Distribution of Sample A and Sample AA2' ) plt.legend() plt.show()
AA测试(系统抽样) # 系统抽样 k = 5 # 每隔3个取一个 sample_AA3 = sample_A[::k]
# 假设零假设为版本 A 和 B 的均值相等 # 使用独立样本 t 检验进行假设检验 t_statistic, p_value = stats.ttest_ind(sample_A, sample_AA3)# 步骤5: 判断结果 alpha = 0.05 # 设置显著性水平 if p_value print(f"p = {p_value} )else : print(f"p = {p_value} > 0.05,接受零假设(无差异),版本 A 和 AA3 在统计上没有显著差异" )
p = 0.4730028024029992 > 0.05,接受零假设(无差异),版本 A 和 AA3 在统计上没有显著差异
import seaborn as snsimport matplotlib.pyplot as plt# 绘制 sample_A 和 sample_AA, 的分布曲线图 plt.figure(figsize=(10 , 6 )) sns.histplot(sample_A, kde=True , color='blue' , label='Sample A' ) sns.histplot(sample_AA3, kde=True , color='orange' , label='Sample AA3' ) plt.xlabel('Value' ) plt.ylabel('Frequency' ) plt.title('Distribution of Sample A and Sample AA3' ) plt.legend() plt.show()
AB测试 # 假设零假设为版本 A 和 B 的均值相等 # 使用独立样本 t 检验进行假设检验 t_statistic, p_value = stats.ttest_ind(sample_A, sample_B)# 步骤5: 判断结果 alpha = 0.05 # 设置显著性水平 if p_value print(f"p = {p_value} )else : print(f"p = {p_value} > 0.05,接受零假设(无差异),版本 A 和 B 在统计上没有显著差异" )
p = 9.893622835346878e-114 < 0.05,拒绝零假设(无差异),版本 A 和 B 在统计上存在显著差异
import seaborn as snsimport matplotlib.pyplot as plt# 绘制 sample_A 和 sample_B 的分布曲线图 plt.figure(figsize=(10 , 6 )) sns.histplot(sample_A, kde=True , color='blue' , label='Sample A' ) sns.histplot(sample_B, kde=True , color='orange' , label='Sample B' ) plt.xlabel('Value' ) plt.ylabel('Frequency' ) plt.title('Distribution of Sample A and Sample B' ) plt.legend() plt.show()
在这个例子中,我们假设有两个版本 A 和 B,通过生成正态分布的样本数据进行比较。然后计算两个样本的均值和标准差,并使用独立样本 t 检验进行假设检验。根据显著性水平alpha 的设定,判断是否拒绝零假设,进而得出结论。
案例:基于假设检验的支付宝点击率策略提升A-B测试效果分析 import pandas as pdimport numpy as npimport matplotlib.pyplot as plt %matplotlib inline
#加载数据 data = pd.read_csv('./data/audience_expansion/effect_tb.csv' ,header = None ) data.columns = ["dt" ,"user_id" ,"label" ,"dmp_id" ]# dmp_id:营销策略编号(源数据文档未做说明,这个根据情况设定为1.对照组,2.营销策略一,3.营销策略二) # user_id:支付宝用户id # label:用户当天是否点击活动广告(0:未点击,1:点击) data = data[["user_id" ,"label" ,"dmp_id" ]]
data = data.drop_duplicates() #删除重复值 data.head(3 )
user_id label dmp_id 0 1 0 1 1 1000004 0 1 2 1000004 0 2
计算3组营销策略的点击率的平均值 根据原始数据计算3营销策略的点击率如下:
df = data.pivot_table(index = "dmp_id" ,columns = "label" ,values = "user_id" ,aggfunc = "count" ,margins = True ) df['crt' ] = df[1 ] / df['All' ] df
label 0 1 All crt dmp_id 1 1881745 23918 1905663 0.012551 2 404811 6296 411107 0.015315 3 307923 8282 316205 0.026192 All 2594479 38496 2632975 0.014621
我们可以得到:
对照组 (dmp_id=1)的点击率0.012551 , 策略1组(dmp_id=2)的点击率0.015315 , 策略2组(dmp_id=2)的点击率0.026192 , df['crt' ][1 :3 ]-0.012551 # 2
dmp_id 2 0.002764 3 0.013641 Name: crt, dtype: float64
从点击率来看,策略一和策略二在对照组的基础上都有一定的提升。
其中策略一提高了0.2个百分点,策略二提高了1.3个百分点,只有策略二满足了我们对点击率提升最小值1个百分点的要求
接下来需要进行假设验证,来看看策略二的点击率提升是否显著
假设检验进行判断 记对照组点击率为p1,策略二点击率为p2,则:
(1) H0假设: p1>=p2 策略2组点击率大于等于对照组点击率 H1假设:p1< p2 策略2组点击率小于对照组点击率 (5) 判断p值是否小于显著性水平0.05,判断是否拒绝H0 import numpy as npimport scipy.stats as statsdef proportion_test (p1, p2, n1, n2, side='two-sided' ) : """ 参数: p1: 样本1的比例 p2: 样本2的比例 n1: 样本1的数量 n2: 样本2的数量 side: 假设检验的方向,可选'two-sided'(双侧检验,默认), 'greater'(右侧检验), 'less'(左侧检验) 返回值: z_value: Z统计量的值 p_value: 对应的p值 """ p = (p1 * n1 + p2 * n2) / (n1 + n2) se = np.sqrt(p * (1 - p) * (1 / n1 + 1 / n2)) z_value = (p1 - p2) / se if side == 'two-sided' : p_value = 2 * (1 - stats.norm.cdf(np.abs(z_value))) elif side == 'greater' : p_value = 1 - stats.norm.cdf(z_value) elif side == 'less' : p_value = stats.norm.cdf(z_value) else : raise ValueError("Invalid side value. Must be 'two-sided', 'greater', or 'less'." ) return z_value, p_value
p1 = df.loc[1 ,'crt' ] p2 = df.loc[3 ,'crt' ] n1 = df.loc[1 ,'All' ] n2 = df.loc[3 ,'All' ] z_value, p_value = proportion_test(p1, p2, n1, n2, side='less' )# 选择双侧检验 alternative = 'two-sided' print("Z_value:" , z_value) print("p_value:" , p_value)
Z_value: -59.44168632985996 p_value: 0.0
# 直接用 sp.proportions_ztest 函数也可以,注意带入的是人数而非比例 import statsmodels.stats.proportion as sp p1 = df.loc[1 ,1 ] p2 = df.loc[3 ,1 ] n1 = df.loc[1 ,'All' ] n2 = df.loc[3 ,'All' ] z_value, p_value = sp.proportions_ztest([p1, p2],[n1, n2], alternative = "smaller" )# 选择双侧检验 alternative = 'two-sided' print("Z_value:" , z_value) print("p_value:" , p_value)
Z_value: -59.44168632985996 p_value: 0.0
可以看到,p约等于0 < 0.05。所以拒绝原假设,认为策略2点击率的提升在统计上是显著的。两种营销策略中,策略二对广告点击率有显著提升效果,因而在两组营销策略中应选择第二组进行推广
至此,统计学的描述性统计、推断统计基本告一段落,剩下的贝叶斯、线性回归、逻辑回归请读者自行查阅资料进行学习,我们下个系列见!
(PS:可以在评价中写下你想学的系列,包括不限于SQL、Pandas、Julia、机器学习、数学建模、数据治理)
致谢《统计学极简入门》图文系列教程的写作过程中参考了诸多经典书籍,包括:
人大统计学教授吴喜之老师的 《统计学:从数据到结论》;
浙大盛骤教授的 《概率论与数理统计》;
辛辛那提大学 David R. Anderson的 《商务经济与统计》;
北海道大学的马场真哉的 《用Python动手学统计学》 ;
千叶大学研究院教授栗原伸一的《统计学图鉴》;
前阿里巴巴产品专家徐小磊的知乎:磊叔-数据化运营;
知乎旧梦的文章T检验、F检验、卡方检验详细分析及应用场景总结;
csdn文章T检验、卡方检验、F检验;
以及CDA认证考试中心 提供的部分案例数据集
在此一并感谢以上内容的作者!
一死生为虚诞,齐彭殇为妄作。各位加油!