【问题标题】:Create a list of N random numbers with max and min value and total sum创建具有最大值和最小值以及总和的 N 个随机数列表
【发布时间】:2022-01-05 13:48:51
【问题描述】:

我正在尝试创建一个包含 0.005 到 0.045 之间的 N 个随机数的列表(称为权重),总和等于 1。N 可以是 22 到 200 之间的任何整数。因此有以下限制:

  • 权重中的数字数 = N
  • 对于每 n 个权重:0.005
  • 所有 n 的权重之和 = 1

我认为第一个限制很容易。另外,我知道如何解决彼此分开的第二个和第三个限制。但我不知道如何将它们组合成一段代码。

  • 第二个限制:0.005
import numpy as np
import random


weights_step1 = np.random.randint(min=5, max = 45, size = N)

weights = []
for weight in weights_step1:
  weights.append(weight/1000)

  • 第三个限制

Generating a list of random numbers, summing to 1

有谁知道如何将这两个限制合并到一段代码中?

【问题讨论】:

  • 如果 N 小于 22 或大于 200 怎么办?
  • 看起来你的问题有一个缺陷,如果 N 可以是任意的并且权重只能从 0.005 到 0.045,如果我给 N 像 5 你无论如何都不能满足你的问题。
  • @mkrieger1 是的,你是对的。在我的情况下,这是一个 N 约为 50 的投资组合
  • @Bruno 我会编辑帖子,我的 N 大约是 50
  • @JonSG 嗯?!狄利克雷分布是约束到所需总和的完美示例

标签: python list numpy random sum


【解决方案1】:

这可能会奏效。该策略是对可用空间进行统一分区,然后对分区进行迭代,每次迭代从当前分区中获取一个随机位并将其添加到第二个分区中。

您可能会发现需要使用decimal 包来获得更高的精度。您可能还需要引入守卫,以确保对分区数量及其最小和最大大小的约束不会不一致。

import random

partitions = 45
partition_size_min = 0.005
partition_size_max = 0.045

weights = [1.0 / partitions] * partitions
for index in range(len(weights)):
    partner_index = random.randint(0, partitions-1)

    available_to_give = weights[index] - partition_size_min
    available_to_recieve = partition_size_max - weights[partner_index]
    delta = random.uniform(0, min(available_to_give, available_to_recieve))

    weights[partner_index] += delta
    weights[index] -= delta

print(f"Sum: {sum(weights)} Min:{min(weights)} Max: {max(weights)}")
print(weights)

这应该会给你这样的结果:

Sum: 1.0 Min:0.0057759435106850415 Max: 0.04428043727891049

[
    0.03408561328744241,
    0.010644787590344313,
    0.01400427089495221,
    0.01484912512559225,
    ...
    0.019186499047958494,
    0.02443794812733188,
    0.03475172101526412,
    0.020782296753987052
]

我相信一个合适的统计学家会发现这种方法的错误,但它可能会让你接近你想要的。

【讨论】:

    【解决方案2】:

    您可能想要使用Dirichlet Rescale algorithm (DRS)Python implementation 可用:

    这为您提供了适当的统计保证。引用数学论文的摘要:

    向量均匀分布在所有可能向量域的有效区域上,受约束限制。

    尝试 50 个数字的总和为 1:

    $ pip install drs
    ...
    Installing collected packages: drs
    Successfully installed drs-2.0.0
    $ 
    $ python3
    Python 3.9.9 (main, Nov 19 2021, 00:00:00) 
    ...
    >>>
    >>> from drs import drs
    >>>
    >>> n = 50
    >>> s = 1.0
    >>>
    >>> v1 = drs(n, s, n*[0.045], n*[0.005])
    >>> sum(v1)
    1.0000000000000004
    >>> max(v1)
    0.04278387127251347
    >>> min(v1)
    0.005035400173241331
    >>> 
    >>> v2 = drs(n, s, n*[0.045], n*[0.005])
    >>> sum(v2)
    0.9999999999999994
    >>> max(v2)
    0.04445793844097045
    >>> min(v2)
    0.005294943276519565
    >>> 
    

    【讨论】:

      猜你喜欢
      • 2018-10-30
      • 1970-01-01
      • 2020-05-10
      • 2019-02-24
      • 2020-07-21
      • 2023-04-10
      • 2018-11-10
      • 2015-05-07
      • 2011-02-09
      相关资源
      最近更新 更多