Python:选择具有相关概率的数字

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",则无法再次选择.

mar*_*cog 5

我将假设所有概率加起来为 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。


Luc*_*ops 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)