PythonとRで分散が微妙に違う理由

知っていましたか?PythonとRで、微妙に分散が違うんです。

分散が違うので、その平方根の標準偏差も違ってきます。

ではなぜ違うのか、それについて見ていきましょう。

 

まずRで分散を実装してみます。

nums <- c(50, 60, 70, 80, 90)
print(nums)
[1] 50 60 70 80 90
var(nums)

250

ではPython

nums = [50, 60, 70, 80, 90]
nums
[50, 60, 70, 80, 90]
np.var(nums)

200.0

あれ、Rでは分散は250だったのに、Pythonでは200になってしまいました。

これ、Rではvar()関数がデフォルトで「不偏分散」になっているのに対し、

Pythonではnp.var()関数が、「標本分散」になっているからなのです。

まず標本分散ですが、これは以下の数式で表せます。

$$ \frac{1}{n} \sum_{j=1}^{n} (x_j – \bar{x})^2 $$

ついで不偏分散

$$ \frac{1}{n – 1} \sum_{j=1}^{n} (x_j – \bar{x})^2 $$

$ \frac{1}{n}$が$ \frac{1}{n – 1}$になってますね。

これは、nで割った分散が、真の分散を小さめに推定する傾向があることがわかっているため、その分だけ分母を小さくして、つまり値を大きくして釣り合いをとっているわけです。

「標本分散」は、標本だけの分散を考えているので、$ \frac{1}{n} $で、

「不偏分散」は、既知の数値は母集団の一部と考え、母集団の分散を推定するので、$ \frac{1}{n – 1} $というわけです。

ではPythonで不偏分散にするためにはどうすればいいのかというと、ddofというパラメータに1を与えればOK

np.var(nums,ddof=1)

250.0

まあ$\frac{n}{n – 1}$すれば良いんですけどね。

逆にRで標本分散にするにはというと、そういうパラメータはないので、$\frac{n – 1}{n}$すればいいです。

(length(nums) -1)/(length(nums)) * var(nums)

200