我有一个代表分类数据的1D数组(其中每个条目是某个类别的元素数):
A = array([ 1, 8, 2, 5, 10, 32, 0, 0, 1, 0])
我正在尝试编写一个函数样本(A,N)来生成一个数组 B ,其中包含通过从A中随机绘制元素生成的N个元素(保持类别):
>>> sample(A, 20)
array([ 1, 3, 0, 1, 4, 11, 0, 0, 0, 0])
我写了这个:
def sample(A, N):
AA = A.astype(float).copy()
Z = zeros(A.shape)
for _ in xrange(N):
drawn = random.multinomial(1, AA/AA.sum())
Z = Z + drawn
AA = AA - drawn
return Z.astype(int)
可能它很天真,是否有更好/更快的方法呢?也许使用一些快速的numpy功能? 编辑:目前尚不清楚:它必须无需更换!!!
答案 0 :(得分:3)
比其他人快。但可能会占用更多内存。
import random
from collections import Counter
def sample2(A,N):
distribution = [i for i, j in enumerate(A) for _ in xrange(j)]
sample = Counter(random.sample(distribution, N))
return [sample[i] for i in xrange(len(A))]
In [52]: A = np.random.randint(0, 100, 500)
In [53]: %timeit sample(A, 100) #Original
100 loops, best of 3: 2.71 ms per loop
In [54]: %timeit sample2(A, 100) #my function
1000 loops, best of 3: 914 µs per loop
In [55]: %timeit sample3(A, 100) #sftd function
100 loops, best of 3: 8.33 ms per loop
答案 1 :(得分:2)
这可能不是最优雅的解决方案,但速度约为3倍。它使用numpy.random.choice
,它有一个布尔替换选项(在这种情况下设置为False
- 即没有替换)。其余代码是:
A[n]
个索引n
的计数,例如对于A=[2,0,3,1]
,你得到choices=[0,0,2,2,2,3]
。请注意,其中每个都具有相同的概率,因此无需创建概率数组。vals
数组的每个元素都是从choices
数组中选取的索引,因此您需要为每个选定的索引将{1}的相应元素加1。我希望这是有道理的!这是代码:
B
每个函数10000次调用的速度测试结果:
def sample_2(A, N):
# Create array of choices (indicies)
choices = []
for n in xrange(len(A)):
for _ in xrange(A[n]):
choices.append(n)
# Randomly choose from these indicies
vals = numpy.random.choice(choices, N, False)
# Count up the chosen indicies
B = numpy.zeros(len(A), dtype=int)
for index in xrange(N):
B[vals[index]] += 1
return B
答案 2 :(得分:0)
这是我将如何做到的:
def sample(A, N):
population = np.zeros(sum(A))
counter = 0
for i, x in enumerate(A):
for j in range(x):
population[counter] = i
counter += 1
sampling = population[np.random.randint(0, len(population), N)]
return np.histogram(sampling, bins = np.arange(len(A)+1))[0]
我们正在做的是建立由直方图A定义的种群,然后从中随机抽样。如果真实世界的情况下N大且sum(A)很小,和/或你需要对固定的A多次采样A,这应该会更好。你要做的是在函数调用之外构建与A对应的总体,并将sample(population, N)
定义为上面的最后两行。