选择一个ndarray的所有尺寸

时间:2016-04-07 01:26:33

标签: python numpy indexing

我有ndarray m维度(2,3,4)。我想选择一个特定的维度索引并总结其他所有内容:

m[:, 2, :].sum()

但是我需要一个函数来处理元素选择,因为ndarray可以有不同的维度,并且总和应该跨越不同的切片。该函数将获取感兴趣的维度(此处为0,1或2)和索引(0,1或2),如果输入为(1,2),则返回m[:, 2, :].sum()。如果是(2,0),我希望它等于m[:, :, 0].sum()

我不知道如何编写这样的函数,这可以让我把切片放到":"变成一个变量呢?到目前为止,我还没有找到解决方案。谢谢!

4 个答案:

答案 0 :(得分:4)

您可以将切片:放入带sl = slice(None, None, None)的变量中。但是,numpy有一个简写,np.s_[:]

总体而言:

def sum_axis_i(arr, axis, i):
    idx = (np.s_[:],) * axis + (i,)
    return arr[idx].sum()

请注意,尾随:是多余的,因此我们不必费心创建它们。

如果您使用与np.index_exp非常相似的np.s_,则可以写下:

def sum_axis_i(arr, axis, i):
    idx = np.index_exp[:] * axis + np.index_exp[i]
    return arr[idx].sum()

答案 1 :(得分:3)

您可以通过动态创建tuple slice

来实现
def sum_layer_axis(array, layer, axis):
    slicer = tuple(slice(None) if ax != axis else layer for ax in range(array.ndim))
    return np.sum(array[slicer])

只是为了说明这是如何工作的,考虑从slice

解释的内容
class Fun(object):
    def __getitem__(self, item):
        return item
Fun()[:, 2, :]
# (slice(None, None, None), 2, slice(None, None, None))

所以我们需要重新创建(但我们不需要指定None的3倍,一个就足够了)。这可以通过生成器表达式实现:

tuple(slice(None) if ax != axis else layer for ax in range(array.ndim))

因此,只要轴不是想要的轴,只需插入:等效物:slice(None),否则插入指定的图层。

测试结果:

a = np.arange(3*4*5).reshape((3,4,5))

axis = 1
layer = 2
a[:, layer, :].sum()
# 480
sum_layer_axis(a, layer, axis)
# 480

答案 2 :(得分:2)

这可能不是最有效的,但应该有效:

m = np.arange(60).reshape((3,4,5))

def my_sum(m, dim, index):
    dims = tuple(i for i in xrange(m.ndim) if i != dim)
    return m.sum(axis=dims)[index]

print my_sum(m,1,2)
print m[:,2,:].sum()

答案 3 :(得分:1)

这是一种方法,它将第一个轴与输入轴交换,然后使用输入索引进行索引,这将选择上下文中的所有元素,最后将所有元素与最终结果相加。实施将是一个紧凑的实施np.swapaxesnp.sum,如此 -

def sum_axis_index(m, axis, index):    
    return m.swapaxes(0,axis)[index].sum()