在numpy数组上执行反向累积和

时间:2013-05-14 11:08:21

标签: python arrays numpy cumsum

有人可以推荐一种方法在numpy数组上进行反向累积求和吗?

其中'反向累积金额'定义如下(我欢迎对此程序的名称进行任何更正):

如果

x = np.array([0,1,2,3,4])

然后

np.cumsum(x)

给出

array([0,1,3,6,10])

但是,我想得到

array([10,10,9,7,4]

有人可以建议这样做吗?

5 个答案:

答案 0 :(得分:46)

这样做:

np.cumsum(x[::-1])[::-1] 

答案 1 :(得分:9)

仅供记录:np.sum(x) - np.cumsum(x)也是一个选项,但在大型阵列上速度快一半(速度很重要):

In [8]: x = np.ones(1e8)

In [9]: %timeit np.cumsum(x[::-1])[::-1]
1 loops, best of 3: 547 ms per loop

In [10]: %timeit np.sum(x) - np.cumsum(x)
1 loops, best of 3: 974 ms per loop

并且想要沿着第一个以外的某个维度做一个cumsum时不那么优雅:

x = np.ones((1e3,1e3))
np.sum(x,axis=-1)[:,np.newaxis] - np.cumsum(x,axis=-1)

答案 2 :(得分:2)

您也可以使用In [0]: x = np.array([0,1,2,3,4]) In [1]: np.flipud(np.flipud(x).cumsum()) Out[1]: array([10, 10, 9, 7, 4] ,这相当于.flip() https://docs.scipy.org/doc/numpy/reference/generated/numpy.flipud.html

.flipud()

.fliplr()是NumPy 1.12的新功能,它将np.flip(np.flip(x, 0).cumsum(), 0) nothing合并为一个API。 https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html

这是等效的,并且函数调用次数较少:

using NIfTI  # Julia package for reading NIfTI medical images

type RR
    source::Union(NIfTI.NIVolume, nothing)
end

答案 3 :(得分:0)

如果您想将结果存储在原始数组中,那么到目前为止给出的答案似乎都是无效的。同样,如果您想要一个副本,请记住,这将返回一个非连续数组的视图,并且仍然需要np.tocontiguousarray()。

怎么样

view=np.flip(x, 0)
np.cumsum(view, 0, out=view)
#x contains the reverse cumsum result and remains contiguous and unflipped

这将修改x的翻转视图,该视图以相反的顺序将数据正确地写回到原始x变量中。它在执行结束时不需要非连续视图,并且尽可能地提高速度效率。我猜想numpy永远不会添加反向求和方法,因为我描述的技术是如此简单有效。但是,使用显式方法可能会稍微更有效。

否则,如果需要复制,则需要额外的翻转并将其转换回连续数组,主要是如果此后它将在许多矢量操作中使用它。 numpy的一个棘手的部分,但是如果您对性能非常感兴趣,则必须谨慎对待视图和连续性。

答案 4 :(得分:-2)

为了好玩,使用匿名函数:

array = [0,1,2,3,4]

reverse = lambda a: a[::-1]
cumsum = lambda a: [ sum(a[:i+1]) for i,x in enumerate(a) ] # there is also an accumulate function present in the itertools module

print reverse(array)
print cumsum(array)

# sadly, no compose function in Python
reverse_cumsum = lambda a: reverse(  cumsum ( reverse(a) ) )

print reverse_cumsum(array)

结果:

[4, 3, 2, 1, 0]
[0, 1, 3, 6, 10]
[10, 10, 9, 7, 4]