標準偏差(Standard Deviation, std)を計算する際、
いろいろなライブラリでstd
と呼ばれる関数がありますが
それぞれ自由度のデフォルト値が違うものがあっていつも調べ直してしまうという話。
主にPythonのnumpyとpandasのもの。
std
と
標準偏差
とあるn個のデータ、 \(x_1, x_2, ..., x_n\) の標準偏差は
平均値 \(\hat{x}\) を使って
\[\begin{aligned} s = \sqrt{\frac{1}{n}\sum^{n}_{i=1}\left(x_i - \hat{x}\right)^2} \end{aligned}\]となります。
このデータがある母集団から抜き出したものだとすると、もとの母集団の標準偏差は
\[\begin{aligned} v = \sqrt{\frac{1}{n-1}\sum^{n}_{i=1}\left(x_i - \hat{x}\right)^2} \end{aligned}\]と推定され、これを不偏標準偏差といいます。
違いは最初の\(n\)で割っているか\(n-1\)で割ってるかで、 この部分が自由度(Degree of Freedom)を表しています。
詳しい説明はたくさんあるので省くとして、 \(n\)が十分大きいときには\(n-1\)で割ろうが\(n\)で割ろうがほとんど値に変わりはありませんが いずれにしろ値は変わってしまうのできちんと欲しい物に対応した値を使わないといけません。
いろいろなライブラリの標準偏差関数
Pythonでこのあたりの統計量をよく扱うライブラリとしてNumpyとPandasがあります。
これらは共にstd
という関数を持っていますが、それらの自由度にあたる部分のデフォルト値が違っています。
- numpy.std: ddof=0
- pandas.DataFrame.std: ddof=1
共に、ddof
(Delta Degree of Freedome)という引数を持っていて、
自由度部分がデータ数\(n\)と合わせて\(n-ddof\)になるものですが、これが違ってきます。
テーブルデータを扱っていればPandasで読み込んで直接DataFrameのstd
を使う事も多いですが、
ちょっと一部だけ配列で取り出してnumpy.std
で計算してみて、みたいなこともあったりします。
そういったときに毎回混乱してhelpで見てみるという。。。
これら以外に、
- scipy.stats.tstd: ddof=1 (the Trimmed Standard Deviation, 端の値を外れ値として落として計算する機能を含む)
もddof=1
がデフォルトです。
また、以下のものはddofに対応するパラメーターはなく、決まった値だけを返します。
- sklearn.preprocessing.StandardScaler: ddof=1に対応する値を返す
- statistics.stdev: ddof=1に対応する値を返す
- statistics.pstdev: ddof=0に対応する値を返す
標準ライブラリのstatistics
が持つpstdev
の方はthe Population Standard Deviation (母標準偏差)のP
がついたもので、
入力の集団が母集団そのものとしてddof=0でその集団の標準偏差を返すようになっています。
statistics
に関してはp
なしの方がデフォルトだと思うと、
- Numpy, scikit-learn: ddof=0
- Pandas, SciPy, statistics: ddof=1
がそれぞれのデフォルト値となっています。
この辺何度やってもどちらか不安になるので、やっぱり使う時はちゃんと引き数指定でやった方が安全です。
scikit-learnのStandardScalerだと変更できないのでこれはわからなくなったら確認。
Python以外でもたまに使うExcelの関数なんかだと、
STDEV.S 関数、
STDEV.P 関数
と言った感じで別々の関数があったりします。
(ここのS
はthe Sample Standard Deviation、標本標準偏差のS
)
テスト
テストコード:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|