数据科学 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 np
import pandas as pd
from scipy import stats
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 个数作为总体
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=100
sample=np.random.choice(a=my_data,size=sample_size)
sigma=sample.std()/(sample_size)**0.5
stats.t.interval(alpha=0.95, # 置信水平 confidence level
df=sample_size-1, # 自由度 Degrees of freedom
loc=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 np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
from scipy.stats import 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 个数作为总体
#print(' 总体的均值为: ',my_data.mean()) # 假装我们不知道
# 现在根据样本,验证 H0: 总体的均值是 47.5
# 这是单样本双边 t 检验,one-sample t-test
print('空假设 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-1
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)
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.25
plt.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.05
if 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 np
import pandas as pd
from scipy import stats
from scipy.stats import t
import matplotlib.pyplot as plt
str_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.25
plt.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 值要除以 2
print('从样本获得的 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 pd
import numpy as np
from scipy import stats
from scipy.stats import chi2
from matplotlib import pyplot as plt
titanic = 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_population
E=pop_size*p
print( '预期的男、女个数是 ',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.05
df=1 # 只有两个类别,因此自由度是 2-1=1
if p_value<=a:
print('我们 \033[1;31m 拒绝 \033[0m 男性女性具有相同死亡率的假设.')
else:
print('我们 \033[1;31m 接受 \033[0m 男性女性具有相同死亡率的假设')
统计检验
- 提出空假设和替代假设
- 选择显著性水平,进行合适的检验
- 将p值与显著性水平比较
- 接受或拒绝空假设
p值:基于当前样本和空假设,现有统计量落入当前值及以外区域的概率。
显著性水平alpha:拒绝接受空假设的门限。
p值 > alpha,接受域
p值