01. データ [ 5, 6, 7, 7, 10 ] に対して分散を計算します
標準ライブラリを用いて、コードを作成します。
import statistics
data = [5, 6, 7, 7, 10]
p_var = statistics.pvariance(data)
s_var = statistics.variance(data)
print(f"Population Variance: {p_var}")
print(f"Sample Variance: {s_var}")
Population Variance: 2.8
Sample Variance: 3.5
Pythonの標準ライブラリであるstatisticsモジュールを使用して、母分散(データ全体を母集団とする場合)と不偏分散(データを標本とする場合)の両方を計算するコードです。
import statistics
data = [5, 6, 7, 7, 10]
# 母分散(Population Variance)を計算
# データそのものを母集団とみなす場合に使用します
p_var = statistics.pvariance(data)
# 不偏分散(Sample Variance)を計算
# データがより大きな母集団から抽出された標本である場合に使用します
s_var = statistics.variance(data)
print(f"母分散: {p_var}")
print(f"不偏分散: {s_var}")
計算結果
- 母分散: 2.8
- 不偏分散: 3.5
(平均値は (5 + 6 + 7 + 7 + 10) / 5 = 7 であり、各データと平均との差の2乗和は 14 となります。母分散はこれをデータ数 5 で割った 2.8、不偏分散は 5 - 1 = 4 で割った 3.5 となります。)
02. 手計算で示してください、
データセット:$5, 6, 7, 7, 10$(データ数 $n = 5$)
1. 平均値を求める
全てのデータを足して、データ数で割ります。
$$\text{平均} = \frac{5 + 6 + 7 + 7 + 10}{5} = \frac{35}{5} = 7$$
2. 偏差(各データと平均値との差)を求め、2乗する
各データから平均値の7を引き、その値を2乗します。
- $(5 - 7)^2 = (-2)^2 = 4$
- $(6 - 7)^2 = (-1)^2 = 1$
- $(7 - 7)^2 = 0^2 = 0$
- $(7 - 7)^2 = 0^2 = 0$
- $(10 - 7)^2 = 3^2 = 9$
3. 偏差の2乗和(平方和)を求める
計算した2乗の値を全て足し合わせます。
$$\text{平方和} = 4 + 1 + 0 + 0 + 9 = 14$$
4. 分散を計算する
目的に応じて2種類の分散があります。
-
母分散(データ全体を母集団とする場合)
平方和をデータ数 $n = 5$ で割ります。
$$\sigma^2 = \frac{14}{5} = 2.8$$
-
不偏分散(データがより大きな集団から抽出された標本である場合)
平方和をデータ数マイナス1(自由度 $n - 1 = 4$)で割ります。
$$s^2 = \frac{14}{5 - 1} = \frac{14}{4} = 3.5$$
03.「5人のテストの点数(10点満点)」について,以下の2つの状況を考えてみます。
状況1: テストの点数がそれぞれ (5,6,7,7,10)
状況2: テストの点数がそれぞれ (6,7,7,7,8)
それぞれの分散をもとめてください。
標準ライブラリを用いてコードを生成してください。
import statistics
data1 = [5, 6, 7, 7, 10]
data2 = [6, 7, 7, 7, 8]
p_var1 = statistics.pvariance(data1)
s_var1 = statistics.variance(data1)
p_var2 = statistics.pvariance(data2)
s_var2 = statistics.variance(data2)
print(f"Situation 1: p_var={p_var1}, s_var={s_var1}")
print(f"Situation 2: p_var={p_var2}, s_var={s_var2}")
Situation 1: p_var=2.8, s_var=3.5
Situation 2: p_var=0.4, s_var=0.5
Pythonの標準ライブラリ statistics を用いて、状況1と状況2のそれぞれの分散(母分散および不偏分散)を計算するコードと結果は以下の通りです。
import statistics
# データセットの定義
data1 = [5, 6, 7, 7, 10]
data2 = [6, 7, 7, 7, 8]
# 状況1の分散を計算
p_var1 = statistics.pvariance(data1) # 母分散
s_var1 = statistics.variance(data1) # 不偏分散
# 状況2の分散を計算
p_var2 = statistics.pvariance(data2) # 母分散
s_var2 = statistics.variance(data2) # 不偏分散
print("【状況1】 5, 6, 7, 7, 10")
print(f"母分散: {p_var1}")
print(f"不偏分散: {s_var1}\n")
print("【状況2】 6, 7, 7, 7, 8")
print(f"母分散: {p_var2}")
print(f"不偏分散: {s_var2}")
計算結果
【状況1】 $(5, 6, 7, 7, 10)$ の場合
- 母分散: 2.8
- 不偏分散: 3.5
【状況2】 $(6, 7, 7, 7, 8)$ の場合
- 母分散: 0.4
- 不偏分散: 0.5
ポイント: どちらの状況も平均点は「7点」で同じです。しかし、状況1の方が点数のばらつきが大きいため、分散の値も状況2より大きくなっていることがわかります。
04. 二つの分散を比較して何がわかりますか。
二つの分散を比較することで、「平均値だけでは見えない、データの散らばり具合(個人差や偏り)」がはっきりとわかります。
1. 平均点は同じでも「中身」が全く違う
今回の2つの状況は、どちらも平均点が同じ「7点」です。
もし「平均点」だけでこの5人を評価しようとすると、「状況1と状況2は、どちらも同じ学力のグループだ」と誤解してしまう可能性があります。
2. 分散が教えてくれるクラスの「実態」
分散の値(状況1:2.8 > 状況2:0.4)を見比べることで、それぞれのグループの実態が次のように読み取れます。
-
【状況1】 分散が大きい(2.8)= 実力にバラつきがある
点数が (5, 6, 7, 7, 10) と散らばっています。10点満点を取る優秀な人がいる一方で、5点の人もいます。
(解釈) グループ内の個人差が大きく、理解度が高い人と低い人が混在している状態です。 -
【状況2】 分散が小さい(0.4)= 実力が揃っている
点数が (6, 7, 7, 7, 8) と、平均点の7点付近に密集しています。
(解釈) グループ内の個人差が小さく、全員がほぼ同じレベルの理解度を共有している安定した状態です。
まとめ:なぜ分散を求めるのか?
現実のデータ分析やテストの評価において、平均値は「集団の真ん中」を教えてくれますが、「全体の形」までは教えてくれません。
もう一度解説
分散を計算して比較することで、「全体のレベルが揃っているのか(状況2)、それとも格差が開いているのか(状況1)」という、データに隠された重要な性質を客観的な数値として把握できるようになります。
2つの分散は次のようになります。
-
状況1: (5, 6, 7, 7, 10)
- 平均は 7
- 分散は 2.8
-
状況2: (6, 7, 7, 7, 8)
- 平均は 7
- 分散は 0.4
わかることは、どちらも平均点は同じ 7 点ですが、分散が大きく違うということです。
-
状況1の分散 2.8 は大きい
- 平均の 7 点から離れた点数がある
- 特に 5 点や 10 点のように、平均との差が大きい点数が含まれています
- つまり、点数のばらつきが大きいです
-
状況2の分散 0.4 は小さい
- 点数が 6, 7, 7, 7, 8 と平均のまわりに集まっています
- つまり、点数のばらつきが小さいです
要するに、
- 平均だけを見ると両方とも同じ 7 点
- でも分散を見ると、
- 状況1は「人によって点数差が大きい」
- 状況2は「みんな似たような点数」
ということがわかります。
分散は、「平均が同じでも、データの散らばり具合は違う」ということを調べるための値だと考えるとよいです。
05. 次のデータ5, 6, 7, 7, 6, 5, 8, 5, 5, 6 について,平均値,分散,標準偏差を求めよ。標準ライブラリを使ってコード作成してください
from statistics import mean, pvariance, pstdev
data = [5, 6, 7, 7, 6, 5, 8, 5, 5, 6]
avg = mean(data)
var = pvariance(data)
std = pstdev(data)
print(f"平均値: {avg:.2g}")
print(f"分散: {var:.2g}")
print(f"標準偏差: {std:.2g}")
このコードは、Python の標準ライブラリ statistics を使って、データの平均値・分散・標準偏差を求めています。
-
mean(data)
平均値を求めます。 -
pvariance(data)
分散を求めます。これは「母分散」です。今回のように、与えられたデータ全体について計算するならこれで大丈夫です。 -
pstdev(data)
標準偏差を求めます。これも「母標準偏差」です。
f"{avg:.2g}" の .2g は、有効数字2桁で表示するという意味です。
たとえば 0.99 や 1.1 のように、必要な桁数で自動的に整えてくれます。
このデータ
5, 6, 7, 7, 6, 5, 8, 5, 5, 6
について実際に計算すると、
- 平均値: 6.0
- 分散: 1.2
- 標準偏差: 1.1
となります。
06.手計算での求め方
与えられたデータは
5, 6, 7, 7, 6, 5, 8, 5, 5, 6
です。
1. 平均値を求める
まず全部足します。
5 + 6 + 7 + 7 + 6 + 5 + 8 + 5 + 5 + 6 = 60
データの個数は 10 個なので、
平均値 = 60 ÷ 10 = 6
したがって、
平均値 = 6.0
です。
2. 分散を求める
分散は、「それぞれの値が平均からどれくらい離れているか」をもとに計算します。
まず、各データから平均 6 を引きます。
| データ | 平均との差 |
|---|---|
| 5 | 5 - 6 = -1 |
| 6 | 6 - 6 = 0 |
| 7 | 7 - 6 = 1 |
| 7 | 7 - 6 = 1 |
| 6 | 6 - 6 = 0 |
| 5 | 5 - 6 = -1 |
| 8 | 8 - 6 = 2 |
| 5 | 5 - 6 = -1 |
| 5 | 5 - 6 = -1 |
| 6 | 6 - 6 = 0 |
次に、その差を2乗します。
| データ | 平均との差 | 2乗 |
|---|---|---|
| 5 | -1 | 1 |
| 6 | 0 | 0 |
| 7 | 1 | 1 |
| 7 | 1 | 1 |
| 6 | 0 | 0 |
| 5 | -1 | 1 |
| 8 | 2 | 4 |
| 5 | -1 | 1 |
| 5 | -1 | 1 |
| 6 | 0 | 0 |
この2乗の合計を求めます。
1 + 0 + 1 + 1 + 0 + 1 + 4 + 1 + 1 + 0 = 10
分散は、この合計をデータの個数 10 で割ります。
分散 = 10 ÷ 10 = 1
したがって、
分散 = 1.0
です。
3. 標準偏差を求める
標準偏差は、分散の平方根です。
標準偏差 = √1 = 1
したがって、
標準偏差 = 1.0
です。
4. 答え
有効数字2桁で表すと、
- 平均値: 6.0
- 分散: 1.0
- 標準偏差: 1.0
です。
5. 前のコード結果と違って見える理由
前回、分散を 1.2、標準偏差を 1.1 としていましたが、これは計算ミスでした。
正しく手計算すると、2乗の合計は 10 なので、
- 分散 = 10 / 10 = 1.0
- 標準偏差 = √1.0 = 1.0
になります。
07. 分散の公式を使って一気に計算する方法
分散は、平均との差を1つずつ2乗して求める方法のほかに、公式を使って少しまとめて計算することもできます。
データは
5, 6, 7, 7, 6, 5, 8, 5, 5, 6
です。
1. 使う公式
母分散は次の公式で求められます。
$$
分散=\frac{1}{n}\sum x^2-\left(\frac{1}{n}\sum x\right)^2
$$
つまり、
- まず各値の2乗の平均を求める
- そこから平均値の2乗を引く
という形です。
2. 平均を求める
まず合計を出します。
$$
5+6+7+7+6+5+8+5+5+6=60
$$
データは10個あるので、
$$
平均=\frac{60}{10}=6
$$
3. 各値の2乗の合計を求める
それぞれ2乗します。
- $(5^2=25$)
- $(6^2=36$)
- $(7^2=49$)
- $(7^2=49$)
- $(6^2=36$
- $(5^2=25$)
- $(8^2=64$)
- $(5^2=25$)
- $(5^2=25$)
- $(6^2=36$)
これを全部足すと、
$$
25+36+49+49+36+25+64+25+25+36=370
$$
したがって、2乗の平均は
$$
\frac{370}{10}=37
$$
4. 公式に代入する
$$
分散=37-6^2
$$
$$
=37-36
$$
$$
=1
$$
したがって、
$$
分散=1.0
$$
です。
5. 標準偏差を求める
標準偏差は分散の平方根なので、
$$
標準偏差=\sqrt{1}=1
$$
よって、
$$
標準偏差=1.0
$$
です。
6. まとめ
- 平均値: 6.0
- 分散: 1.0
- 標準偏差: 1.0
7. この公式のよいところ
平均との差を毎回計算しなくてもよいので、値が多いときに計算しやすくなります。
考え方としては、
- ふつうの方法:$((x-平均)^2$) を全部計算する
- 公式を使う方法:$(x^2$) の平均と、平均の2乗を使う
という違いです。
標本分散では、割る数が変わります。
1. 母分散との違い
さきほどの分散は、データ全体をそのまま対象にしたので
$$
母分散=\frac{1}{n}\sum (x-\bar{x})^2
$$
を使いました。
一方、標本分散は、集団全体の一部だけを取り出したデータからばらつきを見積もるときに使い、
$$
標本分散=\frac{1}{n-1}\sum (x-\bar{x})^2
$$
で求めます。
違いはここです。
- 母分散: $(n$) で割る
- 標本分散: $(n-1$) で割る
この $(n-1$) を使う補正を、よく「不偏のための補正」と考えます。
2. 今回のデータで計算する
データは
5, 6, 7, 7, 6, 5, 8, 5, 5, 6
平均は
$$
\bar{x}=6
$$
でした。
また、平均との差の2乗の合計は
$$
\sum (x-\bar{x})^2=10
$$
でした。
したがって標本分散は
$$
\frac{10}{10-1}=\frac{10}{9}\approx 1.111...
$$
有効数字2桁で
$$
1.1
$$
です。
3. 標本標準偏差
標本標準偏差は、標本分散の平方根です。
$$
\sqrt{\frac{10}{9}} \approx 1.054...
$$
有効数字2桁で
$$
1.1
$$
です。
4. まとめ
今回のデータでは、
- 平均値: 6.0
- 母分散: 1.0
- 母標準偏差: 1.0
- 標本分散: 1.1
- 標本標準偏差: 1.1
となります。
5. どう使い分けるか
考えるときのポイントは次の通りです。
- 手元のデータ全部そのものについて調べる
→ 母分散 - 手元のデータを「全体の一部の標本」とみなして、もとの集団を推定したい
→ 標本分散
たとえば、クラス40人全員の点数なら母分散です。
一方、全国の生徒から10人だけ選んだデータなら、標本分散を使う考え方になります。
08. statisticsを使わない書き方
data = [5, 6, 7, 7, 6, 5, 8, 5, 5, 6]
n = len(data)
mean = sum(data) / n
variance = sum((x - mean) ** 2 for x in data) / n
std_dev = variance ** 0.5
print("データ:", data)
print("平均値:", mean)
print("分散:", variance)
print("標準偏差:", std_dev)
このコードは、与えられたデータの
- 平均値
- 分散
- 標準偏差
を順番に求めています。
まず、データは
5, 6, 7, 7, 6, 5, 8, 5, 5, 6
です。
1. 平均値
平均値は、
(5 + 6 + 7 + 7 + 6 + 5 + 8 + 5 + 5 + 6) ÷ 10
で求めます。
合計は 60、データの個数は 10 なので、
平均値 = 60 ÷ 10 = 6.0
コードではここです。
mean = sum(data) / n
-
sum(data)は合計 -
nはデータの個数です
2. 分散
分散は、「データが平均からどれくらい散らばっているか」を表します。
公式は
((x1 - 平均)^2 + (x2 - 平均)^2 + ... + (xn - 平均)^2) ÷ n
です。
今回の平均は 6 なので、各値について平均との差を2乗します。
- (5 - 6)^2 = 1
- (6 - 6)^2 = 0
- (7 - 6)^2 = 1
- (7 - 6)^2 = 1
- (6 - 6)^2 = 0
- (5 - 6)^2 = 1
- (8 - 6)^2 = 4
- (5 - 6)^2 = 1
- (5 - 6)^2 = 1
- (6 - 6)^2 = 0
合計は
1 + 0 + 1 + 1 + 0 + 1 + 4 + 1 + 1 + 0 = 10
したがって、
分散 = 10 ÷ 10 = 1.0
コードではここです。
variance = sum((x - mean) ** 2 for x in data) / n
これは
「各データ x について (x - mean) ** 2 を計算し、その合計を n で割る」
という意味です。
3. 標準偏差
標準偏差は、分散の平方根です。
つまり
標準偏差 = √分散 = √1.0 = 1.0
コードではここです。
std_dev = variance ** 0.5
** 0.5 は「0.5乗」、つまり平方根を表します。
4. このコードの出力
最終的に出る値は次の通りです。
- 平均値: 6.0
- 分散: 1.0
- 標準偏差: 1.0
補足
このコードでは、分散を求めるときに n で割っています。
これは「データ全体の分散」を求める書き方です。
もし学校で「標本分散」を習っている場合は、n - 1 で割ることもあります。
その場合は値が少し変わります。
09. 内包表記の解説
variance = sum((x - mean) ** 2 for x in data) / n
この表記がよくわかりません
この部分は、Pythonの「内包表記」に似た書き方を使っています。
sum((x - mean) ** 2 for x in data)
これは正確には、よく「内包表記っぽい書き方」と見られますが、[] がないので、リスト内包表記ではなく ジェネレータ式 です。
1. 全体の意味
この式は、
「data の中の各値 x について、(x - mean) ** 2 を計算し、それらを全部足す」
という意味です。
つまり、分散の公式にある
$$
(x_1-\text{平均})^2 + (x_2-\text{平均})^2 + \cdots + (x_n-\text{平均})^2
$$
をそのままPythonで書いた形に近いです。
2. 分解して見る
式を分けるとこうなります。
(x - mean) ** 2 for x in data
これは、
-
for x in data
→dataから1つずつ値を取り出して、xに入れる -
(x - mean) ** 2
→ 取り出したxについて、平均との差の2乗を計算する
という流れです。
たとえば data = [5, 6, 7]、mean = 6 なら、
- x = 5 のとき →
(5 - 6) ** 2 = 1 - x = 6 のとき →
(6 - 6) ** 2 = 0 - x = 7 のとき →
(7 - 6) ** 2 = 1
となります。
つまり、この部分は
1, 0, 1
のような値を順に作っているイメージです。
3. sum(...) の役割
その外側に sum(...) があるので、
sum((x - mean) ** 2 for x in data)
は、作られた値を全部足します。
たとえば先ほどの例なら
sum(1, 0, 1)
のようなイメージで、結果は 2 です。
実際には sum は「順番に出てくる値」を受け取って足しています。
4. 普通のfor文で書くと?
同じことを、もっと基本的な形で書くとこうです。
total = 0
for x in data:
total += (x - mean) ** 2
これと
sum((x - mean) ** 2 for x in data)
は、やっていることが同じです。
つまり、短くまとめて書いた形だと思えば大丈夫です。
5. リスト内包表記との違い
よく似た書き方に、リスト内包表記があります。
[(x - mean) ** 2 for x in data]
こちらは [] があるので、計算結果をリストとしてまとめて作る書き方です。
たとえば
[1, 0, 1, 1, 0]
のようなリストになります。
一方で、
((x - mean) ** 2 for x in data)
は、必要になるたびに1個ずつ値を出す形です。
そのため、sum() の中ではこちらがよく使われます。
6. 今回の式全体
もとの式はこれでした。
variance = sum((x - mean) ** 2 for x in data) / n
順番に読むと、
-
dataの各値xを取り出す -
(x - mean) ** 2を計算する - それを全部足す
- 最後に
nで割る
となります。
つまり、
「平均との差の2乗の平均」
を求めているので、分散になります。
7. 読み方のコツ
この形は、次の順で読むとわかりやすいです。
式 for 変数 in データ
今回なら
(x - mean) ** 2 for x in data
なので、
-
dataからxを1つずつ取り出して -
(x - mean) ** 2を作る
と読めばOKです。
8. まとめ
この部分
sum((x - mean) ** 2 for x in data)
は、
-
dataの各要素に対して - 平均との差の2乗を計算し
- その合計を求める
という意味です。
普通のfor文で書いたものを、短く表したものと考えると理解しやすいです。
参考資料