我有一个整数值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)
答案 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