X
给定具有T
行和列的矩阵k
:
T = 50
H = 10
k = 5
X = np.arange(T).reshape(T,1)*np.ones((T,k))
如何X
使用 lag 沿行轴执行滚动累积和H
?
Xcum = np.zeros((T-H,k))
for t in range(H,T):
Xcum[t-H,:] = np.sum( X[t-H:t,:], axis=0 )
请注意,在广播/矢量化最佳实践下,最好避免跨步和卷积。
X
给定具有T
行和列的矩阵k
:
T = 50
H = 10
k = 5
X = np.arange(T).reshape(T,1)*np.ones((T,k))
如何X
使用 lag 沿行轴执行滚动累积和H
?
Xcum = np.zeros((T-H,k))
for t in range(H,T):
Xcum[t-H,:] = np.sum( X[t-H:t,:], axis=0 )
请注意,在广播/矢量化最佳实践下,最好避免跨步和卷积。
听起来你想要以下内容:
import scipy.signal
scipy.signal.convolve2d(X, np.ones((H,1)), mode='valid')
这当然使用卷积,但如前所述,问题是卷积操作。广播将导致更慢/内存密集型算法。
您实际上缺少滚动总和的最后一行,这将是正确的输出:
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
沿该轴执行 a ,然后将结果计算为两个切片的差异。使用您的示例数组和轴:
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
这是一个跨步的解决方案。我意识到这不是你想要的,但我想知道它是如何比较的。
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
的数据,因此没有内存损失。但更难理解。