本記事は、統計学のテキストの内容をRでコード実装するシリーズです。
この記事で扱うデータおよび度数分布表の考え方は、小島寛之著『完全独習 統計学入門』(ダイヤモンド社)を参考にしています。
今回は、上記テキストで示されている「分散・標準偏差を求める考え方」について、R を用いて具体的に確認することを目的とします。
実行環境
実行環境は以下の通りです。
| 項目 | バージョン |
|---|---|
| OS | Windows 11 Home 64bit (バージョン 24H2) |
| R | 4.5.1 |
| RStudio | 2025.09.0 |
参考文献
参考図書はこちらです。
また、以下の記事も参考にさせていただきました。
データの準備1
最初は、本書P.36に掲載されている架空のバスの到着時刻データ(図表3-1)を使用します。
# バスの到着時刻(単位:分)
bus_arrival_minutes <- c(32, 27, 29, 34, 33)5 回分の観測値があり、値はおおむね 30 分前後に分布しています。
データの散らばり・ばらつきを知りたい
前回の記事では、平均値について詳しく見てきました。

平均値は、分布しているデータを代表する 1 点を与えてくれる統計量です。
しかし、データが平均値の周囲に分布していることは分かりますが、その分布が「どれくらい広がっているか」「どれくらい散らばっているか」までは分かりません。
平均値だけでは分からない例
たとえば、あるバス A とバス B の運行状態を比較することを考えます。
- バス A は、時刻表に対して等確率で2分早着または2分遅延する
- バス B は、時刻表に対して等確率で10分早着または10分遅延する
このとき、いずれのバスも「早着」と「遅延」が正負対称であるため、到着時刻の平均をとると時刻表通りに運行しているという結果になります。
しかし、実際に利用する立場で考えると、到着時刻の前後10分のばらつきがあるバス B よりも、前後2分程度に収まるバス A の方が好ましい、と感じる人が多いでしょう。
このように、平均値が同じでも、ばらつきの大きさが異なることがあります。そのため、上記のような場合は、平均値に加えてデータの散らばり具合を表す統計量を知ることが重要といえます。
偏差と二乗平均
データのばらつきを考えるために、まずは各データが平均値からどれだけ離れているかを確認します。
#平均値
mean_arrival_minutes <- mean(bus_arrival_minutes)
mean_arrival_minutes
#偏差
deviation_arrival_minutes <- bus_arrival_minutes - mean_arrival_minutes
deviation_arrival_minutes## [1] 31
## [1] 1 -4 -2 3 2この「各データ-平均値」で計算された値を偏差(deviation)と呼びます。偏差は「各データが平均値からどのくらい離れているか」を表します。
ここで、5 つの偏差を 1 つの値にまとめることを考えます。まずは単純に、偏差の算術平均を計算してみます。
#偏差の算術平均(0になることを確認)
mean_dev_arrival_minutes <- mean(dev_arrival_minutes)
mean_dev_arrival_minutes## [1] 0すると、結果は0になってしまいます。これは、平均値が「偏差のつり合い点」になっており、正の偏差と負の偏差が互いに打ち消し合うためです。
そのため、偏差をそのまま平均しても、ばらつきの大きさは評価できません。そこで、偏差の正負を打ち消さない方法として、二乗を用います。
たとえば、2つの数値\( x, y \)があるとき、これらの二乗平均(root mean squre; RMS)は次のように計算されます。
$$ \sqrt{\frac{(x^2+y^2)}{2}} $$
つまり、
- 各値を二乗する
- それらの平均を取る
- 平方根を取る
という計算です。
二乗することで、値の正負に関係なく「大きさ」だけを評価できるようになります。
分散と標準偏差
統計学では、この平方根を取る前の量を分散(variance)と呼びます。
ここで、今回のバスの到着時刻データについて、5つの偏差をそれぞれ二乗し、その平均を計算してみます。
$$ \frac{(+1)^2+(-4)^2+(-2)^2+(+3)^2+(+2)^2}{5} $$
#偏差を二乗した平均(分散)
variance_arrival_minutes <-
sum(dev_arrival_minutes^2) / length(dev_arrival_minutes)
variance_arrival_minutes## [1] 6.8この値が、到着時刻データの分散です。分散は、「データのばらつき具合」を評価する量として解釈できます。
ただし、分散は偏差を二乗して計算しているため、単位が [\( 分^2 \)] になります。そのため、元データ(単位: [\( 分 \)] )と直接比較したり、感覚的に理解したりするのがやや難しくなります。
そのため、分散の平方根を取り、単位を元データと同じ [\( 分 \)] にそろえます。こうして得られる統計量を標準偏差(standard deviation; SD)と呼びます。
#標準偏差
sd_arrival_minutes <- sqrt(variance_arrival_minutes)
sd_arrival_minutes## [1] 2.607681標準偏差は「偏差の二乗平均」であり、「平均値から、どの程度のズレが典型的に生じているか」を表す量として解釈することができます。
つまり、バスの到着時刻の平均が31分、標準偏差が約2.6分であることから、このバスが「時刻表では7時30分到着」とされている場合、「バスは平均的には時刻表より1分遅れて到着するが、実際の到着時刻はその前後におよそ2.6分散らばっている」と理解することができます。
データの準備2
次に、本書P.39に掲載されている架空の10点満点のテストの得点データ(図表3-4)を使用します。
# テストの得点データ(単位:点)
score_x <- c(4, 4, 5, 6, 6)
score_y <- c(1, 2, 6, 7, 9)ぱっと見た感じでは、score_yの方がばらつきが大きいデータだとわかります。
標準偏差の比較
以下のようにして、それぞれの得点データの標準偏差を求めます。
#平均値
mean_x <- mean(score_x)
mean_y <- mean(score_y)
mean_x
mean_y
#偏差
dev_x <- score_x - mean_x
dev_y <- score_y - mean_y
dev_x
dev_y
#標準偏差
sd_x <-sqrt(sum(dev_x^2) / length(dev_x))
sd_y <-sqrt(sum(dev_y^2) / length(dev_y))
sd_x
sd_y## [1] 5
## [1] 5
## [1] -1 -1 0 1 1
## [1] -4 -3 1 2 4
## [1] 0.8944272
## [1] 3.03315実際に標準偏差を求めてみると、score_yのSDはおよそ3.03であり、score_xの0.89よりも大きいことがわかります。
度数分布表から分散と標準偏差を求める
ここでは、以下のように与えられた度数分布表を用いて、分散と標準偏差を計算していきます。
# 度数分布表
class_marks <- c(1, 2, 3, 4) #階級値(A)
relative_freq <- c(0.3, 0.5, 0.1, 0.1) #相対度数(B)まずは、平均値(加重平均)を計算します。
#階級値×相対度数(A×B)
weighted_class_marks <- class_marks * relative_freq
weighted_class_marks
#平均値(加重平均)
mean_class_marks <- sum(weighted_class_marks)
mean_class_marks## [1] 0.3 1.0 0.3 0.4
## [1] 2平均値は2.0であることがわかりました。ここまでの計算を表にまとめると、次のようになります。
| A階級値 | B相対度数 | A×B |
|---|---|---|
| 1 | 0.3 | 0.3 |
| 2 | 0.5 | 1.0 |
| 3 | 0.1 | 0.3 |
| 4 | 0.1 | 0.4 |
次に、それぞれの階級値における偏差を計算します。その後、偏差を2乗して相対度数を掛けて合計することで、分散を計算します。
#偏差(C)
dev_class_marks <- class_marks - mean_class_marks
dev_class_marks
#データフレームで整理
freq_df <- data.frame(
A_class_marks = class_marks,
C_dev = dev_class_marks,
C_squared = dev_class_marks^2,
B_relative_freq = relative_freq
)
freq_df
#C_squared_x_Bを追加
freq_df$C_squared_x_B <-
freq_df$C_squared * freq_df$B_relative_freq
freq_df
#分散
variance_class_marks <- sum(freq_df$C_squared_x_B)
variance_class_marks## [1] -1 0 1 2
## A_class_marks C_dev C_squared B_relative_freq
## 1 1 -1 1 0.3
## 2 2 0 0 0.5
## 3 3 1 1 0.1
## 4 4 2 4 0.1
## A_class_marks C_dev C_squared B_relative_freq C_squared_x_B
## 1 1 -1 1 0.3 0.3
## 2 2 0 0 0.5 0.0
## 3 3 1 1 0.1 0.1
## 4 4 2 4 0.1 0.4
## [1] 0.8分散は0.8であることがわかりました。ここまでの計算を表にまとめると、次のようになります。
| A階級値 | C階級値-平均値 | C^2 | B相対度数 | C^2×B |
|---|---|---|---|---|
| 1 | -1 | 1 | 0.3 | 0.3 |
| 2 | 0 | 0 | 0.5 | 0 |
| 3 | +1 | 1 | 0.1 | 0.1 |
| 4 | +2 | 4 | 0.1 | 0.4 |
よって、標準偏差は以下のように求められます。
#標準偏差
sd_class_marks <- sqrt(variance_class_marks)
sd_class_marks## [1] 0.8944272なぜ分散・標準偏差が計算できるのか
以上の操作は、数式で表すと次のようになります。
$$ \sum_i\left\{(階級値_i-平均値)^2×相対度数_i\right\}=分散 $$
$$ \sqrt{分散}=標準偏差 $$
ここで、相対度数は以下のように定義されます。
$$ 相対度数_i = \frac{度数_i}{全体のデータ数n} $$
これを用いると、分散の式は次のように変形できます。
\begin{eqnarray*}
\sum_i\left\{(階級値_i-平均値)^2×相対度数_i\right\}
&=& \sum_i\left\{(階級値_i-平均値)^2×\frac{度数_i}{n}\right\}\\
&=& \frac{1}{n}\sum_i\left\{(階級値_i-平均値)^2×度数_i\right\}\\
&=& 分散
\end{eqnarray*}
よって、「各階級の偏差の2乗に相対度数を掛けて合計する」ことは、「各階級の偏差の2乗に度数を掛けて合計し、最後に全体のデータ数nで割る」ことと数学的に等価です。
このように、度数分布表から求めた平均値(加重平均)をもとにして、データの散らばり具合を示す分散や標準偏差を計算できることがわかりました。
練習問題
本書 P.42に掲載されている架空のデータから、ステップごとに標準偏差を計算します。
#サンプルデータ
x <- c(6, 4, 6, 6, 6, 3, 7, 2, 2, 8)結果は、以下のようになりました。
# 平均値
mean_x <- mean(x)
mean_x
# 偏差
dev_x <- x - mean_x
dev_x
# 偏差の二乗
dev_x_squared <- dev_x^2
dev_x_squared
# 偏差の二乗の平均(分散)
var_x <- mean(dev_x_squared)
var_x
# 標準偏差
sd_x <- sqrt(var_x)
sd_x## [1] 5
## [1] 1 -1 1 1 1 -2 2 -3 -3 3
## [1] 1 1 1 1 1 4 4 9 9 9
## [1] 4
## [1] 2まとめ
今回の記事では、データのばらつき具合を表す分散と標準偏差の計算方法を、Rによる実装とあわせて整理しました。
標準偏差は「データの平均値からの離れ方を平均化したもの」であり、典型的にどのくらいのズレが生じているかを表す指標です。
著者の小島氏が「統計学にとって最も重要な道具は標準偏差である」と書いているだけあって、本書では標準偏差の考え方が直感的に分かるように説明されています。
私も、標準偏差は統計学の初歩を学ぶ上で最も大切な考え方だと思っています。これを土台にして、着実に理解を積み重ねていきたいですね。

