我只想在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) 有什么更快的方法吗?
答案 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
的优势,将执行拆分的位置的索引作为参数(而不是接近均匀的分区数)。