まず set.seed() から
実行のたびに変わるランダムな抽出は、教育にも採点にもデバッグにも科学にも役立ちません。シミュレーションが今日は 0.146、明日は 0.153 と言うなら、レポートにはどちらの数値を載せるのでしょうか。set.seed() は生成器の開始点を固定し、それに続く「ランダムさ」の流れ全体を正確に再現可能にします。
同じシードなら、どのマシンでも、毎回、同一の抽出になります。これらの数値は 擬似 乱数です。あらゆる乱数性の統計的検定に通るよう設計された決定論的な列であり、シードはその列のどこから始めるかを選びます。シードの値自体には意味がありません。42、7、20260807、何でも構いません。ただし書き留めておきましょう。身につけるべき習慣はこうです。乱数を使うスクリプトの先頭に set.seed() を 1 つ。(抽出を消費すると状態が進むので、再現性には呼び出しの 順序 も影響することに注意してください。)
d/p/q/r 体系: 1 つの表がライブラリ全体を読み解く
R はすべての分布関数を接頭辞 + 分布族という形で命名しており、この格子を一度見れば統計ライブラリ全体を読めるようになります。
| 接頭辞 | 答える問い | 正規分布の例 |
|---|---|---|
r | ランダムな抽出がほしい | rnorm(5) |
d | 密度: x における曲線の高さは? | dnorm(0) |
p | 確率: P(X ≤ x) は? | pnorm(1.96) |
q | 分位点: この百分位にある x は? | qnorm(0.975) |
p と q は互いに逆関数であり、信頼区間で qt(0.975, df) として出会った組です。
分布族の名前を差し替えれば、すべてがそのまま通用します: runif/dunif/punif/qunif、rbinom/...、rpois/...、rt/...、rexp/...。4 つの接頭辞を覚えれば、数十の分布が手に入ります。
rnorm(): 正規分布からの抽出
rnorm(n, mean, sd) は釣鐘曲線から抽出します。測定値のようなデータをシミュレートするための主力です。
標本の平均と sd は 100 と 15 のちょうどではなく、その近くに落ち着きます。その差 こそ が標本抽出のノイズであり、n が増えるほど小さくなります。最後の行は盗む価値のある技です。論理値ベクトルの mean() は TRUE の割合であり、130 を超える割合は理論値 1 - pnorm(130, 100, 15) ≈ 2.3% の近くになります。既定値は mean = 0, sd = 1(標準正規分布)です。iq のヒストグラムを描くとおなじみの釣鐘が現れます。
runif()、rbinom()、rpois()
さらに 3 つの分布族が、シミュレーションの必要のほとんどを覆います。
runif() は範囲全体に均等に抽出を散らします("run if" ではなく "uniform" です。誰もが一度は読み違えます)。rbinom(n, size, prob) は size 回の試行からなる実験を n 回シミュレートし、それぞれの成功回数を返します。上の例の各値は、10 回のコイン投げのうち表が出た回数です。rpois(n, lambda) は既知の平均発生率で独立に起こるイベントの件数を生成します。1 時間あたりのサポートチケット数、1 ページあたりの誤字数などです。
sample(): 抽出とシャッフル
r* 系の関数が分布から値を作り出すのに対し、sample() は すでに手元にある 値から抽出します。
replace 引数がすべてを決めます。FALSE(既定)はカードを配るような動作で、各値は一度しか現れず、手持ちより多くを要求するとエラーになります。TRUE はサイコロを振るような動作で、抽出のたびにリセットされます。自分のデータからの 復元 抽出がブートストラップの原動力です。ベクトルだけを渡して呼ぶと、sample(x) はランダムな並べ替えを返します。シャッフルのイディオムです。
データフレームの行の抽出は、行の添字付けの中で sample() を使います。
sample(nrow(mtcars), 5) はランダムな行番号を 5 つ選び、添字付けがその行を取り出します。大きなデータセットを抜き取り確認したり、訓練用とテスト用に分割したりする標準的な手法です。
小さなモンテカルロシミュレーション
ここが道具立て全体の見返りです。問い: あるプロセスが N(100, 15) に従う測定値を生み、そのうち 10 個を平均する — その平均が 105 を超える確率はいくらか? 答えを導出する代わりに、シミュレートしましょう。実験を 10,000 回行って数えます。
シミュレーションは厳密値(約 0.146)の数千分の一以内に落ち着きます。これがひと息で語るモンテカルロです。1 回の試行を関数として書き、それを replicate() で何千回も繰り返し、成功の mean() を取る。 ここで厳密解が存在したのは、設定が教科書的に単純だったからです。問いが込み入った瞬間(風変わりな分布、相関のある抽出の最大値、規則に基づくゲーム)、解析的な道は閉ざされますが、シミュレーションのレシピはそのまま働き続けます。検算の中の 15 / sqrt(10) に注目してください。平均は個々の抽出より揺らぎが小さく、これは信頼区間の幅を支配するのと同じ平方根の法則です。
シミュレーション向けであって、機密向けではない
守るべき境界がひとつあります。R の既定の生成器(メルセンヌ・ツイスタ)は統計的な品質と速度のために作られており、秘匿性のためではありません。その出力はシードが決まれば決定論的であり、観測された出力から内部状態を再構成できます。パスワードやトークン、セキュリティに関わるものにとっては致命的な欠陥です。シミュレーション、ブートストラップ、教育には優れていますが、暗号には専用のライブラリ(たとえば openssl パッケージ)を使い、sample() や runif() は決して使わないでください。
この章のまとめ
- 先頭で一度
set.seed()を呼べば、あらゆる「ランダムな」結果が再現可能になります。同じシードなら同じ抽出です。 - d/p/q/r の接頭辞が分布ライブラリ全体を読み解きます。ランダムな抽出、密度、累積確率、分位点です。
rnorm(n, mean, sd)、runif(n, min, max)、rbinom(n, size, prob)、rpois(n, lambda)がシミュレーションの必要のほとんどを覆います。sample()は自分の値から抽出します。サイコロ的な動作にはreplace = TRUE、カード的な動作は既定、シャッフルにはsizeを省略します。df[sample(nrow(df), k), ]で行を抽出できます。- モンテカルロ = 1 試行の関数 +
replicate()+mean()。数学では簡単に届かない確率の問いに答えるレシピです。 - R の乱数生成器はシミュレーション用であり、暗号用ではありません。
次はデバッグ — R のエラーメッセージが実際に何を意味するのか、そしてトレースバックの読み方です。
よくある質問
R の set.seed() は何をしますか?
R の乱数生成器の開始点を固定します。その結果、続く「ランダムな」抽出は実行のたびに同一になります。乱数を使うスクリプトの先頭で一度呼べば — set.seed(42) — シミュレーションは再現可能になります。同僚も、採点者も、将来のあなたも同じ数値を見ることになります。
R で乱数を生成するにはどうしますか?
分布を選びます。正規分布からの抽出には rnorm(n, mean, sd)、一様分布には runif(n, min, max)、成功回数には rbinom(n, size, prob)、イベント数には rpois(n, lambda) です。既存の値からの抽出には sample(x, size) を使います。
rnorm、dnorm、pnorm、qnorm の違いは何ですか?
1 つの分布に 4 つの接頭辞があります。r はランダムな値を抽出し、d は密度曲線の高さを返し、p は累積確率 P(X ≤ x) を返し、q はその逆関数で、指定した百分位に対応する値を返します。同じ 4 つの接頭辞が R の知るすべての分布で使えます: runif/dunif/punif/qunif、rbinom/dbinom/pbinom/qbinom、などです。
R でデータフレームから行をランダムに抽出するにはどうしますか?
sample() で行に添字を付けます: df[sample(nrow(df), 5), ] は非復元で 5 行を選びます。復元抽出(ブートストラップの土台となる操作)には replace = TRUE を追加します。