我正在尝试使用numpy.random.choice为每一行创建一个由1到50之间的唯一值组成的二维数组(它有六列和很多行)。请注意,这只适用于每一行,而不是整个数组。
但是这会引发一个错误。
感谢大家。
np.sort(np.random.choice(np.arange(1,50),size=(100,6),replace=False))
但是这会引发一个错误。
ValueError: Cannot take a larger sample than population when 'replace=False'
有没有可能用一行代码而不需要循环来完成这个任务?
编辑
好的,我已经得到答案了。
这些是使用jupyter %time单元格魔法的结果。
#@James' solution
np.stack([np.random.choice(np.arange(1,50),size=6,replace=False) for i in range(1_000_000)])
Wall time: 25.1 s
#@Divakar's solution
np.random.rand(1_000_000, 50).argpartition(6,axis=1)[:,:6]+1
Wall time: 1.36 s
#@CoryKramer's solution
np.array([np.random.choice(np.arange(1, 50), size=6, replace=False) for _ in range(1_000_000)])
Wall time: 25.5 s
我更改了@Paul Panzer的解决方案中 np.empty和np.random.randint 的数据类型,因为它在我的电脑上无法正常工作。
3.6.0 |Anaconda custom (64-bit)| (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]
最快的是
def pp(n):
draw = np.empty((n, 6), dtype=np.int64)
# generating random numbers is expensive, so draw a large one and
# make six out of one
draw[:, 0] = np.random.randint(0, 50*49*48*47*46*45, (n,),dtype=np.uint64)
draw[:, 1:] = np.arange(50, 45, -1)
draw = np.floor_divide.accumulate(draw, axis=-1)
draw[:, :-1] -= draw[:, 1:] * np.arange(50, 45, -1)
# map the shorter ranges (:49, :48, :47) to the non-occupied
# positions; this amounts to incrementing for each number on the
# left that is not larger. the nasty bit: if due to incrementing
# new numbers on the left are "overtaken" then for them we also
# need to increment.
for i in range(1, 6):
coll = np.sum(draw[:, :i] <= draw[:, i, None], axis=-1)
collidx = np.flatnonzero(coll)
if collidx.size == 0:
continue
coll = coll[collidx]
tot = coll
while True:
draw[collidx, i] += coll
coll = np.sum(draw[collidx, :i] <= draw[collidx, i, None], axis=-1)
relidx = np.flatnonzero(coll > tot)
if relidx.size == 0:
break
coll, tot = coll[relidx]-tot[relidx], coll[relidx]
collidx = collidx[relidx]
return draw + 1
#@Paul Panzer' solution
pp(1_000_000)
Wall time: 557 ms
感谢大家。
samples = bottleneck.argpartition(np.random.rand(rows, 50), 6, 1)[:,:6])
可能更快,但我还没有检查过。 - pdowling