--- title: "統計データ解析I" subtitle: "第8講 練習問題 解答例" date: "`r Sys.time()`" format: html: toc: true html-math-method: katex self-contained: true grid: margin-width: 350px execute: echo: true warning: false reference-location: margin citation-location: margin tbl-cap-location: margin fig-cap-location: margin editor: visual editor_options: chunk_output_type: console --- ## 準備 以下で利用する共通パッケージを読み込む. ```{r} library(conflicted) # 関数名の衝突を警告 conflicts_prefer( # 優先的に使う関数を指定 dplyr::filter(), dplyr::select(), dplyr::lag(), ) 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))} ``` ## 二項分布 ### 問題 二項分布に関して以下を考察せよ. - 平均と分散の理論計算を確認しなさい. - $X_{1},\dotsc,X_n$ を成功確率 $p$ の Bernoulli 分布に従う独立同分布な確率変数列とする. このとき $\sum_{i=1}^nX_i$ の分布は,試行回数 $n$ , 成功確率 $p$ の二項分布に従う.これをグラフに描画して確認しなさい. ### 解答例 試行を模擬する関数を定義する. ```{r} n <- 16 p <- 0.6 my_random <- function(){ # Bernolli分布をm個生成して合計 sum(rbinom(n, size=1, prob=p))} ``` 確率シミュレーションを行う. ```{r} mc <- 10000 # 実験回数を指定 my_data <- replicate(mc, my_random()) ``` 出現値ごとの度数分布表,および正規化した確率表を表示する. ```{r} my_data |> table() # base::table による頻度表の作成 my_data |> table() |> prop.table() # 確率値に変換 ``` `tibble`形式のデータフレームを作成するには関数 `dplyr::count()` を利用して例えば以下のようにすればよい. ```{r} my_data |> as_tibble_col() |> # ベクトルから1列のtibbleを作成.列名の既定値は value count(value) # value 列の頻度を集計する ``` 棒グラフを利用して頻度表を視覚化する. ```{r} my_data |> as_tibble_col() |> count(value) |> ggplot(aes(x = value, y = n)) + geom_bar(stat = "identity") # 最も単純な表示 ``` 理論値(確率)は関数 `dbinom()` で計算できるので,組み合わせて横並びに表示する. ```{r} my_data |> as_tibble_col() |> count(value) |> set_names(c("値","観測値")) |> # 列名を変更 mutate(観測値 = 観測値/sum(観測値), # 確率に変換 理論値 = dbinom(値, size = n, prob = p)) |> # 理論値を追加 pivot_longer(!値, values_to = "確率") |> ggplot(aes(x = 値, y = 確率, fill = name)) + geom_bar(stat = "identity", width = 0.8, # 並びがわかりやすいように幅を調整 position = "dodge") + labs(fill = NULL, # 凡例のfillの名称(name)を消去 title = paste0("二項分布(試行回数", n, ", 成功確率", p, ")")) ``` ::: callout-note 上記の例では `dplyr::count` を利用する場合を示したが, 視覚化のためのデータフレームはいろいろな方法で作成できる. `base::table()` および `balse::prop.table()` を利用する場合. ```{r} my_table <- my_data |> table() |> prop.table() tibble(値 = as.integer(names(my_table)), # 列名は文字列なので整数値に変換(as.numericでも良い) 観測値 = as.vector(my_table), # table型をvector型に変換(as.numericでも良い) 理論値 = dbinom(値, size = n, prob = p)) ``` `package::janitor` を利用する場合. ```{r} library(janitor) my_data |> as_tibble_col() |> tabyl(value) |> # 確率 set_names(c("値","頻度","観測値")) |> # 列名を変更 mutate(理論値 = dbinom(値, size = n, prob = p)) # 理論値を追加 ``` ::: ## Poisson 分布 ### 問題 Poisson 分布に関して以下を考察せよ. - 平均と分散の理論計算を確認しなさい. - $X,Y$ を独立な2つの確率変数とし,それぞれ強度 $\lambda_{1},\lambda_{2}$ の Poisson 分布に従うとする. このとき, 和 $X+Y$ の分布は強度 $\lambda_{1}+\lambda_{2}$ の Poisson 分布に従う. これをグラフに描画して確認しなさい. ### 解答例 試行を模擬する関数を定義する. ```{r} lambda1 <- 5 lambda2 <- 12 my_random <- function(){ # 2つの Poisson 分布の和 rpois(1, lambda=lambda1)+rpois(1, lambda=lambda2)} ``` 確率シミュレーションを行ない,視覚化する. ```{r} mc <- 10000 my_data <- replicate(mc, my_random()) my_data |> as_tibble_col() |> count(value) |> # 頻度を計算 set_names(c("値","観測値")) |> # 列名を変更 mutate(観測値 = 観測値/sum(観測値), # 確率に変換 理論値 = dpois(値, lambda=lambda1+lambda2)) |> # 理論値を追加 pivot_longer(!値, values_to = "確率") |> ggplot(aes(x = 値, y = 確率, fill = name)) + geom_bar(stat = "identity", width = 0.8, position = "dodge") + labs(fill = NULL, title = paste0("Poisson 分布(強度", lambda1+lambda2, ")")) ``` ## 正規分布 ### 問題 正規分布に関して以下を考察せよ. - $U_{1},U_{2}$ を $(0,1)$ 上の一様分布に従う独立な確率変数とする. このとき $$ \begin{align} X_{1}&=\sqrt{-2\log(U_{1})}\cos(2\pi U_{2}),\\ X_{2}&=\sqrt{-2\log(U_{1})}\sin(2\pi U_{2}) \end{align} $$ とおくと, $X_{1},X_{2}$ は独立かつともに標準正規分布に従う. これをグラフに描画して確認しなさい. ::: callout-note この変換を Box-Muller 変換と呼ぶ. ::: ### 解答例 試行を模擬する関数を作成する. ```{r} my_random <- function(){ # 一方の分布を確認する u1 <- runif(1) u2 <- runif(1) return(sqrt(-2*log(u1))*cos(2*pi*u2))} ``` 確率シミュレーションを行い,ヒストグラムを用いて視覚化する. ```{r} mc <- 10000 # 実験回数を指定 replicate(mc, my_random()) |> # 確率シミュレーション as_tibble_col() |> # 既定値では列名は value ggplot(aes(x = value)) + geom_histogram(bins = 30, # 既定値では頻度で表示される fill ="blue", colour = "white") ``` 理論値は関数 `stats::dnorm()` で計算できるので, 関数 `ggplot2::geom_funciton()` を用いて重ね描きする. ```{r} replicate(mc, my_random()) |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), # 確率で表示 bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dnorm, colour = "red") + labs(title = "標準正規分布") ``` Box-Muller法で作られる2つの確率変数の関係を調べてみる. それぞれを取り出せるように関数を作成する. ```{r} boxmuller <- function(){ u1 <- runif(1) u2 <- runif(1) x1 <- sqrt(-2*log(u1))*cos(2*pi*u2) x2 <- sqrt(-2*log(u1))*sin(2*pi*u2) return(c(x1,x2)) } ``` 2つの変数の散布図を描く. ```{r} x <- replicate(mc, boxmuller()) # 2行xmc列の行列が得られる tibble(x1 = x[1,], x2 = x[2,]) |> ggplot(aes(x = x1, y = x2)) + geom_point(colour = "royalblue") ``` `x1,x2` は同じ分布に従う独立な変数なので以下ではまとめて扱う. 個別に扱う場合は `x` を `x[1,]` などとすれば良い. ```{r} mu <- mean(x) sigma <- sd(x) tibble(x = as.vector(x)) |> ggplot(aes(x = x)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dnorm, args = list(mean = mu, sd = sigma), colour = "red") + labs(title = paste0("正規分布(平均", round(mu,2), # 2桁で四捨五入 ", 分散", round(sigma^2,2), ")")) ``` ::: callout-note 散布図を描くためのデータフレームは以下のようにして作ることもできる. 高次元の場合には関数を利用した方が簡単に記述できる. ```{r} x |> t() |> as_tibble(.name_repair = "minimal") |> set_names(paste0("x", 1:2)) |> ggplot(aes(x = x1, y = x2)) + geom_point(colour = "royalblue") ``` ::: ## $\chi^2$ 分布 ### 問題 $\chi^2$ 分布に関して以下を考察せよ. - 標準正規分布に従う $k$ 個の独立な確率変数の二乗和は自由度 $k$ の $\chi^2$ 分布に従うことを確認しなさい. ### 解答例 試行を模擬する関数を定義する. ```{r} k <- 8 # 自由度を設定 my_random <- function(){ sum(rnorm(k)^2)} # k個の標準正規乱数の二乗和 ``` 確率シミュレーションを行い,視覚化する. ```{r} mc <- 10000 # 実験回数を指定 my_data <- replicate(mc, my_random()) # 注で使うので保存しておく my_data |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dchisq, args = list(df = k), colour = "red") + labs(title = bquote(paste(chi^2,"分布 (自由度",.(k),")"))) ``` ::: callout-note 関数 bquote() は関数 expression() と同様な働きをするが,自由度の k を .(k) で評価して取り込むことができる. 以下と表示を比較してみよう. ```{r} my_data |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dchisq, args = list(df = k), colour = "red") + labs(title = expression(paste(chi^2,"分布 (自由度",k,")"))) # この行だけ違う ``` ::: ## $t$ 分布 ### 問題 $t$ 分布に関して以下を考察せよ. - $Z$ を標準正規分布に従う確率変数,$Y$ を自由度 $k$ の $\chi^2$ 分布に従う確率変数とし,$Z,Y$ は独立であるとする. このとき確率変数 $$ \begin{equation} \frac{Z}{\sqrt{Y/k}} \end{equation} $$ は自由度 $k$ の $t$ 分布に従うことを確認しなさい. ### 解答例 試行を模擬する関数を作成する. ```{r} k <- 8 # 自由度を設定 my_random <- function(){ sum(rnorm(k)^2)} # k個の標準正規乱数の二乗和 ``` 確率シミュレーションを行い,視覚化する. ```{r} mc <- 10000 # 実験回数を指定 my_data <- replicate(mc, my_random()) # 注のところでもう一度描くので保存しておく my_data |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dchisq, args = list(df = k), colour = "red") + labs(title = bquote(paste(chi^2,"分布 (自由度",.(k),")"))) ``` ::: callout-note 関数 bquote() は関数 expression() と同様な働きをするが, 自由度の k を .(k) で評価して取り込むことができる. 以下と比較してみよう. ```{r} my_data |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = dchisq, args = list(df = k), colour = "red") + labs(title = expression(paste(chi^2,"分布 (自由度",k,")"))) ``` ::: ## $F$ 分布 ### 問題 $F$ 分布に関して以下を考察せよ. - $Y_{1},Y_{2}$ をそれぞれ自由度 $k_{1},k_{2}$ の $\chi^2$ 分布に従う独立な確率変数とする. このとき, 確率変数 $$ \begin{equation} \frac{Y_{1}/k_{1}}{Y_{2}/k_{2}} \end{equation} $$ は自由度 $k_{1},k_{2}$ の $F$ 分布に従うことを確認しなさい. ### 解答例 試行を模擬する関数を作成する. ```{r} k1 <- 20 k2 <- 10 my_random <- function(){ y1 <- rchisq(1, df=k1) # 自由度20のカイ二乗分布 y2 <- rchisq(1, df=k2) # 自由度10のカイ二乗分布 ## y1 <- sum(rnorm(k1)^2) # 正規乱数を用いてもよい ## y2 <- sum(rnorm(k2)^2) return((y1/k1)/(y2/k2))} ``` 確率シミューレションを行い,視覚化する. ```{r} mc <- 10000 # 実験回数を指定 replicate(mc, my_random()) |> as_tibble_col() |> ggplot(aes(x = value)) + geom_histogram(aes(y = after_stat(density)), bins = 30, fill ="lightblue", colour = "white") + geom_function(fun = df, args = list(df1 = k1, df2 = k2), colour = "red") + labs(title = bquote(paste(frac(Y[1]/k[1],Y[2]/k[2]), " (",k[1]==.(k1), ", ",k[2]==.(k2),")"))) ``` ::: callout-note グラフの一部に着目したい場合は xlim/ylim で表示を調整することができる. ```{r} last_plot() + # 直前のプロット xlim(0,6) + ylim(0,0.9) # 表示領域を指定する(表示しない部分について警告が出る) ``` :::