把dict值加到一个阈值 - itertools.takewhile?

时间:2014-12-16 05:18:23

标签: python itertools

随机模拟中经常出现的一个问题是计算几个事件中的哪一个发生。这通常通过具有每个事件的概率来完成。然后生成一个随机数,然后迭代可能的事件,直到找到它们的概率总和超过随机数的位置。

以下是执行我想要的代码,但我正在采用更好的方法。

import random

def getEvent(eventProbabilities,probability):
    S = 0
    for key in eventProbabilities.keys():
        S += eventProbabilities[key]
        if S>= probability:   #key is the event to happen.
            break
    return key

x = {'event1' : 0.1 , 'event2' : 0.2 , 'event3' : 0.2 , 'event4' : 0.4, 'event5' : 0.1} #values sum to 1.
p = random.random()  #random number between 0 and 1.
event = getEvent(x,p)
print p, event

我觉得必须有一种更紧凑的方式来定义getEvent - 可能使用takewhile - 但我找不到它。

我追求最高效率,因为我认为这是我的代码将花费大部分时间的地方。

有没有办法通过itertools(或其他方式)提高效率?

编辑后面添加评论我们是否关注迭代顺序。

您会注意到密钥将按某种顺序处理。该顺序与随机数p无关。让我们考虑一下它按照我列出的顺序处理它们的情况。如果p<=0.1那么它将返回event1因此有10%的可能性它是event1。如果0.1<p<0.3它将返回event2(因此概率为20%)。现在我们考虑一个不同的顺序。说它按相反的顺序排列。在这种情况下,如果0.9<p我们将获得event1(10%),而如果0.7<p<=0.9我们获得event2(再次为20%)。因此,无论顺序如何,每个事件的概率都是相同的。

我只想选择1个事件,我希望以相应的概率选择该事件。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,您只需要从给定概率的列表中选择一个元素。为什么不使用numpy

>>> x = {'event1': 0.1 , 'event2': 0.2 , 'event3': 0.2 , 'event4': 0.4, 
         'event5': 0.1}
>>> events, p = zip(*x.items())
>>> np.random.choice(events, p=p, replace=False)
'event4'