統計解析フリーソフト R 入門 R によるシミュレーション入門 R Commander 国際化! R Commander 国際化! GUI メニューから R の機能を使うことが 出来るパッケージ R Commander のセットアップが楽になりました パッケージをインストールするだけで メニューが日本語化! CRAN からの「Rcmdr」と「rgl」の2つの パッケージをインストールするだけ! R Commander の詳しい使い方は荒木先生 の本をご参照下さい 第5回のメニュー R の乱数生成関数 乱数生成関数の一覧 乱数生成の例 乱数データを使った検定の例 繰り返し文(for)と条件分岐(if) 繰り返し文(for) 条件分岐(if) R によるシミュレーション 本日の話の流れ 例数設計を題材とし,SAS と対比をさせなが ら,R によるシミュレーション方法を紹介 2群の平均値の差を検出することを考える 第1群の標本:平均 0,標準偏差1.5の正規分布 第2群の標本:平均 1,標準偏差1.5の正規分布 解析は2標本 t 検定(α = 0.05) 検出力90%を確保するために必要な症例数を算出 する まずは乱数の生成方法を紹介 次にシミュレーションの方法を紹介 第5回のメニュー R の乱数生成関数 乱数生成関数の一覧 乱数生成の例 乱数データを使った検定の例 繰り返し文(for)と条件分岐(if) 繰り返し文(for) 条件分岐(if) R によるシミュレーション R の乱数生成関数 R には多数の乱数生成関数が用意されている SAS の rand() 関数に匹敵する位の種類 SAS と同様,seed を指定することが出来る SAS の rand() 関数と同じ乱数生成アルゴリズム を搭載(メルセンヌ・ツイスター法) R の乱数生成関数 乱数生成速度が速い メルセンヌ・ツイスター法で生成 結果をベクトル(1次元)として持つ 基本的な乱数生成関数 runif(10) :(0,1)区間の一様乱数を10個生成 rnorm(20) :標準正規乱数を20個生成 rexp(30, 5):rate 5(平均1/5)の指数乱数を 30個生成 SASのrand()で生成可能な乱数の分布 分布名 rand()の第1引数 V8.2以前の既存の関数 Rの関数 ベルヌーイ分布 Bernoulli (rbinom()で生成可) ベータ分布 Beta rbeta() 二項分布 Binomial ranbin() rbinom() コーシー分布 Cauchy rancau() rcauchy() χ2分布 Chisquare アーラン分布 Erlang 指数分布 Exponential F分布 F ガンマ分布 Gamma 幾何分布 Geometric rgeom() 超幾何分布 Hypergeometric rhyper() 対数正規分布 Lognormal rlnorm() 負の二項分布 Negbinomial rnbinom() 正規分布 Normal rannor(), normal() rnorm() ポアソン分布 Poisson ranpoi() rpois() t分布 T テーブル(多項)分布 Table rantbl() 三角分布 Triangle rantri() 一様分布 Uniform ranuni(), uniform() ワイブル分布 Weibull rchisq() ranexp() rexp() rf() rangam() rgamma() rt() rmultinom() runif() rweibull() 【例1】2組の正規乱数を生成 2群(各群50例)の正規乱数を1組生成 SAS による乱数生成 data dummy1; array mu(2) mu1-mu2; mu1 = 0.0 ; mu2 = 1.0 ; sd = 1.5 ; n = 50 ; do group=1 to 2; do j=1 to n ; y=normal(7)*sd+mu(group); output; end; end; run; R による乱数生成 > > > > > > > > # 乱数のシード(初期値)を設定 set.seed(7) # 平均0,標準偏差1.5の正規乱数 y1 <- rnorm(n=50, m=0.0, sd=1.5) # 平均1,標準偏差1.5の正規乱数 y2 <- rnorm(n=50, m=1.0, sd=1.5) SASのデータセット mu1 mu2 sd n group j y 0 1 1.5 50 1 1 0.59195 0 1 1.5 50 1 2 0.40391 0 1 1.5 50 1 3 0.41213 0 1 1.5 50 1 4 -0.17594 ・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・ 0 1 1.5 50 1 49 -0.04794 0 1 1.5 50 1 50 0.70376 0 1 1.5 50 2 1 1.95777 0 1 1.5 50 2 2 3.04958 0 1 1.5 50 2 3 1.54307 0 1 1.5 50 2 4 -0.23373 ・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・ 0 1 1.5 50 2 49 1.74497 0 1 1.5 50 2 50 0.69841 R のデータ(ベクトル) > y1 [1] [6] [11] [16] [21] [26] [31] [36] [41] [46] 3.430870742 -1.420919918 0.535479345 0.701520767 1.259625539 0.276289157 -1.306276534 -0.843188814 1.827825802 -0.602289920 > y2 [1] [6] [11] [16] [21] [26] [31] [36] [41] [46] 0.60588648 1.72155407 1.11455721 2.66387468 1.64894074 -0.98875887 1.51387803 0.53244720 3.45369165 0.13953139 -1.795157523 1.122209010 4.075127675 -1.340701085 1.058012746 1.128419844 1.078065830 1.496270167 -1.048975618 2.025776371 0.98849784 -1.35180237 1.23873292 2.15373129 -0.38390258 -0.33355509 1.00637235 0.48089711 0.03186479 2.67698981 -1.041438766 -0.175432839 3.422177889 -0.460992449 1.958947081 0.887617579 0.165979317 -1.657695088 -0.428149127 0.886785041 -0.618439427 0.228986439 0.486030810 -0.007233633 -2.081994325 -1.474578894 -0.117700152 -0.213431746 -1.967329009 0.150788183 -1.456010012 3.284967161 2.844100600 1.482246224 1.909375296 -0.414095933 -0.630735689 0.472492357 -0.586518647 1.396607993 1.55072951 3.56074382 2.08561039 1.47737543 1.24898718 -0.34986144 1.81551128 2.05721103 1.47845371 2.73021051 2.89102525 2.05093526 0.07662369 -0.29998953 -1.45927563 0.16359650 0.90639654 4.63403947 1.04382976 0.40986486 -0.18905684 0.54308862 -1.67884023 1.88091201 1.92848825 1.35459040 2.26975135 -1.31000170 0.34281415 0.77399054 SASに比べて R は・・・ 乱数を生成するのが楽 乱数を生成するプログラムが簡単 生成速度が速い(メルセンヌ・ツイスター法) 自宅のマシン(Pen4:2.6GHz,512MB RAM)で乱数を10万個生成 【SAS】0.15秒∼0.17秒 【 R 】0.03秒∼0.05秒 SAS と同様,seed を指定することができる 生成されたデータに冗長性が無い SAS はデータセット(余分な情報が・・・) R はベクトル 【例2】2標本 t 検定 SAS による2標本 t 検定 ods listing close ; ods output ttests=out1 (where=(method="Pooled")) ; proc ttest data=dummy1 ; class group ; var y ; run ; ods output close ; ods listing ; R による2標本 t 検定 > out1 <- t.test(y1, y2, var.equal=T) > out1 Two Sample t-test data: y1 and y2 t = -2.845, df = 98, p-value = 0.005408 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -1.4219012 -0.2533483 sample estimates: mean of x mean of y -0.005048812 0.832575895 【例2】2標本 t 検定 SAS のアウトプット Variable y Method Pooled Variances tValue DF Equal -2.20599 Probt 98 0.029721 R のアウトプット > names(out1) [1] "statistic" [6] "null.value" > out1$p.value [1] 0.005408422 "parameter" "p.value" "alternative" "method" # p 値 "conf.int" "data.name" "estimate" 【参考】回帰分析 R でやると面倒な例 SAS による回帰分析 R による回帰分析 ods listing close ; > dummy1 <- data.frame( group=c(rep(1,50), ods output ModelANOVA=out2 (where=(HypothesisType=3)); rep(2,50)), y=c(y1,y2) ) proc glm data=dummy1 ; > out2 <- summary( class group ; lm(y group, data=dummy1) ) model y = group ; quit ; ods output close ; ods listing ; 【参考】回帰分析 SAS のアウトプット Dependent HypothesisType Source DF y 3 group SS MS 1 10.3007 10.3007 FValue ProbF 4.8663 0.0297 R のアウトプット > out2$coefficients[ ,"Pr(>│t│)"] (Intercept) group 0.073337026 0.005408422 # 命令は names(out2) で調べる > out2$coefficients[2,"Pr(>│t│)"] [1] 0.005408422 # p 値 第5回のメニュー R の乱数生成関数 乱数生成関数の一覧 乱数生成の例 乱数データを使った検定の例 繰り返し文(for)と条件分岐(if) 繰り返し文(for) 条件分岐(if) R によるシミュレーション 【SAS】検出力のシミュレーション 2群(各群50例)の正規乱数を1000組生成し, 各組で t 検定を行い,p 値を取り出す data dummy2; array mu(2) mu1-mu2; mu1 = 0.0 ; mu2 = 1.0 ; do i=1 to 1000 ; do group=1 to 2; do j=1 to 50 ; y=normal(7)*1.5+mu(group) ; output; end; end; end; run; proc ttest data=dummy2 ; by i ; class group ; var y ; run ; ods output close ; ods listing ; data power2; set out2; if ( Probt < 0.05 ) then flag = 1; else flag = 0; run; ods listing close ; ods output proc freq data=power2; ttests=out2(where=(method="Pooled")) ; tables flag / norow nopercent ; run; 【R】シミュレーションの準備(1) for:同じような作業を繰り返す for (i in 1:1000) { 1000 回繰り返す内容 } > power <- 0 > for (i in 1:1000) { + power <- power + 1 + } > power [1] 1000 # カウンタ power を初期化( 0 を代入) # 同じような作業を 1000 回繰り返す # カウンタ power を 1 増やす # カウンタの中身 【R】シミュレーションの準備(2) if:条件に合致していたら処理を行う if (条件) { 条件に合致していたら処理を行う } > power <- 0 # > for (i in 1:1000) { # + if (i%%2 == 0) { # + power <- power + 1 # + } + } > power # [1] 500 カウンタ power を初期化( 0 を代入) 同じような作業を 1000 回繰り返す i が 2 の倍数だったら・・・ カウンタ power を 1 増やす カウンタの中身 【R】検出力のシミュレーション 2群(各群50例)の正規乱数を1000組生成し, 各組で t 検定を行い,p 値を取り出す > > > + + + + + + + > 乱数のシードを設定 カウンタ <- 0 for (i in 1:1000) { y1 <- 平均 0 ,標準偏差 1.5 の正規乱数を 50 個生成 y2 <- 平均 1 ,標準偏差 1.5 の正規乱数を 50 個生成 out <- y1 と y2 の 2 標本 t 検定(等分散性を仮定) if (結果 out の p 値が 0.05 より小さければ) { カウンタを 1 増やす } } power/1000 で有意になった割合を算出 【R】検出力のシミュレーション 2群(各群50例)の正規乱数を1000組生成し, 各組で t 検定を行い,p 値を取り出す > > > + + + + + + + > set.seed(7) power <- 0 for (i in 1:1000) { y1 <- rnorm(n=50, mean=0.0, sd=1.5) y2 <- rnorm(n=50, mean=1.0, sd=1.5) out <- t.test(y1, y2, var.equal=T) if (out$p.value < 0.05) { power <- power + 1 } } power/1000 検出力のシミュレーション結果 SAS のアウトプット(実行時間:約18秒) FREQ プロシジャ 累積 flag 度数 度数 ---------------------------0 75 75 1 925 1000 R のアウトプット(実行時間:約1~2秒) > power/1000 [1] 0.902 繰り返し文(do ⇔ for) SAS R > set.seed(7) data dummy2; > power <- 0 array mu(2) mu1-mu2; > for (i in 1:1000) { mu1 = 0.0 ; mu2 = 1.0 ; + y1 <- rnorm(n=50, mean=0.0, sd=1.5) do i=1 to 1000 ; + y2 <- rnorm(n=50, mean=1.0, sd=1.5) do group=1 to 2; + out <- t.test(y1, y2, var.equal=T) do j=1 to 50 ; y=normal(7)*1.5+mu(group); + if (out$p.value < 0.05) { + power <- power + 1 output; + } end; + } end; > power/1000 end; run; 1. do が for になっている 2. セミコロンは要らない 3. do~end ではなく { と } で 括る 条件分岐(if) SAS R data power2; set out2; if (Probt<0.05) then flag=1; else flag=0; run; > > > + + + + + + + > set.seed(7) power <- 0 for (i in 1:1000) { y1 <- rnorm(n=50, mean=0.0, sd=1.5) y2 <- rnorm(n=50, mean=1.0, sd=1.5) out <- t.test(y1, y2, var.equal=T) if (out$p.value < 0.05) { power <- power + 1 } } power/1000 1. then は要らない 2. セミコロンは要らない 3. do~end ではなく { と } で 括る 【R】検出力のシミュレーション 2群(各群50例)の正規乱数を1000組生成し, 各組で t 検定を行い,p 値を取り出す > > > + + + + + + + > set.seed(7) power <- 0 for (i in 1:1000) { y1 <- rnorm(n=50, mean=0.0, sd=1.5) y2 <- rnorm(n=50, mean=1.0, sd=1.5) out <- t.test(y1, y2, var.equal=T) if (out$p.value < 0.05) { power <- power + 1 } } power/1000 # # # # # # # カウンタ power を 0 に 繰り返し文開始 第 1 群のデータを生成 第 2 群のデータを生成 t 検定 → 結果を out に格納 結果が有意ならば カウンタに 1 加算 # 結果の表示 第5回のメニュー R の乱数生成関数 乱数生成関数の一覧 乱数生成の例 乱数データを使った検定の例 繰り返し文(for)と条件分岐(if) 繰り返し文(for) 条件分岐(if) R によるシミュレーション R によるシミュレーション 【応用1】先程のプログラムを関数化する > f <- function(n) { + set.seed(7) + power <- 0 + for (i in 1:1000) { + y1 <- rnorm(n, mean=0.0, sd=1.5) + y2 <- rnorm(n, mean=1.0, sd=1.5) + out <- t.test(y1, y2, var.equal=T) + if (out$p.value < 0.05) { + power <- power + 1 + } + } + power/10 # パーセント表示する + } > f(30) # n=30 のときの検出力 [1] 73.4 R によるシミュレーション 【応用2】検出力の値をプロットする 85 86 87 88 y 89 90 91 92 > y <- c(f(40), f(41), f(42), f(43), f(44), f(45), f(46), f(47), f(48), f(49), f(50), f(51)) > plot(40:51, y, type="b", col=ifelse(y>=90, "red", "blue")) > abline(h=90) 40 42 44 46 40:51 48 50 R でシミュレーションを行う利点 計算が速い 繰り返し回数が多くてもフリーズしにくい 記述が簡単(Rに慣れれば・・・) SASのデータステップは,記述は簡単だが繰り返し 回数に制約がある(高々数千回) SASの IML は,繰り返し回数の制約が緩いが, 記述が難解 (可読性に難,統計量を逐一求める必要あり) 今回は t 検定を例に出したが,同様の方法でさ まざまな検定,分析を主解析とした場合の例数 設計が出来る 参考 SASに power プロシジャや glmpower プロシジャが あるように,R にも以下の関数が用意されている power.t.test():t 検定の例数設計を行う power.anova.test():一元配置分散分析の例数 設計を行う power.prop.test():比率の検定の例数設計を行う > power.t.test(n=50, delta=1, sd = 1.5, sig=0.05) Two-sample t test power calculation n = 50 delta = 1 sd = 1.5 sig.level = 0.05 power = 0.9099633 alternative = two.sided NOTE: n is number in *each* group 本日のまとめ R の乱数生成関数 乱数生成関数の一覧 乱数生成の例 乱数データを使った検定の例 繰り返し文(for)と条件分岐(if) 繰り返し文(for) 条件分岐(if) R によるシミュレーション 参考文献・引用文献 SAS Technical News Winter 2005 ⇒「rand関数で生成可能な乱数の分布」で引用 伏見 正則 「乱数」 東京大学出版会 脇本 和昌 「乱数の知識」 http://www.sci.kagoshima-u.ac.jp/ ebsa/wakimoto01/index.html 良い乱数・悪い乱数 http://www001.upp.so-net.ne.jp/isaku/rand.html 間瀬 他「工学のためのデータサイエンス入門」 (数理工学社) 統計解析フリーソフト R 入門 終
© Copyright 2024 Paperzz