对如何切割numpy数组感到困惑

时间:2012-01-31 04:02:26

标签: python numpy

m是一个有形状的ndarray(12,21,21),现在我只想把它的一个稀疏切片组成一个新的2D数组,用

sliceid = 0
indx    = np.array([0, 2, 4, 6, 8, 10])

因此sparse_slice直观地

sparse_slice = m[sliceid, indx, indx]

但显然上述操作不起作用,目前正在使用的是

sparse_slice = m[sliceid,indx,:][:, indx]

为什么第一个“直观”的方式不起作用?并且有一种比我目前的解决方案更紧凑的方式吗?我以前所有的ndarray切片试验都是基于直觉,也许我现在会转而阅读一些严肃的手册......

2 个答案:

答案 0 :(得分:5)

更紧凑的方式是new = m[0, :12:2, :12:2]。这就是numpy docs所谓的“基本索引”,意味着你用整数或切片对象切片(即0:12:2)。当您使用基本索引时,numpy返回原始数组的视图。例如:

In [3]: a = np.zeros((2, 3, 4))

In [4]: b = a[0, 1, ::2]

In [5]: b
Out[5]: array([ 0.,  0.])

In [6]: b[:] = 7

In [7]: a
Out[7]: 
array([[[ 0.,  0.,  0.,  0.],
        [ 7.,  0.,  7.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]]])

在您的“直观”方法中,您正在做的是使用另一个数组索引数组。当您使用另一个数组索引numpy数组时,数组需要具有相同的大小(或者它们需要相互广播,在一秒内更多关于此)。在文档中,这称为花式索引或高级索引。例如:

In [10]: a = np.arange(9).reshape(3,3)

In [11]: a
Out[11]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

In [12]: index = np.array([0,1,2])

In [13]: b = a[index, index]

In [14]: b
Out[14]: array([0, 4, 8])

你看到我得到[0,0],[1,1]和[2,2]而不是[0,0],[0,1] ......如果你想要的话索引索引的“外部产品”可以执行以下操作。

In [22]: index1 = np.array([[0,0],[1,1]])

In [23]: index2 = np.array([[0,1],[0,1]])

In [24]: b = a[index1, index2]

In [25]: b
Out[25]: 
array([[0, 1],
       [3, 4]])

上面有一个简写,如下所示:

In [28]: index = np.array([0,1])

In [29]: index1, index2 = np.ix_(index, index)

In [31]: index1
Out[31]: 
array([[0],
       [1]])

In [32]: index2
Out[32]: array([[0, 1]])

In [33]: a[index1, index2]
Out[33]: 
array([[0, 1],
       [3, 4]])

In [34]: a[np.ix_(index, index)]
Out[34]: 
array([[0, 1],
       [3, 4]])

您会注意到index1(2, 1)index2(1, 2),而不是(2, 2)。这是因为两个阵列相互广播,你可以阅读更多有关广播here的信息。请记住,当您使用花式索引时,您将获得原始数据的副本而不是视图。有时这更好(如果你想保持原始数据不变),有时它只需要更多的内存。有关索引here的更多信息。

答案 1 :(得分:2)

如果我没记错,输入m = np.array(range(5292)).reshape(12,21,21)您需要输出sparse_slice = m[sliceid,indx,:][:, indx]

array([[  0,   2,   4,   6,   8,  10],
       [ 42,  44,  46,  48,  50,  52],
       [ 84,  86,  88,  90,  92,  94],
       [126, 128, 130, 132, 134, 136],
       [168, 170, 172, 174, 176, 178],
       [210, 212, 214, 216, 218, 220]])

在这种情况下,您可以使用切片的step部分来获取它:

m[0, :12:2, :12:2]