首页 > 解决方案 > Numpy 随机选择,每个元素的重复时间有限

问题描述

给定N元素0, ..., N-1,以及一个指定每个元素数量的repeats大小数组。N我想知道随机选择size元素的最快方法是什么?输出是一个大小数组,N指示每个元素的所选数量。sum(output) == size.

例如,

def choice(repeats, size): ...

choice([100, 200, 300, 400, 500], 5)
# a random output: array([1, 0, 2, 1, 1])

请参阅当前解决方案的答案。

我想知道是否有避免分配元素option数组的方法?sum(repeats)

与不正确的实现但没有分配相比,当有很多元素时,速度差异大约为 20 倍:

def choice_wrong(repeats, size):
    chosen = np.random.choice(len(repeats), size, p=repeats/np.sum(repeats))
    return np.bincount(chosen, minlength=len(repeats))

%timeit choice([10000, 20000, 30000, 40000, 50000], 5000)
# 2.3 ms ± 7.47 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit choice_wrong([10000, 20000, 30000, 40000, 50000], 5000)
# 129 µs ± 822 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

标签: pythonperformancenumpyrandom

解决方案


也许这对其他人有用:random.sample 选择多个元素而不重复。因此,如果您根据限制创建一个包含重复元素的列表并使用 random.sample() ,那么您将获得有限重复的随机选择。

一般示例:

size = 5
RepetitionLimit = 3
>>> originalList = [1,2,3]
>>> listWithRep = [i for i in originalList for j in range(RepetitionLimit)]
>>> listWithRep
[1,1,1,2,2,2,3,3,3]
>>> outputList = random.sample(listWithRep , size)
>>> outputList
[1,1,1,2,3]

在这个问题的情况下,它会是这样的(虽然它类似于你的解决方案@Peter O.):

RepetitionLimit = [100, 200, 300, 400, 500]

def choice(repeats, size):
    chosen = random.sample([idx  for idx, elem in enumerate(repeats) for i in range(elem)], size)
    return [chosen.count(i) for i in range(len(repeats))]

choice(RepetitionLimit, 5)
# if chosen is [3, 3, 3, 4, 3] for example then result is [0, 0, 0, 4, 1] 

推荐阅读