n个项目在n个单元上的简单随机分布

时间:2019-02-19 18:55:57

标签: python arrays numpy distribution

我只想在n个单元格中分配N个项目,数字N和n都可以很大,所以我不想像下面这样随机遍历:

import numpy as np

nitems = 100
ncells = 3
cells = np.zeros((ncells), dtype=np.int)
for _ in range(nitems):
    dest = np.random.randint(ncells)
    cells[dest] += 1
print(cells)

在这种情况下,输出为:

[31 34 35]

(总和始终为N) 有什么更快的方法吗?

3 个答案:

答案 0 :(得分:1)

下面是这个问题的答案(在这里我必须感谢@pjs的帮助)。我认为这是最快,可能也是最短和最节省空间的一种:

from numpy import *
from time import sleep

g_nitems =   10000
g_ncells =   10
g_nsamples = 10000

def genDist(nitems, ncells):
    r = sort(random.randint(0, nitems+1, ncells-1))
    return concatenate((r,[nitems])) - concatenate(([0],r))

# Some stats

test = zeros(g_ncells, dtype=int)
Max = zeros(g_ncells, dtype=int)
for _ in range(g_nsamples):
    tmp = genDist(g_nitems, g_ncells)
    print(tmp.sum(), tmp, end='\r')
    # print(_, end='\r')
    # sleep(0.5)
    test += tmp
    for i in range(g_ncells):
        if tmp[i] > Max[i]:
            Max[i] = tmp[i]

print("\n", Max)
print(test//g_nsamples)

答案 1 :(得分:0)

您没有指定计数必须具有任何特定的分布,只要它们加起来为N,因此以下内容将按要求工作:

import numpy as np

nitems = 100
ncells = 3
range_array = [np.random.randint(nitems + 1) for _ in range(ncells - 1)] + [0, nitems]
range_array.sort()
cells = [range_array[i + 1] - range_array[i] for i in range(ncells)]
print(cells)

它会生成一个介于0和nitems之间的有序随机值集,然后采用连续的差值来生成所需数量的单元格计数。

复杂度是O({ncells)而不是O({nitems),因此,当项目数量远远大于单元格时,效率应该更高。

答案 2 :(得分:0)

在我的计算机上,带有timeit的代码花费了151微秒。以下过程耗时11微秒:

import numpy as np
nitems = 100
ncells = 3
values = np.random.randint(0,ncells,nitems)
cells  = np.array_split(values,3)
lengths= [ len(cell) for cell in cells ]
print(lengths,np.sum(lengths))

打印结果为[34, 33, 33] 100

这里的魔力是使用numpy进行拆分,但是请注意,此方法将尽可能接近统一进行拆分。

如果要随机进行分区:

import numpy as np
nitems = 100
ncells = 3
values = np.random.randint(0,ncells,nitems)
ind_split = [ np.random.randint(0,nitems) ]
ind_split.append(np.random.randint(ind_split[-1],nitems))
cells  = np.array_split(values,ind_split)
lengths= [ len(cell) for cell in cells ]
print(lengths,np.sum(lengths))

这利用numpy.array_split的优势,将执行拆分的位置的索引作为参数(而不是接近均匀的分区数)。