用Python講解偏度和峰度
之前筆者在做一個(gè)金融數(shù)據(jù)項(xiàng)目時(shí),有朋友問我,衡量股票收益率有沒有什么好的方法。這個(gè)問題讓筆者也思索了好久,其實(shí)股票的收益率如果我們從本質(zhì)來看不就是數(shù)據(jù)嗎,無非就是收益率我們就想讓其越高越好,也就是讓這個(gè)數(shù)據(jù)增加得越多越好。而衡量數(shù)據(jù)我們經(jīng)常用到的方法有均值、方差、偏度和峰度。均值和方差是我們見到和用到最多的方法,甚至在中學(xué)課本里都有提及,那么筆者今天就講一下偏度和峰度這兩個(gè)大家不太常用的方法,并結(jié)合python代碼講一下偏度和峰度在數(shù)據(jù)分析中的簡(jiǎn)單應(yīng)用。
首先還是介紹一下偏度和峰度的概念。
圖1. 偏度和峰度公式
偏度(skewness)又稱偏態(tài)、偏態(tài)系數(shù),是描述數(shù)據(jù)分布偏斜方向和程度的度量,其是衡量數(shù)據(jù)分布非對(duì)稱程度的數(shù)字特征。對(duì)于隨機(jī)變量X,其偏度是樣本的三階標(biāo)準(zhǔn)化矩,計(jì)算公式如圖1中的式(1)所示。
偏度的衡量是相對(duì)于正態(tài)分布來說,正態(tài)分布的偏度為0。因此我們說,若數(shù)據(jù)分布是對(duì)稱的,偏度為0;若偏度>0,則可認(rèn)為分布為右偏,也叫正偏,即分布有一條長(zhǎng)尾在右;若偏度<0,則可認(rèn)為分布為左偏,也叫負(fù)偏,即分布有一條長(zhǎng)尾在左。正偏和負(fù)偏如圖2所示,在圖2中,左邊的就是正偏,右邊的是負(fù)偏。
圖2. 偏度的示意圖
而峰度(Kurtosis)則是描述數(shù)據(jù)分布陡峭或平滑的統(tǒng)計(jì)量,通過對(duì)峰度的計(jì)算,我們能夠判定數(shù)據(jù)分布相對(duì)于正態(tài)分布而言是更陡峭還是平緩。對(duì)于隨機(jī)變量X,其峰度為樣本的四階標(biāo)準(zhǔn)中心矩,計(jì)算公式如圖1中的式2所示。
當(dāng)峰度系數(shù)>0,從形態(tài)上看,它相比于正態(tài)分布要更陡峭或尾部更厚;而峰度系數(shù)<0,從形態(tài)上看,則它相比于正態(tài)分布更平緩或尾部更薄。在實(shí)際環(huán)境當(dāng)中,如果一個(gè)分部是厚尾的,這個(gè)分布往往比正態(tài)分布的尾部具有更大的“質(zhì)量”,即含又更多的極端值。我們常用的幾個(gè)分布中,正態(tài)分布的峰度為0,均勻分布的峰度為-1.2,指數(shù)分布的峰度為6。
峰度的示意圖如圖3所示,其中第一個(gè)子圖就是峰度為0的情況,第二個(gè)子圖是峰度大于0的情況,第三個(gè)則是峰度小于0。
圖3. 峰度的示意圖
在說完基本概念之后,我們就再講一下怎么基于偏度和峰度進(jìn)行正態(tài)性檢驗(yàn)。這里主要有兩種方法,一是Omnibus檢驗(yàn),二是Jarque - Bera檢驗(yàn)。
圖4. Omnibus和JB檢驗(yàn)的公式
Omnibus檢驗(yàn)的公式如圖4中公式(3)所示,式中Z1和Z2是兩個(gè)正態(tài)化函數(shù),g1和g2則分別是偏度和峰度,在Z1和Z2的作用下,K的結(jié)果就接近于卡方分布,我們就能用卡方分布來檢驗(yàn)了。這個(gè)公式的原理比較復(fù)雜,大家如想了解可自行查找相關(guān)資料。
Jarque - Bera檢驗(yàn)的公式如圖4中公式(4)所示,式中n是樣本量,這個(gè)結(jié)果也是接近于卡方分布,其原理也不在這里贅述。這兩個(gè)檢驗(yàn)都是基于所用數(shù)據(jù)是正態(tài)分布的,即有如下假設(shè)。
原假設(shè)H0:數(shù)據(jù)是正態(tài)分布的。
備擇假設(shè)H1:數(shù)據(jù)不是正態(tài)分布。
下面我們用代碼來說明一下偏度和峰度。
首先看一下數(shù)據(jù),這個(gè)數(shù)據(jù)很簡(jiǎn)單,只有15行2列。數(shù)據(jù)描述的是火災(zāi)事故的損失以及火災(zāi)發(fā)生地與最近消防站的距離,前者單位是千元,后者單位是千米,數(shù)據(jù)如圖5所示。其中distance指火災(zāi)發(fā)生地與最近消防站的距離,loss指火災(zāi)事故的損失。
圖5. 數(shù)據(jù)示例
下面是代碼,首先導(dǎo)入需要的庫。
- import pandas as pd
- import matplotlib.pyplot as plt
- import statsmodels.stats.api as sms
- import statsmodels.formula.api as smf
- from statsmodels.compat import lzip
- from statsmodels.graphics.tsaplots import plot_acf
接下來是讀取數(shù)據(jù)并作圖,這些代碼都非常簡(jiǎn)單,筆者不做過多的解釋。
- file = r'C:\Users\data.xlsx'
- df = pd.read_excel(file)
- fig, ax = plt.subplots(figsize=(8,6))
- plt.ylabel('Loss')
- plt.xlabel('Distance')
- plt.plot(df['distance'], df['loss'], 'bo-', label='loss')
- plt.legend()
- plt.show()
結(jié)果如圖6所示,從結(jié)果中我們可以看到這些點(diǎn)大致在一條直線上,那么我們就用一元線性回歸來擬合這些數(shù)據(jù)。
圖6. 數(shù)據(jù)連線圖
下面是生成模型,并輸出模型的結(jié)果。
- expr = 'loss ~ distance'
- results = smf.ols(expr, df).fit() #生成回歸模型
- print(results.summary())
結(jié)果如圖7所示。從圖中我們可以看到,Prob (F-statistic)的值為1.25e-08,這個(gè)值非常小,說明我們的一元線性回歸模型是正確的,也就是loss和distance的線性關(guān)系是顯著的。而圖中還可以看到Skew=-0.003,說明這部分?jǐn)?shù)據(jù)非常接近正態(tài)分布,而Kurtosis=1.706,說明我們的數(shù)據(jù)比正態(tài)分布更陡峭,是一個(gè)尖峰。此外,從圖中還可以看到Omnibus=2.551,Prob(Omnibus)=0.279,Jarque-Bera (JB)=1.047,Prob(JB)=0.592,這里我們很難直接從Omnibus和Jarque-Bera的數(shù)值來判斷是否支持前面的備擇假設(shè),但我們可以從Prob(Omnibus)和Prob(JB)這兩個(gè)數(shù)值來判斷,因?yàn)檫@兩個(gè)數(shù)值都比較大,那么我們就無法拒絕前面的原假設(shè),即H0是正確的,說明我們的數(shù)據(jù)是服從正態(tài)分布的。
圖7. 模型結(jié)果說明
接下來我們?cè)衮?yàn)證一下Skew、Kurtosis、Omnibus和Jarque-Bera (JB)這些數(shù)值,用的是statsmodels自帶的方法。代碼如下。
- omnibus_label = ['Omnibus K-squared test', 'Chi-squared(2) p-value']
- omnibus_test = sms.omni_normtest(results.resid) #omnibus檢驗(yàn)
- omnibus_results = lzip(omnibus_label, omnibus_test)
- jb_label = ['Jarque-Bera test', 'Chi-squared(2) p-value', 'Skewness', 'Kurtosis']
- jb_test = sms.jarque_bera(results.resid) #jarque_bera檢驗(yàn)
- jb_results = lzip(jb_label, jb_test)
- print(omnibus_results)
- print(jb_results)
這里omnibus_label和jb_label是兩個(gè)list,里面包含了我們所要檢驗(yàn)的項(xiàng)目名稱,sms.omni_normtest就是statsmodels自帶的omnibus檢驗(yàn)方法,sms.jarque_bera就是statsmodels自帶的jarque_bera檢驗(yàn)方法。results.resid是殘差值,一共有15個(gè)值,我們的數(shù)據(jù)本身就只有15個(gè)點(diǎn),這里的每個(gè)殘差值就對(duì)應(yīng)前面的每個(gè)數(shù)據(jù)點(diǎn),sms.omni_normtest和sms.jarque_bera就是通過殘差值來進(jìn)行檢驗(yàn)的。而lzip這個(gè)方法很少見,其用法和python中原生函數(shù)zip差不多,筆者在這里更多地是想讓大家了解statsmodels,所以用了lzip,這里直接用zip也是可以的,至于lzip和zip的區(qū)別,留給大家自行去學(xué)習(xí)。而上面得到的結(jié)果如圖8所示。從圖8中可以看到,我們得到的結(jié)果和前面圖7中的結(jié)果一模一樣。這里用sms.omni_normtest和sms.jarque_bera來進(jìn)行驗(yàn)證,主要是對(duì)前面圖7中的結(jié)果的一個(gè)解釋,幫助大家更好地學(xué)習(xí)statsmodels。
圖8. omnibus和jb檢驗(yàn)的結(jié)果
本文主要通過statsmodels來解釋一下偏度和峰度在數(shù)據(jù)分析中的一些基本應(yīng)用,想要更深入了解偏度、峰度以及statsmodels的讀者,可以自行查閱相關(guān)資料。