给定X
行T
行和列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}}
注意,最好在广播/矢量化最佳实践中避免步幅和卷积。
答案 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。 einsum
比sum(0)
快一点。 temp
使用X
的数据,因此没有内存惩罚。但它更难理解。