数据科学 Python
EDA:描述性统计——对样本的客观描述。
实质:由样本去推断总体的过程。
统计推断:参数估计和假设检验。
而统计推断离不开概率密度函数。
概率密度函数
表示连续随机变量X落在各值附近的可能性。
X一次抽样落入某区间的概率=概率密度函数在该区间上的积分
常见的概率密度函数有:
- 正态分布
- t-分布
-
正态分布
正态分布函数是一个以均值为对称轴的钟形曲线,由均值和标准差两个独立参数控制。

均值=0,标准差=1,标准正态分布服从高斯分布的随机变量:其落入均值加减两倍标准差范围内的概率是95.4%中心极限定理
设X1,…,Xn是某一个均值,标准差为的总体的n个独立随机样本,则对于一个大的n(n>=30),无论总体分布是否为正态分布,都有近似 。
卡方分布

形状与自由度有关,n个服从标准正态分布的独立随机变量的平方和服从自由度为n的卡方分布。t-分布

学生t分布:曲线形态也与自由度有关,而t分布的自由度是样本容量减1,与样本容量有关。
N<30,自由度n-1的t-分布
N≥30,高斯分布(中心极限定理)
均值估计样本统计量(statistics)描述
总体参数(parameters)描述
均值,标准差
基于样本的统计量而对总体分布的参数进行估计是参数估计。
最基本的参数估计:均值和方差估计中心极限定理
点估计:样本的统计就是总体均值的无偏估计。
区间估计:在一个给定的置信水平alpha下,确定出置信区间,该区间会以alpha的概率包含总体均值。
import numpy as npimport pandas as pdfrom scipy import statsnp.random.seed(1234)my_data1=stats.poisson.rvs(loc=10,mu=60,size=3000) # 生成一个规定均值的泊松分布pd.Series(my_data1).hist().get_figure().showprint('第一个分布的均值是:70,\t统计平均是:',my_data1.mean())my_data2=stats.poisson.rvs(loc=10,mu=15,size=6000)pd.Series(my_data2).hist().get_figure().showprint('第二个分布的均值是:25,统计平均是:',my_data2.mean())my_data=np.concatenate((my_data1,my_data2)) # 一个典型的 bi-model 分布,以这 9000 个数作为总体print('总体的均值为: ',my_data.mean())sample_data=np.random.choice(a=my_data,size=100) # 从中随机抽取 100 个做样本print('样本的均值为: ',sample_data.mean())


point_estimates=[]for x in range(500): #500 次循环sample=np.random.choice(a=my_data,size=100) # 每次随机抽样 100 个样本point_estimates.append(sample.mean())pd.DataFrame(point_estimates).hist(bins=40) # 均值大致呈钟型分布print('样本均值的均值为: ', np.array(point_estimates).mean())


sample_size=100sample=np.random.choice(a=my_data,size=sample_size)sigma=sample.std()/(sample_size)**0.5stats.t.interval(alpha=0.95, # 置信水平 confidence leveldf=sample_size-1, # 自由度 Degrees of freedomloc=sample.mean(),scale=sigma)# 返回拥有 95% 置信水平的置信区间
方差估计
设X1,…,Xn是某一个均值,标准差为的总体的随机样本,在样本量为n的所有随机样本中,样本方差S2是的无偏估计
即
其中不同的数据分组之间做比较
比较测试组和对照组到底有没有差异
A/B Testing中控制因素到底对观察变量有没有影响假设检验
第一步:提出假设
第二步:验证是否可以接受假设
零假设(null hypothesis): H0,需要检验的假设。总体的均值等于;
- 测试组和对照组来源于均值相等的总体;
- 控制因素对观察变量没有影响,A组和B组数据同分布;
替代假设(alternative hypothesis): H1(或Ha),某种意义上与H0相反的假设。
- 总体的均值不等于;
- 测试组和对照组来源于均值不相等的总体;
- 控制因素对观察变量有影响,A组和B组数据不同分布;
| | | 真实性 | |
| —- | —- | —- | —- |
|
| | H0 | H1 | | 判定 | 接受H0 | | II型错误 | | | 拒绝H0 | I型错误 | |
单样本均值检验
import numpy as npimport pandas as pdfrom scipy import statsimport matplotlib.pyplot as pltfrom scipy.stats import tnp.random.seed(1234)my_data1=stats.poisson.rvs(loc=10,mu=60,size=3000) # 生成一个规定均值的泊松分布#pd.Series(my_data1).hist().get_figure().show#print(' 第一个分布的均值是:70,\t 统计平均是:',my_data1.mean())my_data2=stats.poisson.rvs(loc=10,mu=15,size=6000)#pd.Series(my_data2).hist().get_figure().show#print(' 第二个分布的均值是:25,统计平均是:',my_data2.mean())my_data=np.concatenate((my_data1,my_data2))# 一个典型的 bi-model 分布,我们以这 9000 个数作为总体#print(' 总体的均值为: ',my_data.mean()) # 假装我们不知道# 现在根据样本,验证 H0: 总体的均值是 47.5# 这是单样本双边 t 检验,one-sample t-testprint('空假设 H0 是:总体的均值是 47.5 \n')sample_data=np.random.choice(a=my_data,size=100) # 从中随机抽取 100 个做样本t_statistic,p_value=stats.ttest_1samp(a=sample_data,popmean=47.5)print('从样本构造的 t 统计量 = ',t_statistic)#t 的绝对值越大,p 值越小,可参见下面的 t-分布图print('单样本双边检验的 p = ',p_value)# 画一下样本容量为 100 时的 t 分布曲线df=100-1x = np.linspace(stats.t.ppf(0.00000001,df),stats.t.ppf(0.99999999,df),100)#ppf 函数是 CDF 的逆函数,用来求分位点plt.plot(x, t.pdf(x, df)) #pdf 生成概率密度函数表plt.plot((t_statistic,t_statistic),(-0.01,0.4),'-.r')str_legend=('t distribution','calculated t')plt.legend(str_legend)plt.show()

x = np.linspace(stats.t.ppf(0.00000001,df),stats.t.ppf(0.99999999,df),100)#ppf 函数是 CDF 的逆函数,用来求分位点plt.plot(x, t.pdf(x, df)) #pdf 生成概率密度函数表plt.plot((t_statistic,t_statistic),(-0.01,0.4),'-.r')str_legend=('t distribution','calculated t')plt.legend(str_legend)x_025=stats.t.ppf(0.025,df)# 注意:同样选取 alpha=0.5,做双边 test 时要给左、右两侧各分配 0.25plt.plot((x_025,x_025),(-0.01,0.4),'--g') # 这根线是双边检验的左阈值x_975=stats.t.ppf(0.975,df)plt.plot((x_975,x_975),(-0.01,0.4),'--g') # 这根线是双边检验的右阈值#print(x_975)rect1=plt.Rectangle((x_025,0),x_975*2,0.5,color='g',alpha=0.25)plt.gca().add_patch(rect1)rect2=plt.Rectangle((x_975,0),5,0.5,color='r',alpha=0.25)plt.gca().add_patch(rect2)rect3=plt.Rectangle((x_025,0),-5,0.5,color='r',alpha=0.25)plt.gca().add_patch(rect3)#plt.ylim(-0.02,0.5)plt.text(x_025,0.4,'accept region') # 图片上不支持中文#plt.savefig('111.png') # 不支持中文文件名plt.show()

print('p = ',p_value,'\n')alpha=0.05if p_value>=0.05:print('\033[1;31m 接受 \033[0m H0')else:print('\033[1;31m 拒绝\033[0m H0, 即总体的均值不等于 47.5,此时错误拒绝 H0 的概率为',p_value,'小于显著性水平')

import numpy as npimport pandas as pdfrom scipy import statsfrom scipy.stats import timport matplotlib.pyplot as pltstr_legend=('t distribution','alpha=0.05 threshod','alpha=0.025 threshold',\'alpha=0.975 threshold','real t')# 画一下样本容量为 100 时的 t 分布曲线df=100-1#a=0.05 # 自定义的显著性水平x = np.linspace(stats.t.ppf(0.00000001,df),stats.t.ppf(0.99999999,df),100)#ppf 函数是 CDF 的逆函数,用来求分位点plt.plot(x, t.pdf(x, df), alpha=1)# 注意此 alpha 是 plot 方法中的透明度参数,不是显著性参数x_05=stats.t.ppf(0.05,df) #p(t<x_05)=0.05#print(x_05)plt.plot((x_05,x_05),(-0.01,0.4),'--') # 这根线是单边检验的阈值x_025=stats.t.ppf(0.025,df)# 注意:同样选取 alpha=0.5,做双边 test 时要给左、右两侧各分配 0.25plt.plot((x_025,x_025),(-0.01,0.4),'--g') # 这根线是双边检验的左阈值x_975=stats.t.ppf(0.975,df)plt.plot((x_975,x_975),(-0.01,0.4),'--g') # 这根线是双边检验的右阈值t_real=stats.t.ppf(p_value/2,df)# 上一个 cell 中我们做的是双边 t-test,因此这里找分位点时,p 值要除以 2print('从样本获得的 t 统计量是',t_real)plt.plot((x_real,x_real),(-0.01,0.4),'-.r')# 各阈值截断的曲线下面积对应 I 型错误率plt.legend(str_legend)plt.show()
I型错误率达到多少时拒绝空假设?
双样本均值检验
- t-检验
- 构造统计量
np.random.seed(1234)my_data1=stats.poisson.rvs(loc=10,mu=60,size=3000) # 生成一个规定均值的泊松分布#pd.Series(my_data1).hist().get_figure().show#print(' 第一个分布的均值是:70,\t 统计平均是:',my_data1.mean())my_data2=stats.poisson.rvs(loc=10,mu=15,size=6000)#pd.Series(my_data2).hist().get_figure().show#print(' 第二个分布的均值是:25,统计平均是:',my_data2.mean())my_data=np.concatenate((my_data1,my_data2))# 一个典型的 bi-model 分布,我们以这 9000 个数作为总体my_sample={}for n in range(2):my_sample[n]=np.random.choice(a=my_data,size=100) # 从中随机抽取 100 个做样本print('第',n,'组样本的均值为',my_sample[n].mean())print('根据样本均值,能否下结论说两组样本来源的总体其均值不相等呢?')# 需进行 two sample t-test#H0: 两样本均值相等

两组的统计方差、样本容量均相等可以使用ttest-ind函数# 能否下结论说两组样本来源的总体其均值不相等呢?# 需进行 two sample t-test#H0: 两样本均值相等alpha=0.01 # 设置显著性水平t_statistic,p_value=stats.ttest_rel(a=my_sample[0],b=my_sample[1])#sample size 相等的双样本均值比较print('t = ',t_statistic)print('p = ',p_value)if p_value<=alpha:print('\033[1;31m 拒绝 \033[0m H0:两样本来源的总体均值相等 ')else:print('\033[1;31m 接受 \033[0m the H0: 两样本来源的总体均值相等')
卡方检验应用
卡方检验:检验类别数据在各类上的分布是否与给定的概率分布一致。
【例】Titanic船难中,幸存者中是否真的是女性居多。
全球性别分布VS登船人员中的性别分布
研究对象——幸存者中的性别分布
H0:幸存者中的性别分布与船上所有人的性别分布一致
替代假设则是不一致。#Titanic 数据存活人的类别分析# 探究性别与存活是否为关联事件# 如果性别与存活与否无关,则存活人群中的性别比应与全体人的一致,全体是什么?# 是船上所有人,还是所有人(即 0.5:0.5)import pandas as pdimport numpy as npfrom scipy import statsfrom scipy.stats import chi2from matplotlib import pyplot as plttitanic = pd.read_csv("C:\Python\Scripts\my_data\Titanic.csv")# 对全体做性别统计mask1=titanic['Sex']=='male'mask2=titanic['Sex']=='female'p=np.array([sum(mask1)/(sum(mask1)+sum(mask2)),sum(mask2)/(sum(mask1)+sum(mask2))])print(p)mask_survived=titanic['Survived']==0# 如果反过来做,活着的人中,性别比满足 p 吗?请同学们验证my_population=titanic.loc[mask_survived,'Sex']print(type(my_population))pop_size=my_population.count()print('总体大小是 ',pop_size)sample=my_populationE=pop_size*pprint( '预期的男、女个数是 ',E)mask1=sample=='male'mask2=sample=='female'my_set1=sample[mask1]my_set2=sample[mask2]O=np.array([len(my_set1),len(my_set2)])print('实际的男女个数是 ',O)chi_squard,p_value=stats.chisquare(f_obs=O,f_exp=E)print(chi_squard,p_value)a=0.05df=1 # 只有两个类别,因此自由度是 2-1=1if p_value<=a:print('我们 \033[1;31m 拒绝 \033[0m 男性女性具有相同死亡率的假设.')else:print('我们 \033[1;31m 接受 \033[0m 男性女性具有相同死亡率的假设')
统计检验
- 提出空假设和替代假设
- 选择显著性水平,进行合适的检验
- 将p值与显著性水平比较
- 接受或拒绝空假设
p值:基于当前样本和空假设,现有统计量落入当前值及以外区域的概率。
显著性水平alpha:拒绝接受空假设的门限。
p值 > alpha,接受域
p值

