【问题标题】:Create Poisson-like distribution with N random numbers whose sum is a constant (C)创建具有 N 个总和为常数 (C) 的随机数的类泊松分布
【发布时间】:2018-08-26 19:31:51
【问题描述】:

我想生成一个随机泊松数分布,其中生成的数字之和为 1000,分布的下上限为 (3-30)。

我可以使用 numpy 生成随机数:

在 [2] 中:np.random.poisson(5, 150) 数组([ 4, 4, 6, 4, 8, 6, 4, 2, 6, 8, 8, 8, 1, 4, 3, 4, 1, 3, 7, 6, 7, 4, 5, 5, 7, 6, 5, 3, 3, 5, 4, 6, 2, 0, 3, 5, 6, 2, 5, 2, 4, 7, 4, 7, 8, 5, 6, 1, 4, 4, 7, 4, 7, 2, 7, 4, 3, 8, 10, 2, 5, 7, 6, 3, 5, 7, 8, 5, 4, 7, 8, 8, 2, 2, 10, 6, 3, 5, 2, 5, 5, 6, 4, 6, 4, 0, 4, 3, 5, 8, 6, 7, 4, 4, 4, 3, 3, 4, 4, 6, 7, 6, 3, 9, 7, 7, 4, 5, 2, 4, 3, 6, 5, 6, 3, 6, 8, 9, 6, 3, 4, 4, 7, 3, 9, 12, 4, 5, 5, 7, 6, 5, 2, 10, 1, 3, 4, 4, 6, 5, 4, 4, 7, 5, 6, 5, 7, 2, 5, 5])


但是,我想添加更多内容:

- The random number should be minimal of 3 and max of 30 
- The sum of the generated random number should be 1000.

我知道,如果我进行操作,我可能无法创建精确的泊松分布。但是,我想要像泊松这样的东西,但有建议的控制。

【问题讨论】:

  • 值的数量总是固定的吗?
  • 你的问题毫无意义。如果它的最小值为 3,则它不是泊松。如果随机变量加到一个常数上,它们就不是独立的泊松。
  • @Denziloe 用泊松最小化 3 很容易 - 只需返回 poisson(lambda)+3。将上限设为 30 很难......
  • @Denziloe 问题要求“类似 possion”(原文如此)。移位泊松是一种合理的解释。
  • @Denziloe 人们采用“纯”分布并一直在重新缩放/转换它们以进行建模。如果两个分布除了轴上的标签之外具有相同的直方图,我认为可以说它们相似。

标签: python pandas numpy random numbers


【解决方案1】:

这是另一种选择,基于预先分配每个 bin 的最小值,计算剩余的观察数,并为每个剩余的 bin 输入泊松率,由剩余的观测数和 bin 数确定,但需要接受/基于每个 bin 的上限的拒绝。

由于泊松是对一个区间内有多少观测值的计数,因此如果不是所有观测值都已在初始阶段分配,它们将被一个接一个地随机分配到具有剩余容量的箱中。

这里是:

import numpy as np

def make_poissonish(n, num_bins):
    if n > 30 * num_bins:
        print("requested n exceeds 30 / bin")
        exit(-1)
    if n < 3 * num_bins:
        print("requested n cannot fill 3 / bin")
        exit(-1)

    # Disperse minimum quantity per bin in all bins, then determine remainder
    lst = [3 for _ in range(num_bins)]
    number_remaining = n - num_bins * 3

    # Allocate counts to all bins using a truncated Poisson
    for i in range(num_bins):
        # dial the rate up or down depending on whether we're falling
        # behind or getting ahead in allocating observations to bins
        rate = number_remaining / float(num_bins - i)  # avg per remaining bin

        # keep generating until we meet the constraint requirement (acceptance/rejection)
        while True:
            x = np.random.poisson(rate)
            if x <= 27 and x <= number_remaining: break
        # Found an acceptable count, put it in this bin and move on
        lst[i] += x
        number_remaining -= x

    # If there are still observations remaining, disperse them
    # randomly across bins that have remaining capacity
    while number_remaining > 0:
        i = np.random.randint(0, num_bins)
        if lst[i] >= 30:    # not this one, it's already full!
            continue
        lst[i] += 1
        number_remaining -= 1
    return lst

样本输出:

result = make_poissonish(150, 10)
print(result)                    # => [16, 19, 11, 16, 21, 18, 12, 17, 8, 12]
print(sum(result))               # => 150

result = make_poissonish(50, 10)
print(result)                    # => [3, 5, 5, 4, 3, 3, 15, 3, 6, 3]
print(sum(result))               # => 50

【讨论】:

  • 这真的很有帮助。我做了一些修改以适应我的需要。是否可以(通过电子邮件)与您联系,就统计和建模进行一些讨论。
【解决方案2】:

让我写一些行不通的东西,我们拭目以待

泊松分布的性质是一个参数 - λ - 同时是均值和方差的度量。让我们尝试另一种分布,它的总和为 1000,并且与 Poisson 足够接近。

我会尝试Multinomial Distribution。假设我们从多项式中抽取 200 个数字。我们将每个采样数移动 3,因此满足最小边界条件。这意味着对于采样多项式和(n 参数)等于 1000 - 3*200 = 400。概率 pi 将设置为 1/200。

因此,对于多项式平均值 E[xi] = n pi = 400/200 = 2。多项式的方差为 = n pi sub> (1 - pi),并且因为 pi 非常小,所以术语 (1 - pi) 会非常接近为 1,从而使采样整数类似于泊松,均值等于方差。问题是,移位后均值为 5,但方差保持在 ~2。

总之,一些代码。

import numpy as np

N = 200
shift = 3
n = 1000 - N*shift
p = [1.0 / float(N)] * N

q = np.random.multinomial(n, p, size=1)
print(np.sum(q))
print(np.mean(q))
print(np.var(q))

result = q + shift
print(np.sum(result))
print(np.mean(result))
print(np.var(result))

【讨论】:

  • p = [1.0 / float(N)] * N ?我想你的意思是*n。这看起来是解决这个问题的好方法。我将使用它进行模拟并进行任何必要的改进。
  • @everestial007 不,我的意思是N,要采样的项目数。所以数组p_i 包含概率并且是标准化的。请分享你的模拟结果,我很好奇它是否有效,如果它不会 - 为什么它没有
【解决方案3】:

您可以使用 while 循环和随机模块轻松完成它,它会完成这项工作:

from random import randint
nums_sum = 0
nums_lst = list()
while nums_sum < 1000:
    n = randint(3, 31)
    nums_sum += n
    nums_lst.append(str(n))
    print(nums_sum)
    if 1000-nums_sum > 30: # means if the sum is more than 30 then complete ..
        continue
    else:
        nums_sum += 1000-nums_sum
print(nums_sum)
print(nums_lst)

这么简单。

【讨论】:

  • 嗨,hassan,这是解决问题的好方法,但我担心分发应该是自然的。因此,获得平均值的平均概率高于分布末尾的数字。与随机数得到任意数的概率基本相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
相关资源
最近更新 更多