我的google-fu让我失望了!
我有一个初始化为0
的10x10 numpy数组,如下所示:
arr2d = np.zeros((10,10))
对于arr2d
中的每一行,我想为1
分配3个随机列。我可以使用循环执行以下操作:
for row in arr2d:
rand_cols = np.random.randint(0,9,3)
row[rand_cols] = 1
输出:
array([[ 0., 0., 0., 0., 0., 0., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.],
[ 0., 0., 1., 0., 1., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
[ 1., 0., 0., 1., 1., 0., 0., 0., 0., 0.],
[ 1., 0., 1., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0., 0., 1., 0., 1., 0.],
[ 0., 0., 1., 0., 1., 0., 0., 0., 1., 0.],
[ 1., 0., 0., 0., 0., 0., 1., 1., 0., 0.],
[ 0., 1., 0., 0., 1., 0., 0., 1., 0., 0.]])
有没有办法利用numpy或数组索引/切片以更pythonic /更优雅的方式实现相同的结果(最好是1或2行代码)?
答案 0 :(得分:2)
使用arr2d
初始化arr2d = np.zeros((10,10))
后,您可以使用two-liner
这样的矢量化方法 -
# Generate random unique 3 column indices for 10 rows
idx = np.random.rand(10,10).argsort(1)[:,:3]
# Assign them into initialized array
arr2d[np.arange(10)[:,None],idx] = 1
如果您喜欢这样的话,或者为了单行而痉挛 -
arr2d[np.arange(10)[:,None],np.random.rand(10,10).argsort(1)[:,:3]] = 1
示例运行 -
In [11]: arr2d = np.zeros((10,10)) # Initialize array
In [12]: idx = np.random.rand(10,10).argsort(1)[:,:3]
In [13]: arr2d[np.arange(10)[:,None],idx] = 1
In [14]: arr2d # Verify by manual inspection
Out[14]:
array([[ 0., 1., 0., 1., 0., 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 1., 1., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 1., 0., 1.],
[ 0., 1., 1., 0., 0., 0., 0., 0., 1., 0.],
[ 0., 0., 1., 1., 0., 0., 0., 1., 0., 0.],
[ 1., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
[ 0., 0., 0., 1., 0., 0., 0., 1., 0., 1.],
[ 1., 0., 0., 0., 0., 0., 1., 0., 1., 0.],
[ 1., 0., 0., 1., 0., 0., 0., 0., 1., 0.],
[ 0., 1., 0., 1., 0., 0., 0., 0., 0., 1.]])
In [15]: arr2d.sum(1) # Verify by counting ones in each row
Out[15]: array([ 3., 3., 3., 3., 3., 3., 3., 3., 3., 3.])
注意:如果您正在寻找效果,我建议采用this other post
中列出的基于np.argpartition
的方法。
答案 1 :(得分:1)
使用this question的答案生成非重复随机数。您可以使用Python的random.sample
模块中的random
或np.random.choice
。
所以,只需对代码进行一些小修改:
>>> import numpy as np
>>> for row in arr2d:
... rand_cols = np.random.choice(range(10), 3, replace=False)
... # Or the python standard lib alternative (use `import random`)
... # rand_cols = random.sample(range(10), 3)
... row[rand_cols] = 1
...
>>> arr2d
array([[ 0., 0., 0., 0., 0., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 0., 0., 0., 0., 0., 1., 1.],
[ 1., 0., 0., 0., 0., 0., 1., 0., 1., 0.],
[ 0., 0., 1., 1., 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 0., 1., 1.],
[ 0., 0., 1., 1., 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
[ 0., 1., 0., 0., 1., 1., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 1., 0., 0., 0., 1., 0.],
[ 0., 0., 1., 1., 0., 0., 0., 0., 1., 0.]])
除非您从头开始生成随机数组,否则我认为您不能真正利用此处的列切片将设置值设置为1。这是因为您的列索引是每行的随机 。为了便于阅读,最好将其保留为循环形式。
答案 2 :(得分:0)
我不确定这在性能方面有多好,但它相当简洁。
arr2d[:, :3] = 1
map(np.random.shuffle, arr2d)