2016-12-26 4 views
1

私はカスタムディストリビューションから乱数を生成しようとしていますが、すでにこの質問が見つかりました: Simulate from an (arbitrary) continuous probability distribution ですが、不満足なことに、私の分布は複数の一様分布の組み合わせであり、基本的に分布関数はヒストグラムのように見える。例は次のようになります。カスタムディストリビューションから乱数を生成する

f(x) = { 
    0  for x < 1 
    0.5 for 1 <= x < 2 
    0.25 for 2 <= x < 4 
    0  for 4 <= x 
} 

答えて

5

あなただけのCDF方法逆必要があります。その逆になるように

F(x) = 0     x < 1 
     0.5 * x - 0.5  1 < x < 2 
     0.25 * x   2 < x < 4 
     1     x > 4 

invF(x) = 2 * x + 1  0 < x < 0.5 
      4 * x   0.5 < x < 1 
自分はそれを確認するために

samplef <- function (n) { 
    x <- runif(n) 
    ifelse(x < 0.5, 2 * x + 1, 4 * x) 
    } 

計算CDFを

+0

ありがとう、これは正常に動作します。なぜ私はCDFを逆にする必要があるのか​​説明できますか? –

+0

ohhhh今私はそれを得る x < - runif(n) ifelse(x <0.5,2 * x + 1,4 x)これは2行です統一された[0,1]を作成し、マップします。もう一度ありがとうございます –

1

さまざまなe discrete distributionsからの連続的な均一化によるサンプリングのための効率的な方法。

つまり、変数の整数部分Y = [X]からシミュレートします。この変数は、(テーブルメソッド(別名エイリアス)メソッドなどの)各インターバル内にある確率に等しい確率で離散分布します。次に、ランダムな一様な[0,1 $、X = Y + U]を単純に追加します。

あなたの例では、確率0.5,0.25と0.25(これは等しい確率で1,1,2,3をサンプリングすることと同等です)の値1,2,3を取ってYをランダムに追加します。

"ヒストグラム"が本当に大きい場合、これは非常に高速なアプローチになります。

Rであなたが

sample(c(1,1,2,3))+runif(1) 

または

sample(c(1,1,2,3),n,replace=TRUE)+runif(n) 

を経由して本の(特に効率的でない場合)簡易版を行うことができ、より一般的にあなたがsampleで、確率の重み引数を使用することができます。

これ以上のスピードが必要な場合は(特に大きなヒストグラムや大きなサンプルサイズのアプリケーションでは)、リンクに記載されている手法を使用してディスクリート部​​品をかなり高速化できます。その関数の仕事の一部をより低いレベルの言語でプログラミングする(C言語で言う)。

これは、かなり大きなヒストグラム(数十から数百のビン)で上記のコードを使用しただけでも、このアプローチは、私のかなり難しいノートパソコンでさえも、100万のランダムな値を1秒未満では、多くのアプリケーションでこれは問題ありません。

+0

ありがとうございました、あなたのアプローチは、すべての「ビン」が同じ幅を持っていれば非常に直感的です。あなたのラインサンプル(c(1,1,2,3)、n、replace = TRUE)+ runif(n) –

+0

Btwを使用すると、次のようなサンプル関数で確率を使用できます。 サンプル、2 = 3)、size = 3000000、replace = TRUE、prob = c(0.5,0.25,0。25))あなたは2つの1 :-)の回避策を使用する必要はありません –

+0

(1,1、...部分は1ビンが2倍一般的ですので、サンプルがうまく実装されている場合は、より一般的な確率重み付けよりも... 2,3)部分は2-4ビンを分割しているので、それらはすべて同じ幅です。繰り返しますが、これは速度のためです。ビンの高さと幅がすべて有理数でない場合(質問にはこれが示唆されていませんが)、 'sample'と' runif'関数を適切に使用することによってやや遅くても一般的なアプローチが望ましいでしょう –