用给定的总和随机生成一个整数列表

时间:2019-03-11 00:58:03

标签: python random

我已经看过有关此主题的几篇文章,但是它们似乎都不必要地复杂或错误---以下提议不会遇到前一个问题(很简单),但可能会遇到后一个问题(那是错误的) )。

我的目标是随机产生均匀的s个整数,即正整数,它们的总和为n。对我来说,以下生成1和n之间的s随机数,然后输出频率的解决方案就是我们想要的:

import random
from collections import defaultdict

samples = list()

for i in range(n) :
    samples.append(random.randint(1,s))

hist = defaultdict(int)

for sample in samples :
    hist[sample] += 1

freq = list()

for j in range(s) :
    freq.append(hist[j+1])

print('list:', freq)
print('sum:', sum(freq))

因此,例如,如果我们想要s = 10个随机整数,总计n = 100,则可以从此过程中获得数据,例如

list: [11, 7, 9, 12, 16, 13, 9, 10, 8, 5]
sum: 100

由于我无论如何都不是统计学家,所以我担心这会产生并非真正均匀分布的数字。任何评论/分析将不胜感激

2 个答案:

答案 0 :(得分:3)

好吧,我相信您在这里提出的是multinomial distribution。直接来自维基百科-“它模拟n次滚动s面模具的计数概率”。 参数向量p i = 1 / s。

  

但是它们看上去都不必要地复杂或错误

不确定您的想法,但是在Python世界中从多项式采样意味着您使用NumPy,然后它是单线的

import numpy as np

result = np.random.multinomial(n, [1.0/s for _ in range(s)])

对于所有可能的参数组合,它可能会更快,经过良好测试并得到纠正。

如果您发现它更适合您,就这样吧,但是发明一种新的方法来采样著名的分布本身就是一项工作。请注意,在很多分布中,结果之和等于固定数-例如Dirichlet-multinomial。而且它们有很多参数,您可以随意改变它们,从而获得统计上不同的结果。

答案 1 :(得分:2)

想象 s = 10和 n = 1_000_000。然后所有数字趋向于聚集在100_000附近。我很确定您实际拥有的是泊松分布,其中lambda = n / s

如果您想要更像是统一发行版,可以尝试执行以下操作:

-生成介于0和1之间的s随机数,并让 sum 表示它们的总和。

-将每个数字乘以(n / sum ),然后让我们将这些十进制数字命名为 d _1,…, d _s。

-向下舍入到最接近的整数,并调用数字i_1,...,i_s。

现在,这些值的总和为 n _i,由于四舍五入的原因,它们可能小于 n 。令 rest = n - n_i 。根据除以1的d_1,…,d_s的其余部分对i_1,…,i_s进行排序(即根据{d_1%1,…,d_s%1}的排序顺序对{i_1,…,i_s}进行排序)最低索引处的最低值。然后:

for j in range(rest):
    i_(s-j) += 1

这将为您提供具有相同均匀分布的s随机数,它们的缩放比例应等于Sum( i _1,…, i _s)= n

我希望这会有所帮助。