数据特征分析-正太分布
期望值,即在一个离散性随机变量试验中每次可能结果的概率乘以其结果的总和。
若随机变量X服从一个数学期望为μ、方差为σ^2的正态分布,记为N(μ,σ^2),其概率密度函数为正态分布的期望值μ决定了其位置,其标准差σ决定了分布的幅度。当μ = 0、σ = 1时的正态分布是标准正态分布。正态分布的图示如下:
在实际场景中,数据可能不完全符合正态分布,因此需要对数据进行检验,验证是否符合正态分布。
一、通过直方图初步判断
df = pd.DataFrame(np.random.randn(1000)+2,columns=['value']) fig,axes = plt.subplots(1,2,figsize = (10,4)) ax1 = axes[0] ax1.scatter(df.index,df.values) ax2 = axes[1] df.hist(bins = 20,alpha = 0.7,ax = ax2) df.plot(kind = 'kde',secondary_y = True,ax = ax2) #使用y轴作为副坐标轴
二、通过qq图判断
qq图通过把测试样本数据的分位数与已知分布进行比较,从而检验数据的分布情况。
qq图是一种散点图,对应于正态分布的qq图,就是有标准正态分布的分位数为横坐标、样本值为纵坐标的散点图。
参考直线:四分之一分位点和四分之三分位点,看散点是否落在这条线附近。
qq图绘制思路:
①数据清洗后进行排序(x(1)<x(2)<...<x(n))
②排序后,计算出每个数据对应的百分位p(i),即第i个数据x(i)为p(i)分位数,其中p(i) = (i-0.5)/n(pi有多种算法,该种最常用)
③绘制直方图 + qq 图,直方图作为参考
# qq图判断 df = pd.DataFrame(np.random.randn(1000)+2,columns=['value']) mean = df['value'].mean() std = df['value'].std() print('平均值为%.2f,标准差为%.2f'%(mean,std)) df.sort_values('value',inplace = True) df_r = df.reset_index(drop = False) #t变为DataFrame df_r['p'] = (df_r.index-0.5)/len(df_r) df_r['q'] = (df_r['value']-mean)/std print(df_r.head()) fig,axes = plt.subplots(1,3,figsize = (20,4)) des = df['value'].describe() # x1,y1 = 0.25,des['25%'] # x2,y2 = 0.75,des['75%'] ax1 = axes[0] ax1.scatter(df.index,df['value']) ax2 = axes[1] df['value'].hist(bins = 20,ax = ax2) df['value'].plot(kind='kde',secondary_y = True,ax = ax2) ax3 = axes[2] ax3.plot(df_r['p'],df_r['value'],'b') # ax3.plot([x1,x2],[y1,y2],'r') ax3.plot([0.25,0.75],[des['25%'],des['75%']],'r')
三、k-s检验
k-s是比较一个频率分布f(x)与理论分布g(x)的检测方法,将样本数据的累计频率分布与特定的理论分布(比如正态分布)进行比较,如果两者差距小,则推论样本分布取自某特定分布。
H0:样本的总体分布 服从 某特定分布
H1:样本的总体分布 不服从 某特定分布
f(x):样本的累计分布函数
g(x):理论分布的分布函数
D:f(x)-g(x)的绝对值的最大值,即max(abs(f(x)-g(x)))
根据D与D(u,a)比较,如果p>0.05则接受H0,p<0.05则拒绝H0接受H1.
from scipy import stats data = np.random.randint(70,80,100) df = pd.DataFrame(data,columns=['value']) u = df['value'].mean() #求均值 std = df['value'].std() #求标准差 stats.kstest(df['value'],'norm',(u,std)) # KstestResult(statistic=0.12748380545258786, pvalue=0.07085249921876394) # 结果中pvalue=0.07,大于0.05
k-s检验的推导过程
df = pd.DataFrame(data,columns=['value']) u = df['value'].mean() #求均值 std = df['value'].std() #求标准差 print('样本均值%.2f,标准差%.2f'%(u,std)) s = df['value'].value_counts().sort_index() df_s = pd.DataFrame({'血糖浓度':s.index,'频数':s.values}) df_s['累计频数'] = df_s['频数'].cumsum() df_s['累计频率'] = df_s['累计频数']/df_s['频数'].sum() df_s['标准化取值'] = (df_s['血糖浓度'] - u)/std df_s['理论分布'] = [0.0764,0.1314,0.2090,0.3085,0.4247,0.5438,0.6628,0.7673,0.8508,0.9099] #根据标准化取值查询正态分布表得到 df_s['D'] = abs(df_s['累计频率'] - df_s['理论分布']) dmax = df_s['D'].max() print('实际观测D值为%.4f'%dmax) df_s['累计频率'].plot(style = '--r') df_s['理论分布'].plot(style = '--g') plt.legend(loc = 'upper left') #红色虚线表示累计频率、绿色虚线表示理论分布的注释位置 # 样本均值74.64,标准差3.23 # 实际观测D值为0.1110
根据D值为0.11,查询显著性水平表,可得知p>0.1,即满足正态分布。