为什么这样做:
a=np.random.rand(10,20)
x_range=np.arange(10)
y_range=np.arange(20)
a_tmp=a[x_range<5,:]
b=a_tmp[:,np.in1d(y_range,[3,4,8])]
而这不是:
a=np.random.rand(10,20)
x_range=np.arange(10)
y_range=np.arange(20)
b=a[x_range<5,np.in1d(y_range,[3,4,8])]
答案 0 :(得分:19)
Numpy参考文档的page on indexing包含答案,但需要仔细阅读。
这里的答案是使用布尔值进行索引相当于使用首先使用np.nonzero
转换布尔数组获得的整数数组进行索引。因此,使用布尔数组m1
,m2
a[m1, m2] == a[m1.nonzero(), m2.nonzero()]
(成功时,即m1.nonzero().shape == m2.nonzero().shape
)相当于:
[a[i, i] for i in range(a.shape[0]) if m1[i] and m2[i]]
我不确定为什么它会像这样工作 - 通常情况下,不是你想要的东西。
为了获得更直观的结果,您可以改为
a[np.ix_(m1, m2)]
产生相当于
的结果[[a[i,j] for j in range(a.shape[1]) if m2[j]] for i in range(a.shape[0]) if m1[i]]
答案 1 :(得分:5)
np.ix_
的替代方法是将布尔数组转换为整数数组(使用np.nonzero()
),然后使用np.newaxis
创建正确形状的数组以利用广播。
import numpy as np
a=np.random.rand(10,20)
x_range=np.arange(10)
y_range=np.arange(20)
a_tmp=a[x_range<5,:]
b_correct=a_tmp[:,np.in1d(y_range,[3,4,8])]
m1=(x_range<5).nonzero()[0]
m2=np.in1d(y_range,[3,4,8]).nonzero()
b=a[m1[:,np.newaxis], m2]
assert np.allclose(b,b_correct)
b2=a[np.ix_(x_range<5,np.in1d(y_range,[3,4,8]))]
assert np.allclose(b2,b_correct)
np.ix_
往往比双索引慢。
长格式解决方案似乎更快一点:
<强>长式强>:
In [83]: %timeit a[(x_range<5).nonzero()[0][:,np.newaxis], (np.in1d(y_range,[3,4,8])).nonzero()[0]]
10000 loops, best of 3: 131 us per loop
双重索引:
In [85]: %timeit a[x_range<5,:][:,np.in1d(y_range,[3,4,8])]
10000 loops, best of 3: 144 us per loop
使用np.ix _ :
In [84]: %timeit a[np.ix_(x_range<5,np.in1d(y_range,[3,4,8]))]
10000 loops, best of 3: 160 us per loop
注意:在您的计算机上测试这些计时是个好主意,因为排名可能会根据您的Python,numpy或硬件版本而改变。