如何沿矩阵轴执行滚动求和?

时间:2014-08-27 18:23:40

标签: python numpy scipy vectorization numpy-broadcasting

给定XT行和列k的矩阵T = 50 H = 10 k = 5 X = np.arange(T).reshape(T,1)*np.ones((T,k))

X

如何沿滞后H的行轴执行Xcum = np.zeros((T-H,k)) for t in range(H,T): Xcum[t-H,:] = np.sum( X[t-H:t,:], axis=0 ) 的滚动累计和?

{{1}}

注意,最好在广播/矢量化最佳实践中避免步幅和卷积。

3 个答案:

答案 0 :(得分:3)

听起来你想要以下内容:

import scipy.signal
scipy.signal.convolve2d(X, np.ones((H,1)), mode='valid')

这当然使用了卷积,但如上所述,问题是卷积运算。广播会导致更慢/内存密集的算法。

答案 1 :(得分:1)

你实际上错过了滚动总和中的最后一行,这将是正确的输出:

Xcum = np.zeros((T-H+1, k))
for t in range(H, T+1):
    Xcum[t-H, :] = np.sum(X[t-H:t, :], axis=0)

如果你需要在仅使用numpy的任意轴上执行此操作,最简单的方法是沿该轴执行np.cumsum,然后将结果计算为两个切片的差值。使用样本数组和轴:

temp = np.cumsum(X, axis=0)
Xcum = np.empty((T-H+1, k))
Xcum[0] = temp[H-1]
Xcum[1:] = temp[H:] - temp[:-H]

另一种选择是使用pandas及其rolling_sum函数,这对于所有可能性显然适用于2D数组,就像你需要它一样:

import pandas as pd
Xcum = pd.rolling_sum(X, 10)[9:] # first 9 entries are NaN

答案 2 :(得分:0)

这是一个跨步的解决方案。我意识到这不是你想要的,但我想知道它是如何比较的。

def foo2(X):
    temp = np.lib.stride_tricks.as_strided(X, shape=(H,T-H+1,k), 
        strides=(k*8,)+X.strides))
    # return temp.sum(0)
    return np.einsum('ijk->jk', temp)

这次是在35 us,而Jaime的cumsum解决方案为22 us。 einsumsum(0)快一点。 temp使用X的数据,因此没有内存惩罚。但它更难理解。