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
第11講 練習問題 解答例
準備
以下で利用する共通パッケージを読み込む.
t 検定の確率シミュレーション
問題
適当な正規乱数を用いて確率シミュレーションを考案し,t 検定の過誤について調べなさい.
例えば適当な数値を指定して以下のような実験を行えばよい.
<- function(n){
mc_trial <- t.test(rnorm(n,mean = mu0,sd = sd0), mu = mu0)
result return(result$p.value)}
<- replicate(mc, mc_trial(n))
mc_data table(mc_data < alpha)/mc # alpha以下のデータの数(比率)を調べる
上記はp値の性質を調べる場合であるが,t統計量についても同様に調べることができる.
解答例
検定統計量の分布を調べるための実験の設定を行う.
<- 10
n <- 5
mu0 <- 3
sd0 <- 10000
mc <- 0.05
alpha <- function(n, pval = TRUE){
mc_trial <- t.test(rnorm(n, mean = mu0, sd = sd0), mu = mu0)
result if(pval) {
return(result$p.value) # p値を取り出す
else {
} return(result$statistic) # 検定統計量を取り出す
} }
検定統計量の分布を視覚化する.
<- replicate(mc, mc_trial(n, pval = FALSE)) |> as_tibble_col()
mc_data |>
mc_data ggplot(aes(x = value)) +
geom_histogram(aes(y = after_stat(density)), # 密度表示
bins = 40,
fill = "lightgreen",
colour = "seagreen") +
geom_function(fun = dnorm, # 正規分布
colour = "red",
linewidth = 1.2) +
geom_function(fun = dt, # 自由度n-1のt分布
args = list(df = n-1),
colour = "blue",
linewidth = 1.2) +
labs(x = "t統計量", title = "検定統計量の分布")
自由度 n-1 の t 分布が良く当て嵌まることが確認できる.
p 値の分布を見るには以下のようにすればよい.
<- replicate(mc, mc_trial(n)) |> as_tibble_col()
mc_data |>
mc_data ggplot(aes(x = value)) +
geom_histogram(bins = 20,
fill = "plum",
colour = "orchid") +
labs(x = "p値", title = "p値の分布")
|>
mc_data count(value < alpha) |>
mutate(prob = n/sum(n)) # alpha以下の結果の数を調べる = サイズ
# A tibble: 2 × 3
`value < alpha` n prob
<lgl> <int> <dbl>
1 FALSE 9504 0.950
2 TRUE 496 0.0496
p 値は一様に分布し,有意水準と第一種の過誤の関係が確認できる.
一方,帰無仮説が成り立たない場合の p 値の分布は例えば以下のようになる.
<- function(n){
mc_trial <- t.test(rnorm(n, mean = mu0+1, sd = sd0), mu = mu0)
result return(result$p.value)} # p値を取り出す
replicate(mc, mc_trial(n)) |>
as_tibble_col() |>
ggplot(aes(x = value)) +
geom_histogram(fill = "khaki",
colour = "tan") +
labs(x = "p値", title = "帰無仮説が成り立たない場合")
p 値は一様に分布しなくなることが確認できる.
たとえば以下のようにすると関数 t.test() で計算される量をまとめて取り出すことができる. まとめて計算できるが,計算が若干重い.
<- function(n){
mc_trial t.test(rnorm(n, mean = mu0, sd = sd0), mu = mu0) |>
::tidy() |> # tidyverse のパッケージ.様々なオブジェクトを tibble 形式に変換
broomselect(where(is.numeric)) |> # 数値のみ取り出す
unlist() # 名前付の数値ベクトルに変換
}<- 2000
mc replicate(mc, mc_trial(n)) |> t() |> as_tibble() |>
pivot_longer(c(statistic.t, p.value)) |>
ggplot(aes(x = value, fill = name)) +
geom_histogram(show.legend = FALSE) +
facet_wrap(vars(name), ncol = 2, scales = "free") # 横に並べる
視聴率の検定
問題
ある番組の視聴率が2桁に達したかどうか知るために,n人にその番組を観たかどうか確認する. 確率変数 \begin{equation} X_{i}= \begin{cases} 1,&\text{番組を観た}\\ 0,&\text{番組を観ていない} \end{cases},\; i=1,2,\dotsc,n \end{equation} を定義して,これを用いた検定を考えてみよ.
X の生成は例えば mu1
を真の視聴率として以下のようにすればよい
<- sample(0:1, n, replace = TRUE, prob = c(1-mu1,mu1)) x
n人分の視聴結果 {1,0} のベクトルが得られる.
X は正規分布には従わないが, n が大きければ標本平均 \bar{X} は正規分布で十分良く近似できることを利用して良い.
解答例
X は正規分布ではないが,n が十分大きい場合には 区間推定と同様に正規分布(自由度の大きな t 分布)で近似される.
<- 600
n <- 0.1 # 越えたい視聴率
mu0 <- 0.11 # 真の視聴率(11%)
mu1 <- sample(0:1, n, replace = TRUE, prob = c(1-mu1,mu1))
x table(x)
x
0 1
530 70
t.test(x,mu = mu0, alternative = "greater")
One Sample t-test
data: x
t = 1.2707, df = 599, p-value = 0.1022
alternative hypothesis: true mean is greater than 0.1
95 percent confidence interval:
0.09505831 Inf
sample estimates:
mean of x
0.1166667
上記の設定で確率シミュレーションを行う.
<- 10000
mc <- 0.05 # 自由に設定せよ
alpha <- function(n){
mc_trial <- sample(0:1, n, replace = TRUE, prob = c(1-mu1,mu1))
x <- t.test(x, mu = mu0, alternative = "greater")
result return(result$p.value)}
<- replicate(mc, mc_trial(n)) |> as_tibble_col()
mc_data |>
mc_data ggplot(aes(x = value)) +
geom_histogram(bins = 20,
fill = "plum",
colour = "orchid") +
labs(x = "p値", title = paste0("p値の分布 (n=",n,")"))
table(mc_data < alpha)/mc # alpha以下のデータの数を調べる=検出力
FALSE TRUE
0.8418 0.1582
n を変えて実験してみる.
<- 5000
n <- replicate(mc, mc_trial(n)) |> as_tibble_col()
mc_data |>
mc_data ggplot(aes(x = value)) +
geom_histogram(bins = 20,
fill = "plum",
colour = "orchid") +
labs(x = "p値", title = paste0("p値の分布 (n=",n,")"))
table(mc_data < alpha)/mc # alpha以下のデータの数を調べる=検出力
FALSE TRUE
0.2621 0.7379
気温の分散の検定
問題
東京の気象データの気温の項目を用いて, 6月の気温の分散が, 月毎に計算した気温の分散の平均値より大きいかどうか検定せよ.
#' データの読み込みを行う
<- read_csv("data/tokyo_weather.csv")
tw_data #' 月毎の気温の分散は以下で計算できる
|> group_by(month) |> summarize(var(temp))
tw_data #' この平均値は以下のように計算される
|> group_by(month) |>
tw_data summarize(var(temp)) |> pull(`var(temp)`) |> mean()
解答例
データの読み込みを行う.
<- read_csv("data/tokyo_weather.csv") |>
tw_data mutate(month = as_factor(month)) # 月毎の表示のために因子化しておく
月毎の分布を確認する.
|>
tw_data ggplot(aes(x = month, y = temp)) +
geom_boxplot(fill = "lightblue", colour = "blue") +
labs(x = "月", y = "気温", title = "東京の気温の分布")
月毎の分散を計算する.
|> group_by(month) |> summarize(var = var(temp)) |>
tw_data ggplot(aes(x = month, y = var)) +
geom_bar(stat = "identity", fill = "royalblue") +
labs(x = "月", y = "気温の分散", title = "東京の気温のばらつき")
関数 summarize()
は列名を指定しなければ計算内容に``を付けて列名とする.これは “()” が特殊な文字(関数の引数を表す)のためである.
|> group_by(month) |> summarize(var(temp)) |>
tw_data ggplot(aes(x = month,
y = `var(temp)`)) +
geom_bar(stat = "identity", fill = "skyblue") +
labs(x = "月", y = "気温の分散", title = "東京の気温のばらつき")
検定統計量の計算を行う.
<- tw_data |> group_by(month) |>
v0 summarize(var = var(temp)) |>
pull(var) |> mean() # 12ヶ月分の分散の単純な平均
<- tw_data |> filter(month == 6) |> pull(temp) # 6月の気温のベクトル
x <- length(x)) # データ数 (n
[1] 30
<- (n-1)*var(x)/v0) # 検定統計量 (chi2
[1] 25.55135
<- pchisq(chi2, df = n-1)
p0 <- 2*min(p0,1-p0)) (p
[1] 0.7012997
分散が小さな8月を検定してみる.
<- tw_data |> filter(month == 8) |> pull(temp) # 8月の気温のベクトル
x <- length(x)) # データ数 (n
[1] 31
<- (n-1)*var(x)/v0) # 検定統計量 (chi2
[1] 7.409891
<- pchisq(chi2, df = n-1)
p0 <- 2*min(p0,1-p0)) (p
[1] 1.657503e-05
平均の差の検定
問題
東京の気象データの気温の項目を用いて, 7月と8月の気温の平均が同じかどうか検定しなさい.
他の項目や自身の集めたデータでも試してみよ.
解答例
7月と8月の平均気温を比較する.
|>
tw_data filter(month %in% c(7,8)) |> # 月を限定
ggplot(aes(x = month, y = temp)) +
geom_boxplot(fill = "pink") +
geom_jitter(colour = "red", width = 0.2) + # データを重ねて表示
labs(x = "月", y = "気温", title = "気温の比較")
ばらつき方は大きく異なるが平均気温はばらつきの範囲内の違いのように見える.
7月と8月の平均気温の差を検定する.
<- tw_data |> filter(month == 7) |> pull(temp)
x <- tw_data |> filter(month == 8) |> pull(temp)
y t.test(x,y)
Welch Two Sample t-test
data: x and y
t = -0.71795, df = 49.355, p-value = 0.4762
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-1.2743483 0.6033806
sample estimates:
mean of x mean of y
28.69032 29.02581
1月と12月でも試してみる.
|>
tw_data filter(month %in% c(1,12)) |>
ggplot(aes(x = month, y = temp)) +
geom_boxplot(fill = "lightblue") + # 色を変える
geom_jitter(colour = "blue", width = 0.2) +
labs(x = "月", y = "気温", title = "気温の比較")
平均気温の差はばらつきと同程度のように見える.
<- tw_data |> filter(month == 1) |> pull(temp)
x <- tw_data |> filter(month == 12) |> pull(temp)
y t.test(x,y)
Welch Two Sample t-test
data: x and y
t = -2.0307, df = 58.897, p-value = 0.04681
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-1.97259032 -0.01450646
sample estimates:
mean of x mean of y
7.106452 8.100000
分布を視覚的に捉えるためには 関数 geom_jitter()
以外にもさまざまなパッケージが利用できる. 例えば以下のようなものがある.
library(see)
|>
tw_data filter(month %in% 6:9) |>
ggplot(aes(x = month, y = temp, fill = month)) +
geom_violindot(fill_dots = "grey") +
labs(x = "月", y = "気温", title = "気温の比較")
分散の比の検定
問題
東京の気象データの気温の項目を用いて, 4月と9月の気温の分散が同じかどうか検定しなさい.
他の項目や自身の集めたデータでも試してみよ.
解答例
4月と9月の気温の分散を比較する.
|>
tw_data filter(month %in% c(4,9)) |>
ggplot(aes(x = month, y = temp)) +
geom_boxplot(fill = "lightgreen") + # 色を変える
geom_jitter(colour = "seagreen", width = 0.2) +
labs(x = "月", y = "気温", title = "気温の比較")
平均気温は大きく異なるがばらつきは同等のように見える.
<- tw_data |> filter(month == 4) |> pull(temp)
x <- tw_data |> filter(month == 9) |> pull(temp)
y var.test(x,y)
F test to compare two variances
data: x and y
F = 0.97488, num df = 29, denom df = 29, p-value = 0.9459
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.4640089 2.0482206
sample estimates:
ratio of variances
0.9748809
1月と2月でも試してみる.
|>
tw_data filter(month %in% c(1,2)) |>
ggplot(aes(x = month, y = temp)) +
geom_boxplot(fill = "lightgreen") + # 色を変える
geom_jitter(colour = "seagreen", width = 0.2) +
labs(x = "月", y = "気温", title = "気温の比較")
平均気温は似通っているがばらつきは異なるように見える.
<- tw_data |> filter(month == 1) |> pull(temp)
x <- tw_data |> filter(month == 2) |> pull(temp)
y var.test(x,y)
F test to compare two variances
data: x and y
F = 0.23395, num df = 30, denom df = 28, p-value = 0.0001723
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.1107671 0.4894081
sample estimates:
ratio of variances
0.2339499