5

嗨,我正在为基因组学课程编写一些代码,但在某些方面遇到了困难。

事件1,事件2,...事件n 我有一组具有概率的互斥事件p1, p2, ... pn

我想以给定的概率模拟随机抽样事件 n 次。

输入:概率 = {0.3, 0.2, 0.5} 事件{e1,e2,e3} n=100

输出:e3 应该有 ~50 个结果,e2 应该有 ~20 个结果,e1 应该有 ~30 个结果。请注意,这些可能不完全是 50、20、30,因为经验值与理论值不同......

4

2 回答 2

5

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

这些分别非常接近 100000 的 30%、20% 和 50%。

于 2013-11-09T02:19:48.290 回答
2

假设我们有三个事件,每个事件的概率分别为 0.3、0.2 和 0.5。然后对于生成的每个样本,我们生成一个范围为 [0,1) 的数字,我们称之为“rand”。如果 "rand" < .3,我们生成事件 1,如果 .3 <= "rand" < .5,我们生成偶数 2,否则我们生成事件 3。这可以使用random()来完成,它确实生成了一个数字在 [0,1) 范围内。

于 2013-11-09T02:20:49.337 回答