使用给定的总和随机均匀生成整数列表

问题描述 投票:1回答:2

我已经看过几个关于这个主题的帖子,但是它们看起来都不必要复杂或错误 - 以下提案不会受到前一个问题的影响(很简单),但可能是后者(这是错误的)。

我的目标是随机均匀地生成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

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

python random
2个回答
3
投票

那么,你在这里展示的是multinomial distribution,我相信。直接来自维基百科 - “它模拟了滚动s侧模具的计数概率n次。”,参数矢量pi = 1 / s。

然而,它们似乎都不必要地复杂或错误

不确定你有什么想法,但在Python世界中从多项式采样意味着你使用NumPy然后它是一个班轮

import numpy as np

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

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

如果你发现它更适合你,那么就这样吧,但是发明一种新的方法来采样众所周知的分布本身就是一项工作。请注意,有很多分布,其中结果的总和等于固定数 - f.e.,Dirichlet-multinomial。它们有很多参数,你可以大相径庭,实现统计上不同的结果。


2
投票

想象一下s = 10和n = 1_000_000。然后所有数字都倾向于聚集在100_000左右。我很确定你实际拥有的是具有lambda = n / s的泊松分布。

如果你想要更像统一分布的东西,你可以试试这样的东西:

- 生成0到1之间的随机数,并且sum表示它们的总和。

- 将每个数乘以(n / sum),并将这些十进制数命名为d_1,...,d_s。

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

现在,这些的总和是一些n_i,由于四舍五入,它可能小于n。让rest = n - n_i。基于d_1,...,d_s的其余部分对i_1,...,i_s进行排序,除以1(即基于{d_1%1,...,d_s%1}的排序顺序排序{i_1,...,i_s})最低指数的最低值。然后:

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

这将给出具有相同均匀分布的随机数,其被缩放以使得Sum(i_1,...,i_s)= n。

我希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.