嗨,我正在为一个基因组学课程编写一些代码,但在某个部分遇到了困难。
我有一组互斥事件 ,其概率为
我想要随机模拟给定概率下对一个事件进行n次采样。
输入:概率 = {0.3, 0.2, 0.5} 事件{e1,e2,e3} n=100
输出:e3大约应该有50个结果,e2有大约20个结果,e1有大约30个结果。请注意,这些可能不是完全准确的50、20、30,因为实际值与理论值不同...
Python本身没有内置任何加权抽样功能(NumPy/SciPy提供了此功能),但对于这样一个非常简单的情况,实现起来相当容易:
import itertools
import random
probabilities = [0.3, 0.2, 0.5]
totals = list(itertools.accumulate(probabilities))
def sample():
n = random.uniform(0, totals[-1])
for i, total in enumerate(totals):
if n <= total:
return i
如果您没有Python 3.2以上版本,则无法使用accumulate
函数;如果列表确实很短,您可以使用低效的一行代码方法来模拟它:
totals = [sum(probabilities[:i+1]) for i in range(len(probabilities))]
...或者您可以编写显式的循环,或者一个丑陋的reduce
调用,或者从文档中复制相应的Python函数。
另外,请注意,如果您确信数字总和为1.0,则random.uniform(0, totals[-1])
只是写random.random()
的一种更复杂的方式。
测试此方法的快速方式:
>>> samples = [sample() for _ in range(100000)]
>>> samples.count(0)
29878
>>> samples.count(1)
19908
>>> samples.count(2)
50214
import random
),并运行了100K次进行测试,它只有大约一半的时间会给出最后一个项的地址,这正是应该的。我已经编辑了答案以显示测试结果。如果它真的总是给你2
,那么要么你复制粘贴错了,要么你在代码的其他部分做错了什么,要么你应该立即去拉斯维加斯利用你的突变概率影响力量。 :) - abarnert
probabilities
和events
输入都是集合,就像你展示的那样,那么就没有办法将概率与事件匹配起来。 - abarnertn
个随机数吗? - Leigh