我已经看过有关此主题的几篇文章,但是它们似乎都不必要地复杂或错误---以下提议不会遇到前一个问题(很简单),但可能会遇到后一个问题(那是错误的) )。
我的目标是随机产生均匀的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
由于我无论如何都不是统计学家,所以我担心这会产生并非真正均匀分布的数字。任何评论/分析将不胜感激
答案 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 。
我希望这会有所帮助。