我希望有人可以向我解释一下我用numpy数组观察到的以下行为:
>>> import numpy as np
>>> data_block=np.zeros((26,480,1000))
>>> indices=np.arange(1000)
>>> indices.shape
(1000,)
>>> data_block[0,:,:].shape
(480, 1000) #fine and dandy
>>> data_block[0,:,indices].shape
(1000, 480) #what happened???? why the transpose????
>>> ind_slice=np.arange(300) # this is more what I really want.
>>> data_block[0,:,ind_slice].shape
(300, 480) # transpose again! arghhh!
我不明白这种转置行为,这对我想做的事情非常不方便。有谁可以向我解释一下?获得data_block
子集的另一种方法是一个很好的奖励。
答案 0 :(得分:3)
您可以通过以下方式获得所需的结果:
>>> data_block[0,:,:][:,ind_slice].shape
(480L, 300L)
我承认我并不完全了解numpy索引的复杂程度,但是the documentation似乎暗示了你遇到的麻烦:
在切片元组中使用多个非:条目的基本切片,就像使用单个非:条目重复应用切片一样,其中连续采用非:条目(替换所有其他非条目:通过:)。因此,
x[ind1,...,ind2,:]
在基本切片下就像x[ind1][...,ind2,:]
一样。警告:高级切片不适用。
和。 。
当选择对象obj是非元组序列对象,ndarray(数据类型为integer或bool)或具有至少一个序列对象或ndarray(数据类型为整数或者数组)的元组时,将触发高级索引。布尔)。
因此,您通过使用ind_slice
数组而不是常规切片进行索引来触发该行为。
文档本身说这种索引“对于理解可能有些令人难以置信”,所以我们两个都遇到麻烦并不奇怪: - )。
答案 1 :(得分:1)
一旦你理解了花哨的索引是如何工作的,真的没有什么可惊讶的。如果您将列表或数组作为索引,则它们必须具有相同的形状,或者可以广播到常见形状。该形状将是返回数组的基本形状。如果有索引是切片,那么基本形状数组中的每个条目都将是多维的,因此基本形状将通过额外的条目进行扩展。虽然这似乎是一个奇怪的选择,但它确实是唯一与多维花式索引一致的选择。例如,如果您执行以下操作,请尝试计算返回形状的预期值:
>>> ind_slice=np.arange(16).reshape(4, 4)
>>> data_block[ind_slice, :, ind_slice].shape
(4, 4, 480) # No, (4, 4, 480, 4, 4) is not a better option
有几种方法可以让你得到你想要的东西。对于你问题中的特殊情况,最明显的是不使用花式索引,因为你可以得到你对切片的要求:
>>> data_block[0, :, :300].shape
(480, 300)
如果确实需要花式索引,可以用可广播数组替换切片:
>>> data_block[0, np.arange(480)[:, None], ind_slice].shape
(480, 300)