分配给numpy数组

时间:2018-01-24 13:51:34

标签: python numpy

我希望以下(或类似)工作(不使用np.where

>>> A = np.arange(0,10)
>>> ind = np.logical_and(A>4, A%2)
>>> k = np.array([0,1,0],dtype=bool)
>>> A[ind][k] = np.pi # Doesn't actually assign to A

也就是说,我希望k成为ind值的附加布尔掩码。

我知道我可以使用np.where(ind)[0][k],但这比逻辑索引更昂贵。

有没有办法引用A[ind]来引用A的基本内存?

2 个答案:

答案 0 :(得分:3)

来自经常引用的numpy索引页面:

  

....单个布尔索引数组实际上与x [obj.nonzero()]相同....但是,当obj.shape == x.shape时它更快。

np.where(cond)np.nonzero(cond)

但是,让我们做一些简单的时间

In [239]: x = np.arange(10000)
In [240]: y = (x%2).astype(bool)
In [241]: x[y].shape
Out[241]: (5000,)
In [242]: idx = np.nonzero(y)
In [243]: x[idx].shape
Out[243]: (5000,)
In [244]: timeit x[y].shape
89.9 µs ± 726 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [245]: timeit x[idx].shape
13.3 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [246]: timeit x[np.nonzero(y)].shape
34.2 µs ± 893 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

因此,即使我们使用显式where,数组索引也比布尔索引更快。

A[ind][k]=不起作用,因为A[ind]是副本,而不是视图。

In [251]: A = np.arange(100,110)
In [252]: ind = np.logical_and(A>104, A%2)
In [253]: ind
Out[253]: 
array([False, False, False, False, False,  True, False,  True, False,
        True])
In [254]: k = np.array([0,1,0], dtype=bool)
In [255]: A[ind]
Out[255]: array([105, 107, 109])
In [256]: A[ind][k]
Out[256]: array([107])
In [257]: A[ind][k] = 12
In [258]: A
Out[258]: array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109])

但是使用knp.where(ind)中选择索引:

In [262]: A[np.where(ind)[0][k]]=12
In [263]: A
Out[263]: array([100, 101, 102, 103, 104, 105, 106,  12, 108, 109])

获取而不是集合的时间:

In [264]: timeit A[np.where(ind)[0][k]]
1.94 µs ± 75.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [265]: timeit A[ind][k]
1.34 µs ± 13.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

所以是的,在这种情况下,双重屏蔽会更快一些,但如果它不起作用则无关紧要。不要为这些小小的改进而烦恼。

布尔索引方法

In [345]: ind1=ind.copy()
In [346]: ind1[ind] = k
In [348]: A[ind1]=3
In [349]: A
Out[349]: array([100, 101, 102, 103, 104, 105, 106,   3, 108, 109])

在这个小例子中,timeit基本上与A[np.where(ind)[0][k]]=12相同。

答案 1 :(得分:0)

这适用于小型数组(索引索引器!)。优化可能会更棘手。

import numpy as np

A = np.arange(0,10)
k = np.array([0,1,0])
ind = np.logical_and(A>4, A%2)

A[ind.nonzero()[0][k.nonzero()]] = np.pi