2016年12月30日 星期五

Standard Deviation with Python

Standard Deviation with Python

在讀 Bollinger Band 時,看到公式裡有提到 Standard Deviation (標準差,SD),想說以前總是沒有把這個基礎的東西弄懂。

今天終於花點時間看一下,順便學著用Python 算一下。

Standard Deviation 是 Variance (變異數) 的平方根。 但 Variance 又是什麼?

Variance 的定義是資料中,每一筆值與這些資料的平均值的差的平方值的平均‧ 一步一步寫出來怎麼算可能會比較清楚。

  1. 算出全部資料的平均值

  2. 把每一筆資料減掉 (1) 算出來的平均值,之後再算這個差的平方。

  3. 算出全部平方過後的差值的平均值。

但是 variance 又有分成兩種,一個是 Population Variance,一個是 Sample Variance。

他們的差別是:

Population variance 是所謂的母體變異數,是包括全部的資料。

Sample variance 是所謂的樣本變異數,是從全部資料裡的一部分。

他們的公式有一點點不一樣的是 (3), Population 是除以全部資料的筆數,Sample 是全部資料筆數再減一。

這也造成了有兩種 Standard Deviation,

Population Standard Deviation Population Standard Deviation

Sample Standard Deviation Sample Standard Deviation


下面是個例子。下面的 code 是盡量寫到跟上面的步驟一樣。

In [1]:
# 先用一個 list 來存值
x = [600, 470, 170, 430, 300]
In [2]:
# 算出平均值,步驟 (1)。
x_mean = sum(x) / len(x); x_mean
Out[2]:
394.0
In [3]:
# 算出每一筆資料和平均值的差
x_diff = [i - x_mean for i in x]; x_diff
Out[3]:
[206.0, 76.0, -224.0, 36.0, -94.0]
In [4]:
# 算出差的平方,步驟 (2)
x_diff_square = [i*i for i in x_diff]; x_diff_square
Out[4]:
[42436.0, 5776.0, 50176.0, 1296.0, 8836.0]
In [5]:
# 算出 母體變異數 Population Variance,步驟 (3)
p_variance = sum(x_diff_square) / len(x_diff_square); p_variance
Out[5]:
21704.0

現在終於可以算 population standard deviation 了。

In [6]:
# 把 variance 開平方根就是 population standard deviation
import math
p_sd = math.sqrt(p_variance); p_sd
Out[6]:
147.32277488562318

再算 sample standard deviation。

In [7]:
# 算出 樣本變異數 Sample Variance,步驟 (3),要注意要多減一
variance = sum(x_diff_square) / (len(x_diff_square) - 1); variance
Out[7]:
27130.0
In [8]:
sd = math.sqrt(variance); sd
Out[8]:
164.7118696390761

Python 3.4 開始,有 statistics module 可以用了。

In [9]:
import statistics
In [10]:
# population variance
statistics.pvariance(x)
Out[10]:
21704
In [11]:
# population standard deviation
statistics.pstdev(x)
Out[11]:
147.32277488562318
In [12]:
# sample variance
statistics.variance(x)
Out[12]:
27130
In [13]:
# sample standard deviation
statistics.stdev(x)
Out[13]:
164.7118696390761

或是要用 numpy

In [14]:
import numpy as np
In [15]:
# 把 python list 換成 numpy array
x_array = np.array(x)
In [16]:
# population standard deviation
np.std(x_array, ddof=0)
Out[16]:
147.32277488562318
In [17]:
# sample standard deviation
np.std(x_array, ddof=1)
Out[17]:
164.7118696390761

或是要用 pandas

In [18]:
import pandas as pd
In [19]:
# 把 python list 換成 pandas series
x_series = pd.Series(x)
In [20]:
# population standard deviation
x_series.std(ddof=0)
Out[20]:
147.32277488562318
In [21]:
# sample standard deviation
x_series.std(ddof=1)
Out[21]:
164.7118696390761

比一下看哪種比較快,結果還是 numpy 比較快

In [22]:
%timeit statistics.pstdev(x)
10000 loops, best of 3: 92.4 µs per loop
In [23]:
%timeit np.std(x_array, ddof=0)
10000 loops, best of 3: 33.7 µs per loop
In [24]:
%timeit x_series.std(ddof=0)
10000 loops, best of 3: 51.7 µs per loop

平均值有時候會騙人,像下面的兩個例子:

z1 = [4, 4, -4, -4]

z2 = [7, 1, -6, -2]

z1 和 z2 的絕對值後的平均值都是 4 ,但是明明資料的差很多。

所以需要用 standard deviation 來顯示出兩份資料的差異性。

假如是用在持續性的資料上,就可以看出新的資料有沒有造成不穩定。


Jupyter(IPython) Notebook: Link

沒有留言:

張貼留言