怎麼樣描述你的數據——用python做描述性分析

描述性統計分析是關於數據的描述和彙總。它使用兩種主要方法:

  1. 定量方法以數值方式描述和彙總數據。

  2. 可視化方法通過圖表,曲線圖,直方圖和其他圖形來說明數據。

一般在數據分析的過程中,拿到數據不會去直接去建模,而是先做描述性分析來對數據有一個大致的把握,很多後續的建模方向也是通過描述性分析來進一步決定的。那麼除了在Excel/R中可以去做描述性分析。

本文將細緻講解如何使用python進行描述性分析的定量分析部分:

  • 均值

  • 中位數

  • 方差

  • 標準差

  • 偏度

  • 百分位數

  • 相關性

至於可視化的部分可以參考我之前講解pyecharts的文章,當然後面還會介紹echarts以及ggplot2的方法。

涉及到的python庫

  • Python statistics是用於描述性統計信息的內置Python庫。如果您的數據集不是太大,或者您不能依賴於導入其他庫,則可以使用它。

  • NumPy是用於數字計算的第三方庫,已針對使用一維和多維數組進行了優化。它的主要類型是稱爲的數組類型ndarray。該庫包含許多用於統計分析的方法。

  • SciPy是基於NumPy的用於科學計算的第三方庫。與NumPy相比,它提供了其他功能,包括scipy.stats統計分析。Getting started - SciPy.org

  • Pandas是基於NumPy的用於數值計算的第三方庫。它擅長處理帶有Series對象的帶標籤的一維(1D)數據和帶有對象的二維(2D)數據DataFrame

  • Matplotlib是用於數據可視化的第三方庫。通常會與NumPy,SciPy和Pandas結合使用


開始

首先導入所有的包

import math
import statistics
import numpy as np
import scipy.stats
import pandas as pd



創建數據

xx_with_nan都是list。不同之處在於x_with_nan包含一個nan值。也就是空值(缺失值),這樣的數據在分析中十分常見。那麼在python裏,創建一個nan值可以有以下方法

float('nan')
math.nan
np.nan

當然這三種方法創建的空值都是等價的

但是真的相等嗎,兩個nan是不相等的,換句話說,是不可以進行比較的,這後面的故事以後再說。

接着,我們使用numpy和pandas來創建兩個一維numpy arrays和pandas series

均值

均值的定義啥的,就不說了,R裏面直接mean()就可以,而在python,不導入包,怎麼計算:

當然也可以用python的內置統計功能

但是如果數據中包含nan,那麼將返回nan

>>> mean_ = statistics.mean(x_with_nan)
>>> mean_
nan

如果使用numpy

>>> mean_ = np.mean(y)
>>> mean_
8.7

在上面的示例中,mean()是一個函數,但是您也可以使用相應的方法

>>> mean_ = y.mean()
>>> mean_
8.7

如果包含nan,numpy也會返回nan,那麼要是想忽略nan,可以使用np.nanmean()

>>> np.mean(y_with_nan)
nan
>>> np.nanmean(y_with_nan)
8.7


pandas也有對應方法,但是,默認情況下,.mean()在Pandas中忽略nan值:

mean_ = z.mean()
mean_
>>> z_with_nan.mean()
8.7


中位數

比較平均值和中位數,這是檢測數據中異常值和不對稱性的一種方法。平均值還是中位數對您更有用,取決於特定問題的背景。而不使用包的計算方法:

>>> n = len(x)
>>> if n % 2:
...     median_ = sorted(x)[round(0.5*(n-1))]
... else:
...     x_ord, index = sorted(x), round(0.5 * n)
...     median_ = 0.5 * (x_ord[index-1] + x_ord[index])
...
>>> median_
4







其他方法

>>> median_ = np.median(y)
>>> median_
4.0
>>> np.nanmedian(y_with_nan)
4.0



方差

方差的意義也不過多說明,在Excel中直接用stdev函數,但是怎麼在python中計算?記得當初研究生複試就被問到用python不導入包怎麼計算方差?

>>> n = len(x)
>>> mean_ = sum(x) / n
>>> var_ = sum((item - mean_)**2 for item in x) / (n - 1)
>>> var_
123.19999999999999



當然更簡單的方法是直接使用函數,不過有nan還是會返回nan

>>> var_ = statistics.variance(x)
>>> var_
123.2
>>> statistics.variance(x_with_nan)
nan



放在numpy裏面就更簡單了,可以使用np.var()或者.var()

>>> var_ = np.var(y, ddof=1)
>>> var_
123.19999999999999
>>> var_ = y.var(ddof=1)
>>> var_
123.19999999999999





這裏ddof就是自由度要設置爲1纔是無偏的。也就是分母用n-1替換n。如果有nan怎麼辦?返回nan,但是可以用np.nanvar()跳過nan,不過ddof依舊要設置爲1

>>> np.var(y_with_nan, ddof=1)
nan
>>> y_with_nan.var(ddof=1)
nan
>>> np.nanvar(y_with_nan, ddof=1)
123.19999999999999




標準差

有了方差,標準差就很好計算了

#直接計算
>>> std_ = var_ ** 0.5
>>> std_
11.099549540409285
#使用內置包
>>> std_ = statistics.stdev(x)
>>> std_
11.099549540409287






numpy中也很好計算

>>> np.std(y, ddof=1)
11.099549540409285
>>> y.std(ddof=1)
11.099549540409285
>>> np.std(y_with_nan, ddof=1)
nan
>>> y_with_nan.std(ddof=1)
nan
>>> np.nanstd(y_with_nan, ddof=1) #跳過nan,ddof還是要是1哦
11.099549540409285








偏度(skew)

偏度(skewness)也稱爲偏態、偏態係數,是統計數據分佈偏斜方向和程度的度量,是統計數據分佈非對稱程度的數字特徵。偏度是利用3階矩定義的,偏度的計算公式爲:

我們之前研究的數據都是比較對稱的數據,但是上圖就給出了不對稱的數據集,第一組用綠點表示,第二組用白點表示。通常,負偏度值表示左側有一個占主導地位的尾巴,可以在第一個集合中看到。正偏度值對應於右側較長或的尾巴,可以在第二組中看到。如果偏度接近0(例如,介於-0.5和0.5之間),則該數據集被認爲是非常對稱的。

那麼不依賴第三包,怎麼計算偏度。可以先計算完數據集的大小n,樣本均值mean和標準差std後用公式計算

>>> x = [8.0, 1, 2.5, 4, 28.0]
>>> n = len(x)
>>> mean_ = sum(x) / n
>>> var_ = sum((item - mean_)**2 for item in x) / (n - 1)
>>> std_ = var_ ** 0.5
>>> skew_ = (sum((item - mean_)**3 for item in x)
...          * n / ((n - 1) * (n - 2) * std_**3))
>>> skew_
1.9470432273905929







可以看出偏度爲正,因此x尾巴在右側。

也可以用第三方包計算

>>> y, y_with_nan = np.array(x), np.array(x_with_nan)
>>> scipy.stats.skew(y, bias=False)
1.9470432273905927
>>> scipy.stats.skew(y_with_nan, bias=False)
nan
>>> z, z_with_nan = pd.Series(x), pd.Series(x_with_nan)
>>> z.skew()
1.9470432273905924
>>> z_with_nan.skew()
1.9470432273905924








百分位數(Percentiles)

如果將一組數據從小到大排序,並計算相應的累計百分位,則某一百分位所對應數據的值就稱爲這一百分位的百分位數。可表示爲:一組n個觀測值按數值大小排列。如,處於p%位置的值稱第p百分位數。每個數據集都有三個四分位數,這是將數據集分爲四個部分的百分位數:

  • 第一四分位數 (Q1),又稱“較小四分位數”,等於該樣本中所有數值由小到大排列後第25%的數字。

  • 第二四分位數 (Q2),又稱“中位數”,等於該樣本中所有數值由小到大排列後第50%的數字。

  • 第三四分位數 (Q3),又稱“較大四分位數”,等於該樣本中所有數值由小到大排列後第75%的數字。

第三四分位數與第一四分位數的差距又稱四分位距(InterQuartile Range,IQR)。

那麼在python裏面怎麼計算分位數呢。可以使用statistics.quantiles()

>>> x = [-5.0, -1.1, 0.1, 2.0, 8.0, 12.8, 21.0, 25.8, 41.0]
>>> statistics.quantiles(x, n=2)
[8.0]
>>> statistics.quantiles(x, n=4, method='inclusive')
[0.1, 8.0, 21.0]



可以看到第一行中,8就是x的中位數,而第二個例子中,0.1和21是樣本的25%和75%分位數。也可以使用第三方包numpy計算

>>> np.percentile(y, [25, 50, 75])
array([ 0.1,  8. , 21. ])
>>> np.median(y)
8.0
#跳過nan
>>> y_with_nan = np.insert(y, 2, np.nan)
>>> y_with_nan
array([-5. , -1.1,  nan,  0.1,  2. ,  8. , 12.8, 21. , 25.8, 41. ])
>>> np.nanpercentile(y_with_nan, [25, 50, 75])
array([ 0.1,  8. , 21. ])








pandas也可以使用.quantile()計算,需要提供分位數值作爲參數。該值可以是0到1之間的數字或數字序列。

>>> z, z_with_nan = pd.Series(y), pd.Series(y_with_nan)
>>> z.quantile(0.05)
-3.44
>>> z.quantile(0.95)
34.919999999999995
>>> z.quantile([0.25, 0.5, 0.75])
0.25     0.1
0.50     8.0
0.75    21.0
dtype: float64
>>> z_with_nan.quantile([0.25, 0.5, 0.75])
0.25     0.1
0.50     8.0
0.75    21.0
dtype: float64













範圍(Ranges)

數據的範圍是數據集中最大和最小元素之間的差。可以通過函數np.ptp()獲得:

>>> np.ptp(y)
27.0
>>> np.ptp(z)
27.0
>>> np.ptp(y_with_nan)
nan
>>> np.ptp(z_with_nan)
27.0






描述性統計摘要

在SciPy和Pandas提供過單個函數或方法調用快速獲取描述性統計信息。

>>> result = scipy.stats.describe(y, ddof=1, bias=False)
>>> result
DescribeResult(nobs=9, minmax=(-5.0, 41.0), mean=11.622222222222222, variance=228.75194444444446, skewness=0.9249043136685094, kurtosis=0.14770623629658886)

describe() 返回包含以下信息:

  • nobs:數據集中的觀測值或元素數

  • minmax:數據的最大和最小值

  • mean:數據集的平均值

  • variance:數據集的方差

  • skewness:數據集的偏度

  • kurtosis:數據集的峯度

>>> result.nobs
9
>>> result.minmax[0]  # Min
-5.0
>>> result.minmax[1]  # Max
41.0
>>> result.mean
11.622222222222222
>>> result.variance
228.75194444444446
>>> result.skewness
0.9249043136685094
>>> result.kurtosis
0.14770623629658886












pandas也有類似的函數.describe():

>>> result = z.describe()
>>> result
count     9.000000 #數據集中的元素數
mean     11.622222 #數據集的平均值
std      15.124548 #數據集的標準差
min      -5.000000
25%       0.100000 #數據集的四分位數
50%       8.000000
75%      21.000000
max      41.000000
dtype: float64









相關性

相關行的統計學意義也不在過多說明,但是要注意,相關性只是能從數據上判斷是否有關係,不能夠說明因果關係!!!

度量相關性主要使用協方差相關性係數:

那麼我們先重新創建數據

>>> x = list(range(-10, 11))
>>> y = [0, 2, 2, 2, 2, 3, 3, 6, 7, 4, 7, 6, 6, 9, 4, 5, 5, 10, 11, 12, 14]
>>> x_, y_ = np.array(x), np.array(y)
>>> x__, y__ = pd.Series(x_), pd.Series(y_)


計算協方差

>>> n = len(x)
>>> mean_x, mean_y = sum(x) / n, sum(y) / n
>>> cov_xy = (sum((x[k] - mean_x) * (y[k] - mean_y) for k in range(n))
...           / (n - 1))
>>> cov_xy
19.95




numpyh和pandas都有可以返回協方差矩陣函數cov()

# numpy
>>> cov_matrix = np.cov(x_, y_)
>>> cov_matrix
array([[38.5       , 19.95      ],
      [19.95      , 13.91428571]])
# pandas
>>> cov_xy = x__.cov(y__)
>>> cov_xy
19.95
>>> cov_xy = y__.cov(x__)
>>> cov_xy
19.95










計算相關係數

我們這裏說的均是pearson相關係數。Pearson相關係數(Pearson CorrelationCoefficient)是用來衡量兩個數據集合是否在一條線上面,它用來衡量定距變量間的線性關係。計算公式爲

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章