library(conflicted) # 関数名の衝突を警告
conflicts_prefer( # 優先的に使う関数を指定
::filter(),
dplyr::select(),
dplyr::lag(),
dplyr
)library(tidyverse)
#' 日本語を用いるので macOS ではフォントの設定を行う
if(Sys.info()["sysname"] == "Darwin") { # macOS か調べて日本語フォントを指定
theme_update(text = element_text(family = "HiraginoSans-W4"))
update_geom_defaults("text", list(family = theme_get()$text$family))
update_geom_defaults("label", list(family = theme_get()$text$family))}
統計データ解析I
第13講 練習問題 解答例
準備
以下で利用する共通パッケージを読み込む.
回帰分析の確率シミュレーション
問題
回帰分析におけるモデルの推定量の精度に関する 確率シミュレーションを考えなさい.
解答例
人工データによる回帰モデルの推定を行う. 以下のモデルのパラメタは適当に変更してよい.
<- 2 # 切片
alpha <- 3 # 回帰係数
beta <- 20 # データ数
n <- 0.5 # 誤差の標準偏差 sigma
データを生成する.
<- runif(n, min = -1, max = 1) # 説明変数 (区間[-1,1]を想定)
x <- rnorm(n, sd = sigma) # 誤差 (正規分布)
epsilon <- alpha + beta * x + epsilon y
データの視覚化を行う
<- tibble(x = x, y = y)
toy_data <- # 後で描き加えるため保存しておく
gg |>
toy_data ggplot(aes(x = x, y = y)) +
geom_point(colour = "forestgreen")
print(gg)
回帰式の推定を行う.
<- lm(y ~ x, data = toy_data)
toy_lm coef(toy_lm) # 推定された係数の取得
(Intercept) x
1.979740 2.701823
推定された回帰分析の結果を表示する. これらの方法については回帰係数の有意性検定でも詳述する.
#' base R での情報の表示
|> summary() # さまざまな情報がlist形式 toy_lm
Call:
lm(formula = y ~ x, data = toy_data)
Residuals:
Min 1Q Median 3Q Max
-0.8331 -0.4578 -0.1656 0.4227 1.1536
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.9797 0.1525 12.98 1.42e-10 ***
x 2.7018 0.2456 11.00 2.02e-09 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.6664 on 18 degrees of freedom
Multiple R-squared: 0.8705, Adjusted R-squared: 0.8633
F-statistic: 121 on 1 and 18 DF, p-value: 2.023e-09
#' tidyverse での情報の表示 (tibble形式)
|> broom::tidy() # 推定された係数の情報 toy_lm
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 1.98 0.153 13.0 1.42e-10
2 x 2.70 0.246 11.0 2.02e- 9
|> broom::glance() # 推定に関するさまざまな情報 toy_lm
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.870 0.863 0.666 121. 0.00000000202 1 -19.2 44.4 47.4
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
|> broom::augment() # 推定に用いられたデータの情報 toy_lm
# A tibble: 20 × 8
y x .fitted .resid .hat .sigma .cooksd .std.resid
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 5.76 0.970 4.60 1.15 0.215 0.609 0.524 1.95
2 -0.113 -0.863 -0.351 0.238 0.122 0.683 0.0101 0.381
3 1.92 -0.192 1.46 0.456 0.0505 0.676 0.0131 0.702
4 1.93 0.255 2.67 -0.736 0.0704 0.660 0.0497 -1.15
5 3.26 0.543 3.45 -0.182 0.112 0.684 0.00532 -0.290
6 0.372 -0.673 0.163 0.209 0.0896 0.684 0.00533 0.329
7 2.25 0.131 2.33 -0.0867 0.0595 0.685 0.000568 -0.134
8 3.00 0.686 3.83 -0.833 0.141 0.650 0.149 -1.35
9 -0.322 -0.694 0.104 -0.425 0.0928 0.677 0.0230 -0.670
10 -0.608 -0.657 0.204 -0.812 0.0873 0.654 0.0778 -1.28
11 2.82 0.462 3.23 -0.404 0.0980 0.678 0.0221 -0.638
12 -1.25 -0.919 -0.504 -0.743 0.134 0.658 0.111 -1.20
13 -0.194 -0.957 -0.605 0.412 0.142 0.677 0.0369 0.667
14 0.518 -0.463 0.728 -0.211 0.0648 0.684 0.00370 -0.327
15 1.93 -0.386 0.937 0.993 0.0587 0.639 0.0736 1.54
16 1.90 0.0694 2.17 -0.266 0.0556 0.683 0.00496 -0.410
17 3.69 0.221 2.58 1.11 0.0670 0.627 0.107 1.72
18 0.882 -0.201 1.44 -0.555 0.0506 0.672 0.0195 -0.855
19 4.06 0.825 4.21 -0.149 0.175 0.685 0.00640 -0.246
20 0.610 -0.815 -0.222 0.832 0.113 0.651 0.112 1.33
推定結果の視覚化を行う.
+
gg geom_abline(intercept = alpha,
slope = beta,
colour = "red") + # 真の回帰式
geom_abline(intercept = coef(toy_lm)[1],
slope = coef(toy_lm)[2],
colour = "blue") # 推定された回帰式
Monte-Carlo 実験を行う.
<- function(){
mc_trial <- rnorm(n, sd = sigma)
epsilon <- alpha + beta * x + epsilon # 説明変数は固定しておく
y <- lm(y ~ x) # データフレームにせずに直接 x,y を渡す
est #' データフレームにする場合は以下のようにすればよい
#' lm(y ~ x, data = tibble(x = x, y = y))
return(coef(est))
}<- # 実験結果をデータフレームに変換
mc_data replicate(2000, mc_trial()) |> t() |> as_tibble()
推定値の分布を視覚化する.
|> # 切片
mc_data ggplot(aes(x = `(Intercept)`)) +
geom_density(fill = "pink") +
geom_vline(xintercept = alpha, colour = "orange") +
labs(x = expression(hat(alpha)), title = "切片の分布")
|> # 傾き
mc_data ggplot(aes(x = x)) +
geom_density(fill = "palegreen") +
geom_vline(xintercept = beta, colour = "darkgreen") +
labs(x = expression(hat(beta)), title = "傾きの分布")
推定された回帰式のばらつきを表示する.
|>
mc_data slice_sample(n = 40) |> # Monte-Carlo 実験から40個ランダムに選択
rowid_to_column() |> # 番号列(rowid)を作成
ggplot() +
geom_abline(aes(intercept = `(Intercept)`,
slope = x,
colour = as_factor(rowid)), # 色を変える
alpha = 0.4, # alpha値を低くして色を薄くする
show.legend = FALSE) + # 凡例は表示しない
geom_abline(intercept = alpha,
slope = beta,
colour = "red",
linewidth = 1.1) + # 真の回帰式(太め)
xlim(-1,1) + ylim(alpha-beta*1.1, alpha+beta*1.1) + # 描画範囲の指定
labs(title = "推定された回帰式のばらつき")
同じ生成モデルでもデータによって推定結果がばらつくことがわかる.
回帰モデルの点推定
問題
東京の気象データを用いて, 必要であれば適当な期間を抽出し, 日射量から気温を説明する回帰モデルを構成しなさい.
解答例
データの読み込みを行う.
<- read_csv("data/tokyo_weather.csv") tw_data
データの散布図 (1年分) を描く.
|>
tw_data ggplot(aes(x = solar, y = temp)) +
geom_point(colour = "olivedrab") +
labs(x = "日射量", y = "気温")
回帰式の推定を行い,その結果を表示する.
<- lm(temp ~ solar, # 目的変数 ~ 説明変数
tw_lm data = tw_data) # 気温を日射量で説明
|> summary() # 結果の要約 tw_lm
Call:
lm(formula = temp ~ solar, data = tw_data)
Residuals:
Min 1Q Median 3Q Max
-15.755 -7.149 0.513 7.468 14.345
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.19919 0.89429 12.523 < 2e-16 ***
solar 0.46433 0.05749 8.077 9.82e-15 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 7.707 on 364 degrees of freedom
Multiple R-squared: 0.152, Adjusted R-squared: 0.1497
F-statistic: 65.24 on 1 and 364 DF, p-value: 9.825e-15
|> broom::tidy() # 係数とその統計量 tw_lm
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 11.2 0.894 12.5 3.64e-30
2 solar 0.464 0.0575 8.08 9.82e-15
|> broom::glance() # その他の統計量 tw_lm
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.152 0.150 7.71 65.2 9.82e-15 1 -1266. 2538. 2549.
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
回帰直線を前の図に重ね描きして図示する.
last_plot() +
geom_abline(intercept = coef(tw_lm)[1], # 切片
slope = coef(tw_lm)[2], # 回帰係数
colour = "slateblue",
linewidth = 1.2)
関数 geom_smooth()
を用いることもできる.
|>
tw_data ggplot(aes(x = solar, y = temp)) +
geom_point(colour = "olivedrab") +
geom_smooth(method = "lm", # 関数 lm を用いて信頼区間(平滑化方法)を計算
se = FALSE, # 信頼区間を付けない
colour = "slateblue") +
labs(x = "日射量", y = "気温")
期間を限って分析する. 夏のモデルのためのデータの散布図を描く.
|>
tw_data filter(month %in% 7:9) |> # 7月-9月を抽出
ggplot(aes(x = solar, y = temp)) +
geom_point(colour = "olivedrab") +
labs(x = "日射量", y = "気温")
回帰式の推定を行い,その結果を表示する.
<- lm(formula(tw_lm), # 前の式を利用
tw_lm2 data = tw_data,
subset = month %in% 7:9) # 7月-9月を抽出
|> summary() tw_lm2
Call:
lm(formula = formula(tw_lm), data = tw_data, subset = month %in%
7:9)
Residuals:
Min 1Q Median 3Q Max
-6.2489 -0.8316 0.3418 1.0467 4.1866
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 23.43954 0.51095 45.874 < 2e-16 ***
solar 0.28037 0.02872 9.761 8.95e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.732 on 90 degrees of freedom
Multiple R-squared: 0.5143, Adjusted R-squared: 0.5089
F-statistic: 95.28 on 1 and 90 DF, p-value: 8.951e-16
期間を限った分析は以下のように書くこともできる.
|>
tw_data filter(month %in% 7:9) |> # 7月-9月を抽出
lm(formula(tw_lm), data = _) # パイプ演算の内容を data に渡す
Call:
lm(formula = formula(tw_lm), data = filter(tw_data, month %in%
7:9))
Coefficients:
(Intercept) solar
23.4395 0.2804
推定結果の可視化を行う.
last_plot() +
geom_abline(intercept = coef(tw_lm2)[1],
slope = coef(tw_lm2)[2],
colour = "tomato",
linewidth = 1.2)
関数 geom_smooth()
を用いてもよい.
|>
tw_data filter(month %in% 7:9) |>
ggplot(aes(x = solar, y = temp)) +
geom_point(colour = "olivedrab") +
geom_smooth(method = "lm",
se = FALSE,
colour = "tomato") +
labs(x = "日射量", y = "気温")
全データのモデルと夏のモデルを比較する.
|>
tw_data mutate(summer = ifelse(month %in% 7:9,
"Jul-Sep", # 7月-9月のラベル
"others")) |>
ggplot(aes(x = solar, y = temp, colour = summer)) +
geom_point() +
geom_abline(intercept = coef(tw_lm)[1],
slope = coef(tw_lm)[2],
colour = "slateblue",
linewidth = 1.2) +
geom_abline(intercept = coef(tw_lm2)[1],
slope = coef(tw_lm2)[2],
colour = "tomato",
linewidth = 1.2) +
labs(x = "日射量", y = "気温", colour = NULL)
関数 geom_smooth()
を用いる場合は以下のようにすればよい.
|>
tw_data mutate(summer = ifelse(month %in% 7:9,
"7-9月", # 7月-9月のラベル
"その他")) |>
ggplot(aes(x = solar, y = temp, colour = summer)) +
geom_point() +
geom_smooth(method = "lm",
se = FALSE,
colour = "slateblue") +
geom_smooth(data = \(x)filter(x, summer == "7-9月"), # 7-9月に限定
method = "lm",
se = FALSE,
colour = "tomato") +
labs(x = "日射量", y = "気温")
data
に一変数関数を渡すと関数 geom_smooth()
内での処理を限定することができる. 上記は base R での無名関数の記述を用いているが,tidyverse では
~ filter(., summer == "7-9月")
%>% filter(summer == "7-9月") .
のように書くこともできる.
回帰モデルの区間推定
問題
前問で作成した回帰モデルについて区間推定を行いなさい.
解答例
前問で作成した1年分のモデル tw_lm
を用いて区間推定を行う.
confint(tw_lm)
2.5 % 97.5 %
(Intercept) 9.4405734 12.9578089
solar 0.3512825 0.5773738
区間推定を視覚化する. 関数 geom_smooth()
を用いると簡潔に記述できる.
|>
tw_data ggplot(aes(x = solar, y = temp)) +
geom_point(aes(colour = factor(month))) + # 月ごとに色を変える
geom_smooth(method = "lm", # 関数 lm を用いて信頼区間(平滑化方法)を計算
level = 0.95, # 既定値なので無くても良い
colour = "royalblue", # 線の色
fill = "steelblue") + # 塗り潰しの色
labs(x = "日射量", y = "気温", colour = NULL)
上記の描画を愚直に行うには以下のような手続きを考えればよい.
視覚化したい信頼区間に合わせて適切な説明変数と信頼区間を作成する.
<-
tw_conf |>
tw_lm ::augment(newdata = tibble(solar = tw_data |> pull(solar) |>
broomrange() |> # 日射量の範囲を取得
pretty(n = 50)), # 50個程度の区間を作成
interval = "confidence",
conf.level = 0.95) # 既定値なので無くてもよい
データ点と信頼区間を描画する.
|>
tw_data ggplot(aes(x = solar, y = temp)) +
geom_point(aes(colour = factor(month))) +
geom_abline(intercept = coef(tw_lm)[1],
slope = coef(tw_lm)[2],
colour = "royalblue",
linewidth = 1.2) +
geom_ribbon(data = tw_conf, # temp 列の代わりに .fitted列がある
aes(x = solar, y = .fitted,
ymin = .lower, ymax = .upper),
fill = alpha("steelblue", 0.3)) +
labs(x = "日射量", y = "気温", colour = NULL)
データ数がある程度多い場合はデータの説明変数をそのまま用いてもよい.
|>
tw_lm ::augment(interval = "confidence") |>
broomggplot(aes(x = solar, y = temp)) +
geom_point(colour = "olivedrab") + # augmentの出力にmonthは含まれていないため
geom_line(aes(y = .fitted),
colour = "royalblue") +
geom_ribbon(aes(ymin = .lower, ymax = .upper),
fill = alpha("steelblue", 0.3)) +
labs(x = "日射量", y = "気温")
データに信頼区間を追加する方法もある.
|>
tw_data mutate(broom::augment(tw_lm, interval = "confidence")) |>
ggplot(aes(x = solar, y = temp)) +
geom_point(aes(colour = factor(month))) +
geom_line(aes(y = .fitted),
colour = "royalblue") +
geom_ribbon(aes(ymin = .lower, ymax = .upper),
fill = alpha("steelblue", 0.3)) +
labs(x = "日射量", y = "気温", colour = NULL)
|>
tw_data mutate(predict(tw_lm, # 推定したモデル
interval = "confidence", # 信頼区間の推定を指定
level = 0.95) |>
as_tibble()) |> # tibble形式に変換して追加する (列名に注意)
ggplot(aes(x = solar, y = temp)) +
geom_point(aes(colour = factor(month))) + # augmentの出力にmonthは含まれていないため
geom_line(aes(y = fit), # predict の出力は .fitted でない
colour = "royalblue") +
geom_ribbon(aes(ymin = lwr, ymax = upr), # predict の出力は .lower/.upper でない
fill = alpha("steelblue", 0.3)) +
labs(x = "日射量", y = "気温", colour = NULL)
夏のモデル tw_lm2
で同様に区間推定を行う.
confint(tw_lm2)
2.5 % 97.5 %
(Intercept) 22.4244444 24.4546376
solar 0.2233102 0.3374357
視覚化を行う
model.frame(tw_lm2) |> # モデルの作成に用いたデータ
ggplot(aes(x = solar, y = temp)) +
geom_point(colour = "orange") +
geom_smooth(method = "lm", level = 0.95,
colour = "red", fill = "pink") +
labs(x = "日射量", y = "気温", colour = NULL)
1年のデータも重ねて表示する.
|> broom::augment() |> # この関数でも取り出せる
tw_lm2 ggplot(aes(x = solar, y = temp)) +
geom_point(data = tw_data, # 1年分のデータを使用
colour = alpha("grey", 0.5)) + # 薄い灰色で表示
geom_point(colour = "orange") +
geom_smooth(method = "lm", level = 0.95,
colour = "red", fill = "pink") +
labs(x = "日射量", y = "気温", colour = NULL)
1年のデータから限定して信頼区間を描いてもよい.
|>
tw_data ggplot(aes(x = solar, y = temp)) +
geom_point(aes(colour = factor(month))) +
geom_smooth(data = \(x)filter(x, month %in% 7:9),
method = "lm", level = 0.95,
colour = "red", fill = "pink") +
labs(x = "日射量", y = "気温", colour = NULL)
回帰モデルの係数の検定
問題
前問で作成した回帰モデルについて係数の検定を行いなさい.
解答例
前問で構成したモデルを用いる. 1年分のモデル tw_lm
を用いた場合の base R での操作は以下のようになる.
summary(tw_lm)
Call:
lm(formula = temp ~ solar, data = tw_data)
Residuals:
Min 1Q Median 3Q Max
-15.755 -7.149 0.513 7.468 14.345
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.19919 0.89429 12.523 < 2e-16 ***
solar 0.46433 0.05749 8.077 9.82e-15 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 7.707 on 364 degrees of freedom
Multiple R-squared: 0.152, Adjusted R-squared: 0.1497
F-statistic: 65.24 on 1 and 364 DF, p-value: 9.825e-15
情報が多いので,整理してみる
summary(tw_lm)$coef # 名前は識別できれば途中まででも可
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.1991911 0.89428702 12.523039 3.641899e-30
solar 0.4643281 0.05748562 8.077292 9.824715e-15
summary(tw_lm)$coef["solar",c("t value","Pr(>|t|)")]
t value Pr(>|t|)
8.077292e+00 9.824715e-15
summary(tw_lm)$coef[2,3:4] # 上と同じ
t value Pr(>|t|)
8.077292e+00 9.824715e-15
summary(tw_lm)$fstat # F統計量 (モデルの有意性の評価)
value numdf dendf
65.24265 1.00000 364.00000
anova(tw_lm)$'Pr(>F)'[1] # F統計量のp値 (summaryからは取り出し難い)
[1] 9.824715e-15
パイプを使う場合は以下のようにすればよい.
|> summary() |> _$coef tw_lm
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.1991911 0.89428702 12.523039 3.641899e-30
solar 0.4643281 0.05748562 8.077292 9.824715e-15
|> summary() |> _$coef["solar",c("t value","Pr(>|t|)")] tw_lm
t value Pr(>|t|)
8.077292e+00 9.824715e-15
|> summary() |> _$coef[2,3:4] tw_lm
t value Pr(>|t|)
8.077292e+00 9.824715e-15
tidyverse での操作は以下のようになる.
|> broom::tidy() # 係数の情報をまとめたデータフレーム tw_lm
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 11.2 0.894 12.5 3.64e-30
2 solar 0.464 0.0575 8.08 9.82e-15
|> broom::tidy() |> # solarの係数のt統計量とp値を抽出
tw_lm filter(term == "solar") |> select(statistic, p.value)
# A tibble: 1 × 2
statistic p.value
<dbl> <dbl>
1 8.08 9.82e-15
|> broom::tidy() |> _[2, c("statistic","p.value")] tw_lm
# A tibble: 1 × 2
statistic p.value
<dbl> <dbl>
1 8.08 9.82e-15
|> broom::tidy() |> _[2,4:5] tw_lm
# A tibble: 1 × 2
statistic p.value
<dbl> <dbl>
1 8.08 9.82e-15
|> broom::glance() # モデルの情報をまとめたデータフレーム tw_lm
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.152 0.150 7.71 65.2 9.82e-15 1 -1266. 2538. 2549.
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
|> broom::glance() |> # F統計量に関する情報
tw_lm select(statistic, p.value, df, df.residual)
# A tibble: 1 × 4
statistic p.value df df.residual
<dbl> <dbl> <dbl> <int>
1 65.2 9.82e-15 1 364
夏のモデル tw_lm2
の base R での操作は以下のようになる.
summary(tw_lm2)
Call:
lm(formula = formula(tw_lm), data = tw_data, subset = month %in%
7:9)
Residuals:
Min 1Q Median 3Q Max
-6.2489 -0.8316 0.3418 1.0467 4.1866
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 23.43954 0.51095 45.874 < 2e-16 ***
solar 0.28037 0.02872 9.761 8.95e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.732 on 90 degrees of freedom
Multiple R-squared: 0.5143, Adjusted R-squared: 0.5089
F-statistic: 95.28 on 1 and 90 DF, p-value: 8.951e-16
coef(summary(tw_lm2)) # 関数coefでも可
Estimate Std. Error t value Pr(>|t|)
(Intercept) 23.439541 0.51095263 45.874196 3.264630e-64
solar 0.280373 0.02872275 9.761356 8.950908e-16
coef(summary(tw_lm2))["solar",c("t value","Pr(>|t|)")]
t value Pr(>|t|)
9.761356e+00 8.950908e-16
coef(tw_lm2) # 推定された係数のみ取り出す場合
(Intercept) solar
23.439541 0.280373
coef(summary(tw_lm2))[,"Estimate"] # 上と同じ
(Intercept) solar
23.439541 0.280373
tidyverse での操作は以下のようになる.
|> broom::tidy() # 係数の情報 tw_lm2
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 23.4 0.511 45.9 3.26e-64
2 solar 0.280 0.0287 9.76 8.95e-16
|> broom::glance() # モデルの情報 tw_lm2
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.514 0.509 1.73 95.3 8.95e-16 1 -180. 366. 374.
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
決定係数による回帰モデルの検討
問題
前問で作成した回帰モデルについて 決定係数を確認しなさい. また,説明変数として降水量を用いた回帰モデルについて 検討しなさい.
解答例
前問で構成した1年分のモデル tw_lm
を用いる.
summary(tw_lm) # 全情報の表示
Call:
lm(formula = temp ~ solar, data = tw_data)
Residuals:
Min 1Q Median 3Q Max
-15.755 -7.149 0.513 7.468 14.345
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.19919 0.89429 12.523 < 2e-16 ***
solar 0.46433 0.05749 8.077 9.82e-15 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 7.707 on 364 degrees of freedom
Multiple R-squared: 0.152, Adjusted R-squared: 0.1497
F-statistic: 65.24 on 1 and 364 DF, p-value: 9.825e-15
summary(tw_lm)$r.squared
[1] 0.1519948
summary(tw_lm)$adj.r.squared
[1] 0.1496651
|> broom::glance() tw_lm
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.152 0.150 7.71 65.2 9.82e-15 1 -1266. 2538. 2549.
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
|> broom::glance() |> # 1:2列が決定係数
tw_lm select(r.squared, adj.r.squared)
# A tibble: 1 × 2
r.squared adj.r.squared
<dbl> <dbl>
1 0.152 0.150
夏のモデル tw_lm2
の場合は以下のようになる.
summary(tw_lm2) # 全情報の表示
Call:
lm(formula = formula(tw_lm), data = tw_data, subset = month %in%
7:9)
Residuals:
Min 1Q Median 3Q Max
-6.2489 -0.8316 0.3418 1.0467 4.1866
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 23.43954 0.51095 45.874 < 2e-16 ***
solar 0.28037 0.02872 9.761 8.95e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.732 on 90 degrees of freedom
Multiple R-squared: 0.5143, Adjusted R-squared: 0.5089
F-statistic: 95.28 on 1 and 90 DF, p-value: 8.951e-16
summary(tw_lm2)$r.squared
[1] 0.5142594
summary(tw_lm2)$adj.r.squared
[1] 0.5088623
|> broom::glance() tw_lm2
# A tibble: 1 × 12
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.514 0.509 1.73 95.3 8.95e-16 1 -180. 366. 374.
# ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
|> broom::glance() |>
tw_lm2 select(r.squared, adj.r.squared)
# A tibble: 1 × 2
r.squared adj.r.squared
<dbl> <dbl>
1 0.514 0.509
降水量と気温の関係を調べる.
<- lm(temp ~ rain, data = tw_data)
tw_lm3 <- lm(formula(tw_lm3), # 上の式を用いる
tw_lm4 data = tw_data,
subset = month %in% 7:9) # 夏(7-9月)のモデル
1年分のモデル tw_lm3
を調べる.
|> summary() tw_lm3
Call:
lm(formula = temp ~ rain, data = tw_data)
Residuals:
Min 1Q Median 3Q Max
-16.6101 -7.9009 0.1991 6.7916 14.9991
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 17.30090 0.46512 37.196 <2e-16 ***
rain 0.06598 0.03136 2.104 0.0361 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 8.319 on 364 degrees of freedom
Multiple R-squared: 0.01201, Adjusted R-squared: 0.009298
F-statistic: 4.426 on 1 and 364 DF, p-value: 0.03609
model.frame(tw_lm3) |> # 推定に用いたデータを利用
ggplot(aes(x = rain, y = temp)) +
geom_point(colour = "blue") +
geom_smooth(method = "lm",
colour = "red", fill = "pink") +
labs(x = "降水量", y = "気温")
1年分のモデル tw_lm3
に有意性はないことがわかる.
夏のモデル tw_lm4
を調べる.
|> summary() tw_lm4
Call:
lm(formula = formula(tw_lm3), data = tw_data, subset = month %in%
7:9)
Residuals:
Min 1Q Median 3Q Max
-7.7497 -0.8979 0.5539 1.7860 4.0860
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 28.21401 0.28153 100.218 <2e-16 ***
rain -0.01429 0.01491 -0.958 0.34
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 2.472 on 90 degrees of freedom
Multiple R-squared: 0.0101, Adjusted R-squared: -0.0008977
F-statistic: 0.9184 on 1 and 90 DF, p-value: 0.3405
model.frame(tw_lm4) |> # 推定に用いたデータを利用
ggplot(aes(x = rain, y = temp)) +
geom_point(colour = "orange") +
geom_smooth(method = "lm",
colour = "red", fill = "pink") +
labs(x = "降水量", y = "気温")
夏場は雨が降ると気温が下がる傾向が有意にあることが読み取れる. 決定係数が低いのはそもそも気温のばらつきが大きいことに起因すると考えられる.
補遺
ggplot2
を用いた線形回帰分析(単回帰)の例
#' パッケージの読み込み
#' 以下のほかに 'ggrepel' 'broom' 'magrittr' 'MASS' を利用
library(tidyverse)
library(ggfortify)
データの読み込み (“MASS::Animals”を用いる) を行う.
data(Animals, package = "MASS")
以下 Animals
で参照可能となる.
データの内容を確認する.
help(Animals, package = "MASS") # 内容の詳細を表示
print(Animals) # データの表示
body brain
Mountain beaver 1.350 8.1
Cow 465.000 423.0
Grey wolf 36.330 119.5
Goat 27.660 115.0
Guinea pig 1.040 5.5
Dipliodocus 11700.000 50.0
Asian elephant 2547.000 4603.0
Donkey 187.100 419.0
Horse 521.000 655.0
Potar monkey 10.000 115.0
Cat 3.300 25.6
Giraffe 529.000 680.0
Gorilla 207.000 406.0
Human 62.000 1320.0
African elephant 6654.000 5712.0
Triceratops 9400.000 70.0
Rhesus monkey 6.800 179.0
Kangaroo 35.000 56.0
Golden hamster 0.120 1.0
Mouse 0.023 0.4
Rabbit 2.500 12.1
Sheep 55.500 175.0
Jaguar 100.000 157.0
Chimpanzee 52.160 440.0
Rat 0.280 1.9
Brachiosaurus 87000.000 154.5
Mole 0.122 3.0
Pig 192.000 180.0
データのプロット (normal plot) を行う.
|>
Animals ggplot(aes(body, brain)) + # x軸,y軸に用いる列の指定
geom_point(colour = "royalblue") + # 点の追加
labs(title = "Brain and Body Weights (normal plot)",
x = "body [kg]", y = "brain [g]") # タイトルと軸名の追加
データのプロット (log plot) を行う.
|>
Animals ggplot(aes(body, brain)) +
geom_point(colour = "royalblue") +
scale_x_log10() + scale_y_log10() + # log-log plot を指定
labs(title = "Brain and Body Weights (log-log plot)",
x = "body [kg]", y="brain [g]")
データの分布から両対数変換が分析においては適切であることがわかる.
回帰分析 (単回帰) を行う.
<- lm(log(brain) ~ log(body), # 対数変換した変数で線形回帰
bb_lm data = Animals)
|> summary() # 分析結果のまとめを表示 bb_lm
Call:
lm(formula = log(brain) ~ log(body), data = Animals)
Residuals:
Min 1Q Median 3Q Max
-3.2890 -0.6763 0.3316 0.8646 2.5835
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.55490 0.41314 6.184 1.53e-06 ***
log(body) 0.49599 0.07817 6.345 1.02e-06 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.532 on 26 degrees of freedom
Multiple R-squared: 0.6076, Adjusted R-squared: 0.5925
F-statistic: 40.26 on 1 and 26 DF, p-value: 1.017e-06
信頼区間付きで回帰式を表示する.
|>
Animals rownames_to_column() |>
ggplot(aes(body, brain)) +
geom_point(colour = alpha("royalblue", 0.75)) +
::geom_text_repel(aes(label = rowname), # 各点の名前を追加
ggrepelsize = 3) +
geom_smooth(method = "lm", # 回帰式
colour = "dodgerblue",
fill = "dodgerblue") +
scale_x_log10() + scale_y_log10() + # log-log plot
labs(title = "Brain and Body Weights",
x = "body [kg]", y = "brain [g]")
信頼区間および予測区間付きで回帰式を表示する.
|>
Animals rownames_to_column() |>
mutate( # 予測区間の情報を追加する
::augment(bb_lm,
broominterval = "prediction", # 予測区間を指定
conf.level = 0.95) |> # 既定値なので省略可能
select(.fitted, .lower, .upper) |> exp() # 必要な列を選択して対数変換を戻す
|>
) ggplot(aes(body, brain)) +
geom_point(colour = "royalblue") +
::geom_text_repel(aes(label = rowname), # 各点の名前を追加
ggrepelsize = 3) + # 文字の大きさを調整
geom_smooth(method = "lm", # 回帰式
colour = "dodgerblue",
fill = "dodgerblue") +
geom_ribbon(aes(ymin = .lower, ymax = .upper), # 予測区間の描画
fill = alpha("dodgerblue", 0.2)) +
scale_x_log10() + scale_y_log10() + # log-log plot
labs(title = "Brain and Body Weights",
x = "body [kg]", y = "brain [g]")
予測区間の計算は関数 predict()
を用いてもよい.
mutate( # 予測区間の情報を追加する
predict(bb_lm,
newdata = Animals, # 対数変換のため指定しないと警告が出る
interval = "prediction") |>
exp() |> # 対数変換を戻す
as_tibble() # tibble形式でfit/lwr/upr列を追加
)
診断プロットを表示する.
autoplot(bb_lm,
colour = "royalblue",
smooth.colour = "gray50",
smooth.linetype = "dashed",
ad.colour = "blue",
label.size = 3, # 以下,外れ値ラベルに関する設定
label.n = 5,
label.colour = "red")
外れ値を除いた回帰分析を行う.
<- c(6,16,26) # 外れ値のindex (いずれも恐竜)
idx <- lm(log(brain) ~ log(body),
bb_lm data = Animals,
subset = -idx) # 外れ値を除く
|> summary() bb_lm
Call:
lm(formula = log(brain) ~ log(body), data = Animals, subset = -idx)
Residuals:
Min 1Q Median 3Q Max
-0.9125 -0.4752 -0.1557 0.1940 1.9303
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.15041 0.20060 10.72 2.03e-10 ***
log(body) 0.75226 0.04572 16.45 3.24e-14 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.7258 on 23 degrees of freedom
Multiple R-squared: 0.9217, Adjusted R-squared: 0.9183
F-statistic: 270.7 on 1 and 23 DF, p-value: 3.243e-14
信頼区間および予測区間付き回帰式を表示する.
|>
Animals rownames_to_column() |>
mutate(
::augment(bb_lm,
broomnewdata = Animals, # 外れ値を除いたので全データで計算
interval = "prediction") |>
select(.fitted, .lower, .upper) |> exp()) |>
ggplot(aes(body, brain)) +
geom_point(colour = "royalblue") +
::geom_text_repel(aes(label = rowname), # 各点の名前を追加
ggrepelsize = 3) + # 文字の大きさを調整
geom_smooth(data = \(x)slice(x, -idx), # 外れ値を除く
method = "lm", # 回帰式
colour = "dodgerblue",
fill = "dodgerblue") +
geom_ribbon(data = \(x)slice(x, -idx), # 外れ値を除く
aes(ymin = .lower, ymax = .upper), # 予測区間の描画
fill = alpha("dodgerblue", 0.2)) +
scale_x_log10() + scale_y_log10() + # log-log plot
labs(title = "Brain and Body Weights",
x = "body [kg]", y = "brain [g]")
恐竜の領域でも信頼・予測区間を描画するには,少し工夫が必要となる.
<- # 計算用のbody列を作成
bb_new_body tibble(body = Animals |> pull(body) |>
log() |> pretty(n=32) |> exp())
<- # 作成したbody列に対する区間の計算
bb_new_data tibble(bb_new_body,
::augment(bb_lm,
broomnewdata = bb_new_body,
interval = "confidence") |> # 信頼区間
select(.fitted, .lower, .upper) |> exp() |>
::set_colnames(c("brain","c.lower","c.upper")), # 列名の指定
magrittr::augment(bb_lm,
broomnewdata = bb_new_body,
interval = "prediction") |> # 予測区間
select(.lower, .upper) |> exp() |>
::set_colnames(c("p.lower","p.upper"))) # 列名の指定
magrittr|>
Animals rownames_to_column() |>
ggplot(aes(body, brain)) +
geom_point(colour = "royalblue") +
::geom_text_repel(aes(label = rowname),
ggrepelsize = 3) +
geom_line(data = bb_new_data, # 回帰式の描画
colour = "dodgerblue") +
geom_ribbon(data = bb_new_data,
aes(ymin = c.lower, ymax = c.upper), # 信頼区間の描画
fill = alpha("dodgerblue", 0.4)) +
geom_ribbon(data = bb_new_data,
aes(ymin = p.lower, ymax = p.upper), # 予測区間の描画
fill = alpha("dodgerblue", 0.2)) +
scale_x_log10() + scale_y_log10() +
labs(title = "Brain and Body Weights",
x = "body [kg]", y = "brain [g]")
診断プロットを表示する.
autoplot(bb_lm,
colour = "royalblue",
smooth.colour = "gray50",
smooth.linetype = "dashed",
ad.colour = "blue",
label.size = 3, # 以下,外れ値ラベルに関する設定
label.n = 5,
label.colour = "red")