Har*_*pal 5 python random statistics probability
可能重复:
随机加权选择
生成具有给定(数字)分布的随机数
我有一个列表列表,其中包含一系列数字和相关概率.
prob_list = [[1, 0.5], [2, 0.25], [3, 0.05], [4, 0.01], [5, 0.09], [6, 0.1]]
Run Code Online (Sandbox Code Playgroud)
例如,prob_list[0]数字1的概率为0.5,与之相关.所以你会期望1出现50%的时间.
当我选择数字时,如何为数字增加权重?
注意:列表中的数字量可以在6到100之间变化
编辑
在列表中,我有6个数字及其相关概率.我想根据它们的概率选择两个数字.
没有数字可以选择两次.如果选择"2",则无法再次选择.
我将假设所有概率加起来为 1。如果它们不是,您将不得不相应地缩放它们,以便它们能够实现。
首先使用 生成均匀随机变量 [0, 1] random.random()。然后遍历列表,对概率求和。第一次总和超过随机数时,返回关联数。这样,如果生成的均匀随机变量落在您的示例中的范围 (0.5, 0.75] 内,则将返回 2,从而使其具有所需的 0.25 返回概率。
import random
import sys
def pick_random(prob_list):
r, s = random.random(), 0
for num in prob_list:
s += num[1]
if s >= r:
return num[0]
print >> sys.stderr, "Error: shouldn't get here"
Run Code Online (Sandbox Code Playgroud)
这是一个表明它有效的测试:
import collections
count = collections.defaultdict(int)
for i in xrange(10000):
count[pick_random(prob_list)] += 1
for n in count:
print n, count[n] / 10000.0
Run Code Online (Sandbox Code Playgroud)
输出:
1 0.498
2 0.25
3 0.0515
4 0.0099
5 0.0899
6 0.1007
Run Code Online (Sandbox Code Playgroud)
编辑:刚刚看到问题中的编辑。如果您想选择两个不同的数字,您可以重复上述操作,直到您选择的第二个数字不同。但是,如果一个数字与它相关的概率非常高(例如 0.99999999),这将非常缓慢。在这种情况下,您可以从列表中删除第一个数字并重新调整概率,以便在选择第二个数字之前它们的总和为 1。
这可能就是您正在寻找的。扩展为生成具有给定(数值)分布的随机数中的解决方案。从分布中删除所选项目,更新概率并返回selected item, updated distribution。尚未被证明有效,但应该给人留下良好的印象。
def random_distr(l):
assert l # don't accept empty lists
r = random.uniform(0, 1)
s = 0
for i in xrange(len(l)):
item, prob = l[i]
s += prob
if s >= r:
l.pop(i) # remove the item from the distribution
break
else: # Might occur because of floating point inaccuracies
l.pop()
# update probabilities based on new domain
d = 1 - prob
for i in xrange(len(l)):
l[i][1] /= d
return item, l
dist = [[1, 0.5], [2, 0.25], [3, 0.05], [4, 0.01], [5, 0.09], [6, 0.1]]
while dist:
val, dist = random_distr(dist)
print val
Run Code Online (Sandbox Code Playgroud)