この実習では、アメリカの大学777校のデータ(College.csv)を使い、
卒業率(Grad.Rate)
という量的変数を例として、以下の分析を学ぶ。
# =====================================================================
# 【パッケージとは?】
# R には標準機能のほかに、追加の便利な機能(パッケージ)がある。
# パッケージは最初に1回だけ install.packages("パッケージ名") で
# インストールし、使うたびに library() で呼び出す。
#
# ここでは以下のパッケージを使う:
# tidyverse : データ操作と可視化の定番パッケージ群
# (ggplot2, dplyr, readr などをまとめて読み込む)
# cowplot : 複数の ggplot2 グラフを並べるパッケージ
# install.packages("cowplot") で事前インストールが必要
# =====================================================================
library(tidyverse) # データ操作と可視化に使う(ggplot2 も含まれる)
library(cowplot) # 複数グラフを並べて表示するパッケージ# =====================================================================
# 【read.csv() とは?】
# CSV ファイルを R に読み込んでデータフレームとして保存する関数。
# "ISLR_CSV_Data/College.csv" はファイルのパス(場所)を指定している。
# このRmdファイルと同じフォルダに「ISLR_CSV_Data」フォルダがある想定。
#
# 【<- とは?】
# 代入演算子。右辺の結果を左辺の名前に「保存」する。
# ここでは読み込んだデータを「college」という名前で保存している。
#
# 【$ 演算子】
# データフレームから特定の列(変数)を取り出すときに使う。
# college$Grad.Rate は「college の中の Grad.Rate 列」を意味する。
#
# 【x への代入】
# 毎回 college$Grad.Rate と書くのは冗長なので、
# 分析対象の変数を y という短い名前に保存しておく。
# 以降のコードでは y = 卒業率(Grad.Rate)として使う。
# =====================================================================
# CSV ファイルを読み込んでデータフレームとして保存
college <- read.csv("ISLR_CSV_Data/College.csv")
# 分析対象の変数(卒業率)を y に代入して以降の記述を簡潔にする
# ★ 以降のコードでは y が Grad.Rate(卒業率)を表す ★
y <- college$Grad.Rate# =====================================================================
# 【nrow() / ncol() / dim()】
# データの行数(観測数)と列数(変数数)を確認する関数。
# nrow() → 行数(= 大学の数)
# ncol() → 列数(= 変数の数)
# dim() → 行数と列数をまとめて表示(行数, 列数の順)
# =====================================================================
nrow(college) # 行数:何校分のデータがあるか## [1] 777
## [1] 19
## [1] 777 19
# =====================================================================
# 【head()】
# データの先頭数行を表示する関数。デフォルトは6行。
# head(college, 10) とすれば先頭10行が表示できる。
# データを読み込んだ直後に必ず実行して、正しく読めているか確認する。
# =====================================================================
head(college) # 先頭6行を表示してデータの中身を確認# =====================================================================
# 【str()】
# データフレームの「構造(structure)」を表示する関数。
# 各変数の型(int=整数, chr=文字列, num=数値など)と
# 最初のいくつかの値を一覧で確認できる。
# データを読んだら必ずチェックする習慣をつけよう。
# =====================================================================
str(college) # 変数の型と構造を確認## 'data.frame': 777 obs. of 19 variables:
## $ X : chr "Abilene Christian University" "Adelphi University" "Adrian College" "Agnes Scott College" ...
## $ Private : chr "Yes" "Yes" "Yes" "Yes" ...
## $ Apps : int 1660 2186 1428 417 193 587 353 1899 1038 582 ...
## $ Accept : int 1232 1924 1097 349 146 479 340 1720 839 498 ...
## $ Enroll : int 721 512 336 137 55 158 103 489 227 172 ...
## $ Top10perc : int 23 16 22 60 16 38 17 37 30 21 ...
## $ Top25perc : int 52 29 50 89 44 62 45 68 63 44 ...
## $ F.Undergrad: int 2885 2683 1036 510 249 678 416 1594 973 799 ...
## $ P.Undergrad: int 537 1227 99 63 869 41 230 32 306 78 ...
## $ Outstate : int 7440 12280 11250 12960 7560 13500 13290 13868 15595 10468 ...
## $ Room.Board : int 3300 6450 3750 5450 4120 3335 5720 4826 4400 3380 ...
## $ Books : int 450 750 400 450 800 500 500 450 300 660 ...
## $ Personal : int 2200 1500 1165 875 1500 675 1500 850 500 1800 ...
## $ PhD : int 70 29 53 92 76 67 90 89 79 40 ...
## $ Terminal : int 78 30 66 97 72 73 93 100 84 41 ...
## $ S.F.Ratio : num 18.1 12.2 12.9 7.7 11.9 9.4 11.5 13.7 11.3 11.5 ...
## $ perc.alumni: int 12 16 30 37 2 11 26 37 23 15 ...
## $ Expend : int 7041 10527 8735 19016 10922 9727 8861 11487 11644 8991 ...
## $ Grad.Rate : int 60 56 54 59 15 55 63 73 80 52 ...
# =====================================================================
# 【summary()】
# 各変数の基本的な要約統計量をまとめて表示する関数。
# 量的変数には:最小値・第1四分位数・中央値・平均値・第3四分位数・最大値
# 質的変数(文字列)には:値の個数などが表示される。
# まずここで全体像をつかむのがデータ分析の第一歩。
# =====================================================================
summary(college) # 全変数の要約統計量を一括表示## X Private Apps Accept
## Length:777 Length:777 Min. : 81 Min. : 72
## Class :character Class :character 1st Qu.: 776 1st Qu.: 604
## Mode :character Mode :character Median : 1558 Median : 1110
## Mean : 3002 Mean : 2019
## 3rd Qu.: 3624 3rd Qu.: 2424
## Max. :48094 Max. :26330
## Enroll Top10perc Top25perc F.Undergrad
## Min. : 35 Min. : 1.00 Min. : 9.0 Min. : 139
## 1st Qu.: 242 1st Qu.:15.00 1st Qu.: 41.0 1st Qu.: 992
## Median : 434 Median :23.00 Median : 54.0 Median : 1707
## Mean : 780 Mean :27.56 Mean : 55.8 Mean : 3700
## 3rd Qu.: 902 3rd Qu.:35.00 3rd Qu.: 69.0 3rd Qu.: 4005
## Max. :6392 Max. :96.00 Max. :100.0 Max. :31643
## P.Undergrad Outstate Room.Board Books
## Min. : 1.0 Min. : 2340 Min. :1780 Min. : 96.0
## 1st Qu.: 95.0 1st Qu.: 7320 1st Qu.:3597 1st Qu.: 470.0
## Median : 353.0 Median : 9990 Median :4200 Median : 500.0
## Mean : 855.3 Mean :10441 Mean :4358 Mean : 549.4
## 3rd Qu.: 967.0 3rd Qu.:12925 3rd Qu.:5050 3rd Qu.: 600.0
## Max. :21836.0 Max. :21700 Max. :8124 Max. :2340.0
## Personal PhD Terminal S.F.Ratio
## Min. : 250 Min. : 8.00 Min. : 24.0 Min. : 2.50
## 1st Qu.: 850 1st Qu.: 62.00 1st Qu.: 71.0 1st Qu.:11.50
## Median :1200 Median : 75.00 Median : 82.0 Median :13.60
## Mean :1341 Mean : 72.66 Mean : 79.7 Mean :14.09
## 3rd Qu.:1700 3rd Qu.: 85.00 3rd Qu.: 92.0 3rd Qu.:16.50
## Max. :6800 Max. :103.00 Max. :100.0 Max. :39.80
## perc.alumni Expend Grad.Rate
## Min. : 0.00 Min. : 3186 Min. : 10.00
## 1st Qu.:13.00 1st Qu.: 6751 1st Qu.: 53.00
## Median :21.00 Median : 8377 Median : 65.00
## Mean :22.74 Mean : 9660 Mean : 65.46
## 3rd Qu.:31.00 3rd Qu.:10830 3rd Qu.: 78.00
## Max. :64.00 Max. :56233 Max. :118.00
# =====================================================================
# 【変数 Grad.Rate とは?】
# 各大学の卒業率(%)。0〜100の値をとる量的変数(連続変数)。
# すでに y <- college$Grad.Rate として y に保存済み。
#
# 【length() / min() / max()】
# length() → データの個数(= 大学の数)
# min() → 最小値
# max() → 最大値
# =====================================================================
# x(= 卒業率)の基本情報を確認
length(y) # データの個数## [1] 777
## [1] 10
## [1] 118
# =====================================================================
# 【注意:Grad.Rate に 100 を超える値がある?】
# summary() を見ると最大値が 118 になっている。
# 卒業率は本来 0〜100% のはずなので、これは入力エラーの可能性がある。
# 実際のデータ分析では、こうした「おかしな値(外れ値・異常値)」を
# 見つけることも重要な作業のひとつ。
# 今回は確認だけして、そのまま分析を進める。
#
# college[条件, 列名] は「条件を満たす行の指定列を取り出す」操作。
# =====================================================================
# 100 を超えるデータがある大学を確認
college[y > 100, c("X", "Grad.Rate")]# =====================================================================
# 【ヒストグラムとは?】
# 量的変数の「分布の形」を視覚的に確認するグラフ。
# 横軸に変数の値の範囲(階級)、縦軸に度数(頻度)をとる。
#
# 【ggplot2 の基本的な書き方】
# ggplot(データ, aes(x = 変数名)) →「何を」「どう」描くかの土台
# + geom_histogram() → ヒストグラムを追加
# + labs() → タイトル・軸ラベルを追加
#
# 「+」でグラフの要素を積み上げていく書き方が ggplot2 の特徴。
# theme_bw() は setup チャンクで theme_set() により自動適用済みのため
# 各グラフに毎回書く必要はないが、明示的に書いても問題ない。
# =====================================================================
ggplot(college, aes(x = y)) +
geom_histogram(
binwidth = 5, # 階級幅(ここでは5%ごとに区切る)
fill = "steelblue", # バーの塗りつぶし色
color = "white" # バーの境界線の色
) +
labs(
title = "ヒストグラム:大学の卒業率", # グラフのタイトル
y = "卒業率(%)", # 横軸のラベル
y = "度数(大学数)" # 縦軸のラベル
)# =====================================================================
# 【階級幅(binwidth)の重要性】
# 階級幅が広すぎると分布の細かい形が見えなくなり、
# 狭すぎるとデコボコが多くなりすぎて全体像がつかみにくくなる。
# 複数の階級幅を試して、最も分布の形が読み取りやすいものを選ぼう。
#
# ここでは base R の hist() を使って3つの階級幅を並べて比較する。
# par(mfrow = c(1, 3)) は「グラフを1行3列に並べる」設定。
# par(mfrow = c(1, 1)) で元の1画面1グラフに戻す(必ず忘れずに)。
# =====================================================================
par(mfrow = c(1, 3)) # グラフを1行3列に並べる
# 階級幅 約2%:細かすぎる例
hist(y,
breaks = 50, # breaks でおおよその区切り数を指定
main = "階級幅:約2%",
xlab = "卒業率(%)",
col = "lightblue")
# 階級幅 約5%:ちょうど良い例
hist(y,
breaks = 20,
main = "階級幅:約5%",
xlab = "卒業率(%)",
col = "steelblue")
# 階級幅 約20%:広すぎる例
hist(y,
breaks = 5,
main = "階級幅:約20%",
xlab = "卒業率(%)",
col = "darkblue")確認ポイント: 階級幅によって分布の見え方はどう変わるか? どの階級幅が分布の特徴(山の形・裾の広がり)をいちばん読み取りやすいか考えてみよう。
# =====================================================================
# 【平均値(mean)とは?】
# 全データの合計 ÷ データの個数。
# すべてのデータを「均等に配分」したときの値。
# 外れ値(極端に大きい・小さい値)の影響を受けやすい。
#
# 【中央値(median)とは?】
# データを小さい順に並べたときの「真ん中」の値。
# データ数が偶数のときは、真ん中2つの平均をとる。
# 外れ値の影響を受けにくい(ロバストな指標)。
#
# 【平均と中央値の使い分け】
# 分布が左右対称に近い → 平均値が代表値として適切
# 分布が右や左に歪んでいる → 中央値の方が実態を反映しやすい
# 年収・地価など「外れ値が多いデータ」には中央値がよく使われる
# =====================================================================
mean(y) # 平均値## [1] 65.46332
## [1] 65
# =====================================================================
# 【ヒストグラムに平均・中央値を重ねて表示する】
# geom_vline() は縦線(vertical line)を追加する関数。
# xintercept に線を引く位置(x軸の値)を指定する。
# linetype で実線(solid)や破線(dashed)を切り替えられる。
#
# annotate() はグラフ上の任意の位置にテキストや図形を追加する関数。
# x, y でテキストを置く座標を指定する。
# =====================================================================
mean_val <- mean(y) # 平均値を変数に保存(グラフ内で2回使うため)
median_val <- median(y) # 中央値を変数に保存
ggplot(college, aes(x = y)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "white", alpha = 0.8) +
# 平均値を赤い実線で表示
geom_vline(xintercept = mean_val,
color = "red", linewidth = 1.2, linetype = "solid") +
# 中央値を橙色の破線で表示
geom_vline(xintercept = median_val,
color = "darkorange", linewidth = 1.2, linetype = "dashed") +
# 凡例の代わりにグラフ上にラベルを直接追加
annotate("text", x = mean_val + 1, y = 60,
label = paste0("平均値 = ", round(mean_val, 1)),
color = "red", hjust = 0, size = 4) +
annotate("text", x = median_val + 1, y = 55,
label = paste0("中央値 = ", round(median_val, 1)),
color = "darkorange", hjust = 0, size = 4) +
labs(title = "ヒストグラムに平均・中央値を重ねた図",
x = "卒業率(%)", y = "度数(大学数)")確認ポイント: - 平均値と中央値はどちらが大きいか? - ヒストグラムの形(左右の歪み)と、平均・中央値のズレの向きに関係はあるか?
# =====================================================================
# 【散布度(ばらつき)とは?】
# データが平均値のまわりにどれだけ散らばっているかを表す指標。
# 代表値だけではデータの特徴は十分にわからないため、
# 必ず散布度もセットで報告するのが基本。
#
# 【分散(variance)とは?】
# 各データと平均値の差(偏差)を2乗して平均したもの。
# 数式:s² = Σ(xᵢ - x̄)² / (n-1)
# ※ R の var() は「不偏分散」(n-1 で割る)を計算する。
# 単位が元データの2乗になるため、直感的に解釈しにくい。
#
# 【標準偏差(standard deviation)とは?】
# 分散の平方根。元データと同じ単位になるため解釈しやすい。
# 「平均からだいたいこのくらい離れている」という目安になる。
# 正規分布では:平均±1SD に約68%、±2SD に約95% のデータが入る。
#
# 【四分位範囲(IQR: Interquartile Range)とは?】
# 第3四分位数(Q3)- 第1四分位数(Q1)で求める。
# 中央の50%のデータが含まれる範囲を表す。
# 外れ値の影響を受けにくい「ロバストな散布度の指標」。
# =====================================================================
var(y) # 分散## [1] 295.0737
## [1] 17.17771
## 0% 25% 50% 75% 100%
## 10 53 65 78 118
## [1] 25
# =====================================================================
# 【まとめ表を作る】
# 上で計算した値をひとつの表にまとめて表示する。
# data.frame() でデータフレームを手動で作成できる。
# round(値, 桁数) は指定した桁数で四捨五入する関数。
# knitr::kable() は R の表をきれいな HTML テーブルに変換する関数。
# =====================================================================
# 第1・第3四分位数をあらかじめ計算して変数に保存
q1 <- quantile(y, 0.25) # 第1四分位数(下から25%の点)
q3 <- quantile(y, 0.75) # 第3四分位数(下から75%の点)
# 統計量をまとめた表を作成
summary_table <- data.frame(
統計量 = c("データ数", "平均値", "中央値", "分散", "標準偏差",
"第1四分位数(Q1)", "第3四分位数(Q3)", "四分位範囲(IQR)",
"最小値", "最大値"),
値 = round(c(
length(y),
mean(y),
median(y),
var(y),
sd(y),
q1,
q3,
IQR(y),
min(y),
max(y)
), 2)
)
# kable() で表を表示(caption はテーブルのキャプション)
knitr::kable(summary_table,
caption = "卒業率(Grad.Rate)の記述統計量まとめ",
align = c("l", "r"))| 統計量 | 値 |
|---|---|
| データ数 | 777.00 |
| 平均値 | 65.46 |
| 中央値 | 65.00 |
| 分散 | 295.07 |
| 標準偏差 | 17.18 |
| 第1四分位数(Q1) | 53.00 |
| 第3四分位数(Q3) | 78.00 |
| 四分位範囲(IQR) | 25.00 |
| 最小値 | 10.00 |
| 最大値 | 118.00 |
# =====================================================================
# 【箱ひげ図(box plot / box-and-whisker plot)とは?】
# 5つの統計量(最小値・Q1・中央値・Q3・最大値)を1つの図で表す。
# 分布のばらつき・歪み・外れ値を視覚的に確認できる強力なグラフ。
#
# 【箱ひげ図の読み方】
# ┌─────────┐
# │ │ ← 箱の上端:第3四分位数(Q3)
# │─────────│ ← 箱の中の線:中央値(Q2)
# │ │ ← 箱の下端:第1四分位数(Q1)
# └─────────┘
# │ ← ひげ上端:Q3 + 1.5×IQR まで
# │ ← ひげ下端:Q1 - 1.5×IQR まで
# ・ ← 点:ひげの外側の値 = 外れ値
#
# 箱の高さ(縦幅)= IQR(四分位範囲)
# ひげを超えた点は外れ値として個別に表示される
# =====================================================================
ggplot(college, aes(y = y)) +
geom_boxplot(
fill = "steelblue", # 箱の塗りつぶし色
color = "black", # 線の色
outlier.color = "red", # 外れ値の点の色
outlier.size = 2 # 外れ値の点の大きさ
) +
labs(
title = "箱ひげ図:大学の卒業率",
y = "卒業率(%)"
) +
# y 軸の目盛りラベルを消す(縦1変数の場合は不要なため)
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank())# =====================================================================
# 【geom_jitter() とは?】
# データの実際の値を点として重ねて表示する。
# 同じ値が重なって見えなくなるのを防ぐため、
# 点を左右にランダムに少しずらして(jitter)表示する。
#
# これにより「箱ひげ図の要約」と「実際のデータの分布」を
# 同時に確認できる、より情報量の多いグラフになる。
#
# outlier.shape = NA で箱ひげ図が自動表示する外れ値点を非表示にし、
# geom_jitter() 側の点と重複して二重に表示されるのを防ぐ。
# =====================================================================
ggplot(college, aes(x = "", y = y)) +
# まず箱ひげ図を描く(外れ値点は geom_jitter に任せて非表示に)
geom_boxplot(
fill = "steelblue",
color = "black",
alpha = 0.5, # 箱を半透明にして後ろの点が見えるようにする
outlier.shape = NA # 外れ値の点を非表示(geom_jitter で代わりに表示)
) +
# 実際のデータ点を重ねる
geom_jitter(
width = 0.15, # 左右のずらし幅(小さいほど中央に集まる)
alpha = 0.3, # 点の透明度(0=完全透明 ↔ 1=不透明)
color = "black",
size = 1.5
) +
labs(
title = "箱ひげ図+データ点:大学の卒業率",
y = "",
y = "卒業率(%)"
)# =====================================================================
# 【plot_grid() とは?(cowplot パッケージ)】
# 複数の ggplot2 グラフを格子状に並べて1枚の図にまとめる関数。
# ncol = 1 で縦に並べる、rel_heights で各グラフの高さ比率を指定。
#
# ヒストグラムと横向き箱ひげ図を縦に並べることで、
# 「同じ y 軸スケール」で分布の形を比較しやすくなる。
# =====================================================================
# ヒストグラム(上段)
p_hist <- ggplot(college, aes(x = y)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "white") +
geom_vline(xintercept = mean_val,
color = "red", linewidth = 1, linetype = "solid") +
geom_vline(xintercept = median_val,
color = "darkorange", linewidth = 1, linetype = "dashed") +
labs(title = "ヒストグラム(赤実線=平均値、橙破線=中央値)",
y = "卒業率(%)", y = "度数")
# 横向き箱ひげ図(下段):x 軸をヒストグラムと揃えるため aes(x=) で指定
p_box <- ggplot(college, aes(x = y, y = "")) +
geom_boxplot(fill = "steelblue", color = "black",
outlier.color = "red", outlier.size = 2) +
geom_vline(xintercept = mean_val,
color = "red", linewidth = 1, linetype = "solid") +
labs(title = "箱ひげ図(横向き)", x = "卒業率(%)", y = "")
# 2つを縦に並べる(高さ比率 2:1 でヒストグラムを大きく)
plot_grid(p_hist, p_box, ncol = 1, rel_heights = c(2, 1))確認ポイント: - ヒストグラムで確認した分布の形(歪み)が箱ひげ図にも反映されているか? - 外れ値(赤い点)はどのくらいあるか?それはどのような大学か想像してみよう。
# =====================================================================
# 【分析結果を日本語で解釈する練習】
# 数値やグラフを出すだけではなく、それが「何を意味するか」を
# 言葉で説明することが統計学で最も重要なスキルのひとつ。
#
# cat() : 文字列をコンソール(出力欄)に表示する関数
# sprintf(): C言語風の書式指定で数値を文字列に埋め込む関数
# %d → 整数
# %.1f → 小数点1桁の実数
# %% → % 記号そのもの(%% と書くと % が1つ表示される)
# =====================================================================
cat("============================================\n")## ============================================
## 卒業率(Grad.Rate)の要約
## ============================================
## データ数 : 777 校
## 最小値 : 10.0 %
## 最大値 : 118.0 %
## 平均値 : 65.5 %
## 中央値 : 65.0 %
## 標準偏差 : 17.2 ポイント
## Q1(25%) : 53.0 %
## Q3(75%) : 78.0 %
## 四分位範囲 : 25.0 ポイント
## ============================================
以下の空欄を埋めて、分析結果を文章でまとめよう。
アメリカの大学777校の卒業率(Grad.Rate)を分析した。
卒業率の平均値は約 [ ] %、中央値は約 [ ] % であり、 平均値が中央値より【大きい / 小さい】ことから、分布は【右 / 左】に歪んでいることが確認できる。
ヒストグラムをみると、卒業率は [ ] % 前後に山がある【単峰性 / 双峰性】の分布で、 分布の広がりは標準偏差 [ ] ポイントであった。
箱ひげ図から、中央50%の大学が [ ] %〜 [ ] % の範囲(IQR = [ ] ポイント)に 集中していることがわかる。また、ひげの外側に [ ] 校の外れ値が確認された。
# =====================================================================
# 【グループ別の比較(次回以降の内容)】
# College データには Private(私立か否か)という質的変数がある。
# これを使ってグループ別に箱ひげ図を描くと、
# 私立と公立で卒業率の分布がどう異なるか比較できる。
# t 検定(2グループの平均値の差の検定)につながる分析の第一歩。
# =====================================================================
# 私立・公立別の平行箱ひげ図(プレビュー)
ggplot(college, aes(x = Private, y = y, fill = Private)) +
geom_boxplot(color = "black",
outlier.color = "red", outlier.size = 2) +
scale_fill_manual(values = c("No" = "lightcoral", "Yes" = "steelblue")) +
scale_x_discrete(labels = c("No" = "公立", "Yes" = "私立")) +
labs(
title = "【予告】私立・公立別の卒業率の分布",
subtitle = "この差が「偶然か否か」はt検定(推測統計)で判断する",
y = "大学の種別",
y = "卒業率(%)"
) +
theme(legend.position = "none")次のステップへ: グループ間に「見た目の差」があることはわかった。 しかしこれが「偶然ではない差」かどうかを判断するには、 推測統計(t 検定・ANOVA) が必要になる。それは3年生の内容で学ぼう。
作成:久保田貴文(多摩大学)