我想生成一个随机数字分布列表,这样它们的总和就等于一个随机选择的数字。例如,如果随机选择的数字是5,则分布将是[1 2 2]或[2 3]或[1 1 1 2],依此类推。 欢迎任何建议!
答案 0 :(得分:3)
让n
成为您想要加起来的数字。生成随机大小(小于sample
)的随机n
,由除n
之外的1到n
范围内的值组成。现在添加端点0和n
,然后排序。排序值的连续差异将总计为n
。
import random as r
def random_sum_to(n):
a = r.sample(range(1, n), r.randint(1, n-1)) + [0, n]
list.sort(a)
return [a[i+1] - a[i] for i in range(len(a) - 1)]
print random_sum_to(20) # yields, e.g., [4, 1, 1, 2, 4, 2, 2, 4]
如果您希望能够明确指定总和中的术语数,或者如果未指定则使其为随机数,请添加可选参数:
import random as r
def random_sum_to(n, num_terms = None):
num_terms = (num_terms or r.randint(2, n)) - 1
a = r.sample(range(1, n), num_terms) + [0, n]
list.sort(a)
return [a[i+1] - a[i] for i in range(len(a) - 1)]
print random_sum_to(20, 3) # [9, 7, 4] for example
print random_sum_to(5) # [1, 1, 2, 1] for example
答案 1 :(得分:2)
在一个循环中,您可以继续在1和剩余的总和之间绘制一个随机数,直到您达到总数
from random import randint
def generate_values(n):
values = []
while n > 0:
value = randint(1, n)
values.append(value)
n -= value
return values
这种功能的一些样本
>>> generate_values(20)
[17, 1, 1, 1]
>>> generate_values(20)
[10, 4, 4, 1, 1]
>>> generate_values(20)
[14, 4, 1, 1]
>>> generate_values(20)
[5, 2, 4, 1, 5, 1, 1, 1]
>>> generate_values(20)
[2, 13, 5]
>>> generate_values(20)
[14, 3, 2, 1]
答案 2 :(得分:0)
首先考虑连续进行。暂时我们不关心最终数字,所以让我们在区间[0 ... 1]中统一采样X_i,使它们的总和等于1
X_1 + X_2 + ... X_n = 1
这是众所周知的分布,称为Dirichlet分布,或伽马变量,或单纯形式采样。请参阅Generating N uniform random numbers that sum to M的详细信息和讨论。可以使用random.gammavariate(a,1)
或正确处理角点伽马变量与参数1是等效的指数分布,下面有直接采样代码
def simplex_sampling(n):
r = []
sum = 0.0
for k in range(0,n):
x = random.random()
if x == 0.0:
return (1.0, make_corner_sample(n, k))
t = -math.log(x)
r.append(t)
sum += t
return (sum, r)
def make_corner_sample(n, k):
r = []
for i in range(0, n):
if i == k:
r.append(1.0)
else:
r.append(0.0)
return r
所以从simplex_sampling
开始,你有向量和总和用作规范化。
因此,将其用于N = 5
N = 5
sum, r = simplex_sampling(N)
norm = float(N)/sum
# normalization together with matching back to integers
result = []
for k in range(N):
# t is now float uniformly distributed in [0.0...N], with sum equal to N
t = r[k] * norm
# not sure if you could have zeros,
# and check for boundaries might be useful, but
# conversion to integers is trivial anyway:
# values in [0...1) shall be converted to 0,
# values in [1...2) shall be converted to 1, etc
result.append( int(t) )
答案 3 :(得分:0)
这是一个简单的方法,一个随机的概率列表,其中总和等于一;
a = np.random.random(2)
a /=sum(a)
a