リスト内の各インデックス(たとえばdata
)に対して、あらかじめ計算された確率リスト(たとえばprobs
)があるとします。
また、probs
とdata
は明らかに同じ長さを有していなければならないとprobs
のエントリが1
に加算非負数でなければなりません。
ランダムルーレットホイールとして知られているprobs
に分布に従ってdata
のインデックスを選択するニート単純な技術があります。 Pythonでは、私は信じて、これはによってrand
を乗じて(1
まで追加する必要はありません)非負の重みのリストに一般化することができることをこの
import random
data = ['A', 'B', 'C', 'D']
probs = [0.2, 0.4, 0.3, 0.1]
def roulette_wheel(probs):
rand = random.random()
for slot, prob in enumerate(probs):
rand -= prob
if rand < 0.0:
return slot
ノートのように何とかなります用語sum(weights)
。私は信じて、私は最初に、これまでのところ、パスカルのプログラミングについての本でこのかわいいアイデアを見ました。
編集:
MadPhysicistは1つが、同じデータから繰り返し描画する必要がある場合、これは多くの効率化を図ることができるcommentで示唆したように。その場合、累積分布関数を事前に計算してから、インデックスのバイナリ検索を実行して、cumulative prob. <= rand ~ U(0, 1)
とすることができます。 Pythonでは、これは例えば次のよう
from random import random
from bisect import bisect_right
def cdf(probs):
cdf = []
total = 0.0
for p in probs:
total += p
cdf.append(total)
return cdf
def roulette_wheel_bisect(cdf):
return bisect_right(cdf, random())
# compute cdf
cumsum = cdf(probs)
# randomly draw 10 indexes
for i in range(0, 10):
print(roulette_wheel_bisect(cumsum))
免責条項のように何とかなります:私は貿易によってPythonプログラマじゃないので、上記のコードは一般的な考えを示して必要があります。実用にはあまり強くないかもしれません。可能ならば、よくテストされた標準ライブラリ、例えばnumpyを使用するべきです。
EDIT2:
私はちょうどnumpy
はあなたが必要な正確に何んnumpy.random.choiceを持っていることを学びました。例:
from numpy import random
data = ['A', 'B', 'C', 'D']
probs = [0.2, 0.4, 0.3, 0.1]
# randomly draw 10 list elements with replacement
for i in range(0, 10):
print(random.choice(data, p=probs))
([異なる確率でリスト要素を選択するためのPython的な方法]の
可能重複http://stackoverflow.com/questions/4113307/pythonic-way-to-select-list-elements-with-different - 確率) – davedwards
numpyを使用しても問題ありませんか? –