數據特徵分析 正態性檢驗

關於正態分佈是統計學中最常見的概論分佈。而正態性檢驗,是利用利用觀測數據判斷總體是否服從正態分佈的檢驗,它是統計判決中重要的一種特殊的擬合優度假設檢驗。

關於正態性檢驗的方法主要有以下三種:直方圖初判,QQ圖判斷,K-S檢驗。下面咱們一一瞭解:

注:認爲關於一些numpy,pandas,和matplotlib繪圖的知識大家都有了解

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline

直方圖初判

簡單的說就是根據數據繪製出散點圖,直方圖,及概論密度曲線,通過肉眼觀察是否符合正態分佈。下面我們舉個例子:

s = pd.Series(np.random.randn(1000)+10,name = 'value')
# 創建隨機數據

fig = plt.figure(figsize = (10,6))
ax1 = fig.add_subplot(2,1,1)  # 創建子圖1
ax1.scatter(s.index, s.values)
plt.grid()
# 繪製數據分佈圖

ax2 = fig.add_subplot(2,1,2)  # 創建子圖2
s.hist(bins=30,alpha = 0.5,ax = ax2)
s.plot(kind = 'kde', secondary_y=True,ax = ax2) #繪製密度曲線
plt.grid()
# 繪製直方圖
# 呈現較明顯的正太性

                         

通過圖像我們可以看到明顯符合正態分佈。

QQ圖判斷

QQ圖是一種散點圖,對應於正態分佈的QQ圖,就是由標準正態分佈的分位數爲橫座標,樣本值爲縱座標的散點圖。QQ圖通過把測試樣本數據的分位數與已知分佈相比較,從而來檢驗數據的分佈情況。通過判斷散點是否落在參考直線附近。(參考直線:四分之一分位點和四分之三分位點這兩點確定)

繪製思路:

  1. 在做好數據清洗後,對數據進行排序(次序統計量:x(1)<x(2)<....<x(n))
  2. 排序後,計算出每個數據對應的百分位p{i},即第i個數據x(i)爲p(i)分位數,其中p(i)=(i-0.5)/n (pi有多重算法,這裏以最常用方法爲主)
  3. 繪製直方圖 + qq圖,直方圖作爲參考
s = pd.DataFrame(np.random.randn(1000)+10,columns = ['value'])
# 創建隨機數據

mean = s['value'].mean() 
std = s['value'].std()   
#  計算均值,標準差

s.sort_values(by = 'value', inplace = True)  # 重新排序
s_r = s.reset_index(drop = False)  # 重新排序後,更新index
s_r['p'] = (s_r.index - 0.5) / len(s_r)  
# 計算百分位數 p(i)
# 計算q值 每個值標準化之後的結果

st = s['value'].describe()
x1 ,y1 = 0.25, st['25%']
x2 ,y2 = 0.75, st['75%']
# 計算四分之一位數、四分之三位數

fig = plt.figure(figsize = (10,9))
ax1 = fig.add_subplot(3,1,1)  # 創建子圖1
ax1.scatter(s.index, s.values)
plt.grid()
# 繪製數據分佈圖

ax2 = fig.add_subplot(3,1,2)  # 創建子圖2
s.hist(bins=30,alpha = 0.5,ax = ax2)
s.plot(kind = 'kde', secondary_y=True,ax = ax2)
plt.grid()
# 繪製直方圖

ax3 = fig.add_subplot(3,1,3)  # 創建子圖3
ax3.plot(s_r['p'],s_r['value'],'k.',alpha = 0.1)
ax3.plot([x1,x2],[y1,y2],'-r') #繪製參考直線
plt.grid()
# 繪製QQ圖,直線爲四分之一位數、四分之三位數的連線,基本符合正態分佈

                 

我們可以觀察到散點落在參考直線(紅線)附近。(一般QQ呈S型曲線)

但是QQ圖判斷也有一個問題,假如是一組符合平均分佈的數據

s = pd.DataFrame(np.random.rand(1000)+10,columns = ['value'])
#創建一組符合平均分佈數據

                    

我們看到散點落在參考直線(紅線)附近,而並不是正態分佈,是平均分佈。這時我們考慮K-S檢驗。

K-S檢驗

Kolmogorov-Smirnov檢驗是比較一個頻率分佈f(x)與理論分佈g(x)或者兩個觀測值分佈的檢驗方法。

以樣本數據的累計頻數分佈與特定的理論分佈比較(如正態分佈),如果兩者差距小,則推論樣本分佈取自某特定分佈。

假設檢驗:

H0:樣本的總體分佈服從某特定分佈 H1:樣本的總體分佈不服從某特定分佈

Fn(x)->樣本的累計分佈函數  F(x)->理論分佈的分佈函數

計算Fn(x)與F(x)的絕對差,令最大的絕對差爲Dn;Dn=max{[Fn(x) - F(x)]}

D與D(n,a)通過顯著性對照表相比較,p>0.05接受H0

# KS檢驗,理論推導

data = [87,77,92,68,80,78,84,77,81,80,80,77,92,86,
       76,80,81,75,77,72,81,72,84,86,80,68,77,87,
       76,77,78,92,75,80,78]
# 樣本數據,35位健康男性在未進食之前的血糖濃度

df = pd.DataFrame(data, columns =['value'])
u = df['value'].mean()
std = df['value'].std()
print("樣本均值爲:%.2f,樣本標準差爲:%.2f" % (u,std))
print('------')
# 查看數據基本統計量

s = df['value'].value_counts().sort_index()
df_s = pd.DataFrame({'血糖濃度':s.index,'次數':s.values})
# 創建頻率數據

df_s['累計次數'] = df_s['次數'].cumsum()
df_s['累計頻率'] = df_s['累計次數'] / len(data)
df_s['標準化取值'] = (df_s['血糖濃度'] - u) / std #轉換標準正態分佈
df_s['理論分佈'] =[0.0244,0.0968,0.2148,0.2643,0.3228,0.3859,0.5160,0.5832,0.7611,0.8531,0.8888,0.9803]  # 通過查閱正太分佈表
df_s['D'] = np.abs(df_s['累計頻率'] - df_s['理論分佈'])
dmax = df_s['D'].max()
print("實際觀測D值爲:%.4f" % dmax)
# D值序列計算結果表格

df_s['累計頻率'].plot(style = '--k.')
df_s['理論分佈'].plot(style = '--r.')
plt.legend(loc = 'upper left')
plt.grid()
# 密度圖表示

df_s

                 

對照顯著性檢驗表,n=35,可以發現p>0.05.同時當我們清楚原理,可以引入scipy包,來完成KS檢驗。

# 直接用算法做KS檢驗

from scipy import stats
# scipy包是一個高級的科學計算庫,它和Numpy聯繫很密切,Scipy一般都是操控Numpy數組來進行科學計算

data = [87,77,92,68,80,78,84,77,81,80,80,77,92,86,
       76,80,81,75,77,72,81,72,84,86,80,68,77,87,
       76,77,78,92,75,80,78]
# 樣本數據,35位健康男性在未進食之前的血糖濃度

df = pd.DataFrame(data, columns =['value'])
u = df['value'].mean()  # 計算均值
std = df['value'].std()  # 計算標準差
stats.kstest(df['value'], 'norm', (u, std))
# .kstest方法:KS檢驗,參數分別是:待檢驗的數據,檢驗方法(這裏設置成norm正態分佈),均值與標準差
# 結果返回兩個值:statistic → D值,pvalue → P值
# p值大於0.05,爲正態分佈

 

附正態分佈表及顯著性對照表:

 

發佈了67 篇原創文章 · 獲贊 49 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章