选择要在numpy数组中索引的维度

时间:2017-01-01 19:57:32

标签: python arrays numpy

我正在编写一个程序,假设能够导入更高维度的numpy数组,例如像数组a:

a = numpy.zeros([3,5,7,2])

此外,每个尺寸将对应于一些物理尺寸,例如,频率,距离......我还会导入包含这些尺寸信息的数组,例如:以上:

freq = [1,2,3]
time = [0,1,2,3,4,5,6]
distance = [0,0,0,4,1]
angle = [0,180]

显然,从这个例子和签名中可以看出,freq属于维度0,时间属于维度2,依此类推。但由于事先不知道,我可以采用像

这样的频率切片
a_f1 = a[1,:,:,:]

因为我不知道频率被索引到哪个维度。

所以,我想要的是有一些方法来选择索引索引的维度;在一些Python的代码中就像

a_f1 = a.get_slice([0,], [[1],])

这假设从维度0返回索引为1的切片以及其他完整维度。

否则

a_p = a[0, 1:, ::2, :-1]
然后

会对应像

这样的东西
a_p = a.get_slice([0, 1, 2, 3], [[0,], [1,2,3,4], [0,2,4,6], [0,]])

2 个答案:

答案 0 :(得分:1)

您可以根据需要使用slice对象轻松构建索引元组,然后使用它来索引数组。配方的基本原则是:

indices = {
    0: # put here whatever you want to get on dimension 0,
    1: # put here whatever you want to get on dimension 1,
    # leave out whatever dimensions you want to get all of
}
ix = [indices.get(dim, slice(None)) for dim in range(arr.ndim)]
arr[ix]

这里我用字典完成了,因为我认为这样可以更容易地看出哪个维度与哪个索引器有关。

所以使用您的示例数据:

x = np.zeros([3,5,7,2])

我们这样做:

indices = {0: 1}
ix = [indices.get(dim, slice(None)) for dim in range(x.ndim)]

>>> x[ix].shape
(5L, 7L, 2L)

因为你的数组都是零,我只是显示结果的形状以表明它是我们想要的。 (即使它不是全零,也很难以文本形式读取3D数组。)

对于你的第二个例子:

indices = {
    0: 0,
    1: slice(1, None),
    2: slice(None, None, 2),
    3: slice(None, -1)
}
ix = [indices.get(dim, slice(None)) for dim in range(x.ndim)]

>>> x[ix].shape
(4L, 4L, 1L)

您可以看到形状与a_p示例中的值数相对应。需要注意的一点是,第一个维度消失了,因为您只为该索引指定了一个值。最后一个维度仍然存在,但长度为1,因为您指定了恰好只获得一个元素的切片。 (这与some_list[0]为您提供单一值的原因相同,但some_list[:1]为您提供了单元素列表。)

答案 1 :(得分:0)

您可以使用advanced indexing来实现此目标。

每个维度的索引需要适当调整,以便索引在数组中正确广播。例如,三维数组的第一维的索引需要被整形(x, 1, 1),以便它将在第一维上广播。三维数组的第二维索引需要整形(1, y, 1),以便在第二维上进行广播。

import numpy as np
a = np.zeros([3,5,7,2])
b = a[0, 1:, ::2, :-1]

indices = [[0,], [1,2,3,4], [0,2,4,6], [0,]]
def get_aslice(a, indices):
    n_dim_ = len(indices)
    index_array = [np.array(thing) for thing in indices]
    idx = []
    # reshape the arrays by adding single-dimensional entries
    # based on the position in the index array 
    for d, thing in enumerate(index_array):
        shape = [1] * n_dim_
        shape[d] = thing.shape[0]
        #print(d, shape)
        idx.append(thing.reshape(shape))

    c = a[idx]

    # to remove leading single-dimensional entries from the shape
    #while c.shape[0] == 1:
    #   c = np.squeeze(c, 0)

    # To remove all single-dimensional entries from the shape
    #c = np.squeeze(c).shape

    return c

对于a作为输入,它返回一个形状为(1,4,4,1)的数组,a_p示例的形状为(4,4,1)。如果需要删除额外的维度,请取消注释函数中的np.squeeze行。

现在我觉得很傻。在阅读文档较慢时,我注意到numpy有一个索引例程可以执行您想要的操作 - numpy.ix_

>>> a = numpy.zeros([3,5,7,2])
>>> indices = [[0,], [1,2,3,4], [0,2,4,6], [0,]]
>>> index_arrays = np.ix_(*indices)
>>> a_p = a[index_arrays]
>>> a_p.shape
(1, 4, 4, 1)
>>> a_p = np.squeeze(a_p)
>>> a_p.shape
(4, 4)
>>>