如何按概率将整数分配到各个箱中

时间:2019-04-26 19:03:59

标签: python

我有一个整数值k和一个总计为1的概率列表。我想创建一个新列表,根据列表中的概率将k分解为较小的整数。

问题在于我事先不知道列表的大小,并且列表中的多个概率可能很小且相等,因此我的新列表并不总等于k

例如:

> k = 10
> l = [0.12, 0.12, 0.04, 0.04, 0.02, 0.02, 0.03, 0.03, 0.02, 0.02, 0.27, 0.27]
> sum(l)
1.0
> new_l = [int(round(k*v)) for v in a]
> print(new_l)
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3]
> sum(new_l)
8

如何执行sum(new_l) == k

也许这是不可能的,至少用我的方法。即使k大于len(l),如果k很奇怪,它似乎也无法正常工作:

>>> for k in [10, 11, 12, 13, 14, 15, 16, 20, 50, 75, 101, 1001, 1002, 10001, 10002, 100001, 100002]:
...     print(k, sum([round(k*v,0) for v in a]))
... 
(10, 8.0)
(11, 8.0)
(12, 8.0)
(13, 14.0)
(14, 14.0)
(15, 14.0)
(16, 14.0)
(20, 18.0)
(50, 52.0)
(75, 76.0)
(101, 100.0)
(1001, 1000.0)
(1002, 1002.0)
(10001, 10000.0)
(10002, 10002.0)
(100001, 100000.0)
(100002, 100002.0)

3 个答案:

答案 0 :(得分:2)

怎么样:

k = 10
l = [0.12, 0.12, 0.04, 0.04, 0.02, 0.02, 0.03, 0.03, 0.02, 0.02, 0.27, 0.27]
targets = [k*v for v in l]
new_l = [ int(v) for v in targets]

while sum(new_l) < k:
    residuals = [ t - v for t,v in zip(targets, new_l) ]
    index = residuals.index( max(residuals) )
    new_l[index] += 1

首先查找最大整数n,使n小于k*v,然后通过递增最差的n到sum(new_l) == k来固定它。完成操作不会超过O(len(l))个操作。

答案 1 :(得分:0)

您正在以错误的方式进行操作。您要尝试的是从列表n次中选择一个选项。这可以使用numpy.random.choice函数来实现。

这是对应的代码:

from numpy.random import choice
from collections import Counter
draw = choice(range(12), 100,
              p=[0.12, 0.12, 0.04, 0.04, 0.02, 0.02, 0.03, 0.03, 0.02, 0.02, 0.27, 0.27])
counter = Counter(draw)
print(counter.values())
print(sum(counter.values()))

这将输出:

dict_values([16, 13, 7, 3, 1, 1, 2, 2, 3, 2, 31, 19])
100

答案 2 :(得分:-1)

您可以通过随机操作做到这一点:

sl = np.cumsum(l) # cumulative probability
b = np.random.rand(10) # a random number for each of your integers

new_l = np.zeros(l.shape)    
for i in range(k):
    iinsert = np.where(b[i]>sl)[0][0] # first entry where b is larger than the cumumlative prob
    new_l[iinsert] += 1