我有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()
。
我不知道如何编写这样的函数,这可以让我把切片放到":"变成一个变量呢?到目前为止,我还没有找到解决方案。谢谢!
答案 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.swapaxes
和np.sum
,如此 -
def sum_axis_index(m, axis, index):
return m.swapaxes(0,axis)[index].sum()