区間$(a、b)$内の正規分布に従って乱数を生成する必要があります。 (私はRで作業しています。)
関数rnorm(n,mean,sd)
が正規分布に従って乱数を生成することは知っていますが、その範囲内で間隔制限を設定するにはどうすればよいですか?そのために利用できる特定のR関数はありますか?
コメント
回答
切断された分布 から、特定の例でシミュレートしたいようです。 、 切断正規 。
これを行うにはさまざまな方法があり、いくつかは単純で、いくつかは比較的です。効率的。
通常の例でいくつかのアプローチを説明します。
-
これは、一度に1つずつ生成するための非常に簡単な方法です(ある種の擬似コードで)。 ):
$ \ tt {repeat} $ Nから
$ x_i $ を生成します(mean、sd) $ \ tt {until} $ 下部 $ \ leq x_i \ leq $ 上部 ほとんどの分布が範囲内にある場合、これはかなり合理的ですが、次の場合はかなり遅くなる可能性がありますほとんどの場合、制限外で生成します。
Rでは、境界内の領域を計算することで一度に1つのループを回避し、破棄した後にほぼ確実になる十分な値を生成できます。範囲外の値でも、必要な数の値があります。
-
間隔全体で適切なメジャー化関数を使用してaccept-rejectを使用できます(場合によっては均一になります)十分に良い)。制限がs.dに比べて適度に狭い場合。しかし、あなたは尾に遠くはありませんでした。たとえば、均一なメジャー化は通常の場合でも問題なく機能します。
-
適度に効率的な累積分布関数と逆累積分布関数(
pnorm
やqnorm
など)がある場合Rの正規分布)切断正規のウィキペディアページのシミュレーションセクションの最初の段落で説明されている逆累積分布関数を使用できます。[事実上これは、切り捨てられたユニフォーム(必要な分位で切り捨てられます。これは単なる別のユニフォームであるため、実際には拒否をまったく必要としません)を取得し、それに逆正規cdfを適用するのと同じです。 「テールの奥深くにいる」場合は失敗する可能性があることに注意してください] -
他のアプローチもあります。同じウィキペディアのページで、さまざまなディストリビューションで機能する ziggurat メソッドの適応について言及しています。
同じウィキペディアのリンクでは、切断正規分布を生成する関数を備えた2つの特定のパッケージ(両方ともCRAN)について言及しています。
Rの
MSM
パッケージには、切り捨てられたものから描画を計算する関数rtnorm
があります。通常。Rのtruncnorm
パッケージには、切断正規から描画する関数もあります。
周りを見回すと、これの多くは他の質問への回答でカバーされています(ただし、この質問は切断正規分布よりも一般的であるため、正確には重複していません)…追加の説明を参照してください
a。この回答
b。 Xi “an”の回答ここには、彼のarXiv論文へのリンクがあります(他の価値のある回答もあります)。
回答
迅速で汚いアプローチは、 68-95-99.7ルールを使用することです。
正規分布では、値の99.7%が平均の3標準偏差内にあります。したがって、平均を目的の最小値と最大値の中央に設定し、標準偏差を平均の1/3に設定すると、(ほとんどの場合)目的の間隔内に収まる値が得られます。その後、残りをクリーンアップできます。
minVal <- 0 maxVal <- 100 mn <- (maxVal - minVal)/2 # Generate numbers (mostly) from min to max x <- rnorm(count, mean = mn, sd = mn/3) # Do something about the out-of-bounds generated values x <- pmax(minVal, x) x <- pmin(maxVal, x)
最近、同じ問題に直面し、を生成しようとしました。テストデータのランダムな学生の成績。上記のコードでは、pmax
とpmin
を使用して、範囲外の値を最小または最大の範囲内に置き換えました。値。生成するデータの量がかなり少ないため、これは私の目的には役立ちますが、大量のデータでは、最小値と最大値で顕著なバンプが発生します。したがって、目的によっては、これらの値を破棄して置き換える方がよい場合があります。 NA
を使用するか、「インバウンドになるまで再ロール」します。
コメント
- なぜわざわざこれを行うのですか?正規の乱数を生成し、切り捨てが必要なものを削除するのは非常に簡単なので、必要な切り捨てが領域の100%に近い場合を除いて、複雑にする必要はありません。'
- おそらく私は'元の質問を誤解しています。 Rで直接統計に関連しないプログラミングタスクを実行する方法を見つけようとしているときにこの質問に出くわしましたが、'このページが統計スタックエクスチェンジであることに気づきました。 、プログラミングスタックエクスチェンジではありません。 :)私の場合、0から100の範囲の値で、特定の量のランダムな整数を生成したいと思いました。生成された値は、その範囲全体で適切なベルカーブに収まるようにしました。これを書いた後、私は'
sample(x=min:max, prob=dnorm(...))
がおそらくそれを行うためのより簡単な方法であることに気づきました。 - @Glen_b Aaronウェルズは、あなたの答えより少し短いように見える
sample(x=min:max, prob=dnorm(...))
について言及しています。 - ただし、
sample()
のトリックは有用であることに注意してください。 'ランダムな整数、またはその他の個別の事前定義された値のセットを選択しようとしている場合。
回答
ここでの回答はどれも、任意の大きさの棄却を伴わない切り捨てられた正規変数を生成する効率的な方法を提供しません生成された値の数。指定された下限と上限
$ \ Phi $ が標準正規分布のCDFを表すとします。切断正規分布から
$$ X_i = \ mu + \ sigma \ cdot \ Phi ^ {-1}(U_i)\ quad \ quad \ quad U_1、…、U_N \ sim \ text {IID U} \ Big [\ Phi \ Big(\ frac {a- \ mu} {\ sigma} \ Big)、\ Phi \ Big(\ frac {b- \ mu} {\ sigma} \ Big)\ Big]。$$
切り捨てられた分布から生成された値の組み込み関数はありませんが、このメソッドを使用してこのメソッドをプログラムするのは簡単です。確率変数を生成するための通常の関数。これは、このメソッドを数行のコードで実装する単純なR
関数rtruncnorm
です。
rtruncnorm <- function(N, mean = 0, sd = 1, a = -Inf, b = Inf) { if (a > b) stop("Error: Truncation range is empty"); U <- runif(N, pnorm(a, mean, sd), pnorm(b, mean, sd)); qnorm(U, mean, sd); }
これは、切断正規分布からN
IIDランダム変数を生成するベクトル化された関数です。同じ方法で他の切り捨てられた分布の関数をプログラムするのは簡単です。また、切り捨てられた分布に関連する密度関数と分位関数をプログラムすることもそれほど難しくありません。
$ ^ \ dagger $ 注意してください。切り捨てにより、分布の平均と分散が変更されるため、 $ \ mu $ と
回答
3つの方法が役に立ちました:
-
rnorm()でsample()を使用する:
sample(x=min:max, replace= TRUE, rnorm(n, mean))
-
msmパッケージとrtnorm関数の使用:
rtnorm(n, mean, lower=min, upper=max)
-
ヒューが上記に投稿したように、rnorm()を使用して下限と上限を指定します:
sample <- rnorm(n, mean=mean); sample <- sample[x > min & x < max]
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]