このようなリストがある場合:
results=[-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
このリストの分散をPythonで計算します。これは平均からの差の二乗の平均です。
これについてどうすればいいですか?リスト内の要素にアクセスして計算を行うと、平方差を取得するのが混乱します。
Numpyの組み込み関数 var
を使用できます。
import numpy as np
results = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
print(np.var(results))
これにより、28.822364260579157
-何らかの理由でnumpy
を使用できない場合、および/または組み込み関数を使用したくない場合は、たとえば「手動」で計算することもできます。 リスト内包表記 :
# calculate mean
m = sum(results) / len(results)
# calculate variance using a list comprehension
var_res = sum((xi - m) ** 2 for xi in results) / len(results)
同じ結果が得られます。
標準偏差に興味がある場合は、 numpy.std を使用できます:
print(np.std(results))
5.36864640860051
@ Serge Ballestaは非常にうまく説明しました 分散n
とn-1
。 numpyでは、オプションddof
;を使用してこのパラメーターを簡単に設定できます。デフォルトは0
、したがってn-1
単純にできる場合:
np.var(results, ddof=1)
「手で」解決策は @ Serge Ballestaの答え で与えられます。
どちらのアプローチでも32.024849178421285
。
std
にもパラメーターを設定できます。
np.std(results, ddof=1)
5.659050201086865
さて、分散を定義するには2つの方法があります。フルセットがある場合に使用する分散nと分散n-1サンプルがあるときに使用します。
2の違いは、値m = sum(xi) / n
が実際の平均なのか、それとも平均値の近似値なのかということです。
例1:クラスの生徒の平均身長とその分散を知りたい:ok、値m = sum(xi) / n
は実際の平均であり、Clebによって与えられた式はok(variancen)。
例2:バス停でバスが通過する平均時間とその変動を知りたいとします。 1か月の時間を記録し、30個の値を取得します。ここで、値m = sum(xi) / n
は実際の平均の近似にすぎず、その近似はより多くの値でより正確になります。その場合、実際の分散の最適な近似は分散ですn-1
varRes = sum([(xi - m)**2 for xi in results]) / (len(results) -1)
OK、Pythonとは関係ありませんが、統計分析に影響があり、質問には statistics および variance というタグが付けられています
注:通常、numpyなどの統計ライブラリは、var
またはvariance
と呼ばれるものに分散nを使用し、標準偏差を与える関数の分散n-1。
Python 3.4
から、標準ライブラリには variance
関数(サンプルの分散またはが付属しています statistics
モジュールの一部としての分散n-1):
from statistics import variance
# data = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439, 0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
variance(data)
# 32.024849178421285
p人口分散(またはvariance n)は pvariance
関数を使用して取得できます:
from statistics import pvariance
# data = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439, 0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
pvariance(data)
# 28.822364260579157
リストの平均がすでにわかっている場合、variance
およびpvariance
関数は2番目の引数(それぞれxbar
およびmu
)を順番に取ることに注意してください(分散計算の一部である)サンプルの平均を再計算するための予備。
実際、Numpyは最もエレガントで高速な方法です。
実際の質問は、リストの個々の要素にアクセスしてそのような計算を自分で行う方法についてだったと思うので、以下の例:
results=[-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
import numpy as np
print 'numpy variance: ', np.var(results)
# without numpy by hand
# there are two ways of calculating the variance
# - 1. direct as central 2nd order moment (https://en.wikipedia.org/wiki/Moment_(mathematics))divided by the length of the vector
# - 2. "mean of square minus square of mean" (see https://en.wikipedia.org/wiki/Variance)
# calculate mean
n= len(results)
sum=0
for i in range(n):
sum = sum+ results[i]
mean=sum/n
print 'mean: ', mean
# calculate the central moment
sum2=0
for i in range(n):
sum2=sum2+ (results[i]-mean)**2
myvar1=sum2/n
print "my variance1: ", myvar1
# calculate the mean of square minus square of mean
sum3=0
for i in range(n):
sum3=sum3+ results[i]**2
myvar2 = sum3/n - mean**2
print "my variance2: ", myvar2
あなたにあげる:
numpy variance: 28.8223642606
mean: -3.731599805
my variance1: 28.8223642606
my variance2: 28.8223642606
正解はNumPyのようなパッケージの1つを使用することですが、自分でロールバックしたい場合や、段階的に実行したい場合は、より正確なアルゴリズムがあります。このリンクを参照してください https://www.johndcook.com/blog/standard_deviation/
Perlの実装をPythonに移植しました。コメントで問題を指摘してください。
Mklast = 0
Mk = 0
Sk = 0
k = 0
for xi in results:
k = k +1
Mk = Mklast + (xi - Mklast) / k
Sk = Sk + (xi - Mklast) * ( xi - Mk)
Mklast = Mk
var = Sk / (k -1)
print var
答えは
>>> print var
32.0248491784
import numpy as np
def get_variance(xs):
mean = np.mean(xs)
summed = 0
for x in xs:
summed += (x - mean)**2
return summed / (len(xs) - 1)
print(get_variance([1,2,3,4,5]))
アウト2.5
a = [1,2,3,4,5]
variance = np.var(a, ddof=1)
print(variance)