从每日到每分钟更快地重采样每日协方差矩阵(MultiIndex)
Faster Resampling Daily Covariance Matrix (MultiIndex) from Daily to Minutely
我查看了类似的答案,但找不到适合我问题的答案。
我有一个构造为 MultiIndex 的每日协方差矩阵。它有“k”个日期,对于每个“k”日期,它都有一个大小为“n”דn”的矩阵。维度在技术上是 (k, n, n) 但因为这是一个 MultiIndex pandas 将其视为形状 (kxn, n)。
作为最低限度的工作示例,我可以提供以下内容:
dates = pd.date_range(start='20120101', end='20210101', freq='D')
X = pd.DataFrame( {'A' : np.random.rand(len(dates)), 'B' : np.random.rand(len(dates)), 'C' : np.random.rand(len(dates)), 'D' : np.random.rand(len(dates)), 'E' : np.random.rand(len(dates)) }, index=dates).ewm(halflife=30, min_periods=1).cov()
我想从每天到每分钟重新采样。假设我的 MultiIndex 协方差矩阵被称为“X”,我已经设法让下面的工作:
X.unstack().resample("T").first().ffill().stack()
但是,这需要很长时间来计算。有没有更快更有效的方法来执行这个操作?
对于在 pandas 0.24 之后弃用的面板,这曾经是快速的。从我自己的分析工作来看,内存最密集的部分似乎是 'stack()'
IIUC
使用 resample 添加信息 ('D' -> 'T') 不是一个正确的选择,尤其是当您想要填充前向值时。您可以使用 np.vsplit
创建一个类似面板的面板,然后根据您的 DatetimeIndex 重复您的数组,最后重塑数据:
# Create new MultiIndex
dates2 = pd.date_range(X.index.levels[0].min(),
X.index.levels[0].max() + pd.DateOffset(days=1),
freq='T', closed='left')
mi = pd.MultiIndex.from_product([dates2, X.index.levels[1]])
# Manipulate your array
vals = np.array(np.repeat(np.vsplit(X.values, len(X.index.levels[0])), 24*60, axis=0))
vals = vals.reshape(vals.shape[0]*vals.shape[1], vals.shape[2])
# New dataframe
out = pd.DataFrame(vals, index=mi, columns=X.columns)
对于较小的样本:
>>> df
A B
2012-01-01 A 11 12
B 13 14
2012-01-02 A 21 22
B 23 24
2012-01-03 A 31 32
B 33 34
# Resample: 12H and 2 values per day
# dates2 = pd.date_range(df.index.levels[0].min(), df.index.levels[0].max() + pd.DateOffset(days=1), freq='12H', closed='left')
# mi = pd.MultiIndex.from_product([dates2, df.index.levels[1]])
# vals = np.array(np.repeat(np.vsplit(df.values, len(df.index.levels[0])), 2, axis=0))
# vals = vals.reshape(vals.shape[0]*vals.shape[1], vals.shape[2])
# out = pd.DataFrame(vals, index=mi, columns=df.columns)
>>> out
A B
2012-01-01 00:00:00 A 11 12
B 13 14
2012-01-01 12:00:00 A 11 12
B 13 14
2012-01-02 00:00:00 A 21 22
B 23 24
2012-01-02 12:00:00 A 21 22
B 23 24
2012-01-03 00:00:00 A 31 32
B 33 34
2012-01-03 12:00:00 A 31 32
B 33 34
使用您的代码:
>>> df.unstack().resample("12H").first().ffill().stack()
A B
2012-01-01 00:00:00 A 11.0 12.0
B 13.0 14.0
2012-01-01 12:00:00 A 11.0 12.0
B 13.0 14.0
2012-01-02 00:00:00 A 21.0 22.0
B 23.0 24.0
2012-01-02 12:00:00 A 21.0 22.0
B 23.0 24.0
2012-01-03 00:00:00 A 31.0 32.0
B 33.0 34.0
# <- Lost 2012-01-03 12:00:00
在 X
上的表现
>>> %timeit op_resample()
9.1 s ± 568 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit new_array()
1.86 s ± 23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我查看了类似的答案,但找不到适合我问题的答案。
我有一个构造为 MultiIndex 的每日协方差矩阵。它有“k”个日期,对于每个“k”日期,它都有一个大小为“n”דn”的矩阵。维度在技术上是 (k, n, n) 但因为这是一个 MultiIndex pandas 将其视为形状 (kxn, n)。
作为最低限度的工作示例,我可以提供以下内容:
dates = pd.date_range(start='20120101', end='20210101', freq='D')
X = pd.DataFrame( {'A' : np.random.rand(len(dates)), 'B' : np.random.rand(len(dates)), 'C' : np.random.rand(len(dates)), 'D' : np.random.rand(len(dates)), 'E' : np.random.rand(len(dates)) }, index=dates).ewm(halflife=30, min_periods=1).cov()
我想从每天到每分钟重新采样。假设我的 MultiIndex 协方差矩阵被称为“X”,我已经设法让下面的工作:
X.unstack().resample("T").first().ffill().stack()
但是,这需要很长时间来计算。有没有更快更有效的方法来执行这个操作?
对于在 pandas 0.24 之后弃用的面板,这曾经是快速的。从我自己的分析工作来看,内存最密集的部分似乎是 'stack()'
IIUC
使用 resample 添加信息 ('D' -> 'T') 不是一个正确的选择,尤其是当您想要填充前向值时。您可以使用 np.vsplit
创建一个类似面板的面板,然后根据您的 DatetimeIndex 重复您的数组,最后重塑数据:
# Create new MultiIndex
dates2 = pd.date_range(X.index.levels[0].min(),
X.index.levels[0].max() + pd.DateOffset(days=1),
freq='T', closed='left')
mi = pd.MultiIndex.from_product([dates2, X.index.levels[1]])
# Manipulate your array
vals = np.array(np.repeat(np.vsplit(X.values, len(X.index.levels[0])), 24*60, axis=0))
vals = vals.reshape(vals.shape[0]*vals.shape[1], vals.shape[2])
# New dataframe
out = pd.DataFrame(vals, index=mi, columns=X.columns)
对于较小的样本:
>>> df
A B
2012-01-01 A 11 12
B 13 14
2012-01-02 A 21 22
B 23 24
2012-01-03 A 31 32
B 33 34
# Resample: 12H and 2 values per day
# dates2 = pd.date_range(df.index.levels[0].min(), df.index.levels[0].max() + pd.DateOffset(days=1), freq='12H', closed='left')
# mi = pd.MultiIndex.from_product([dates2, df.index.levels[1]])
# vals = np.array(np.repeat(np.vsplit(df.values, len(df.index.levels[0])), 2, axis=0))
# vals = vals.reshape(vals.shape[0]*vals.shape[1], vals.shape[2])
# out = pd.DataFrame(vals, index=mi, columns=df.columns)
>>> out
A B
2012-01-01 00:00:00 A 11 12
B 13 14
2012-01-01 12:00:00 A 11 12
B 13 14
2012-01-02 00:00:00 A 21 22
B 23 24
2012-01-02 12:00:00 A 21 22
B 23 24
2012-01-03 00:00:00 A 31 32
B 33 34
2012-01-03 12:00:00 A 31 32
B 33 34
使用您的代码:
>>> df.unstack().resample("12H").first().ffill().stack()
A B
2012-01-01 00:00:00 A 11.0 12.0
B 13.0 14.0
2012-01-01 12:00:00 A 11.0 12.0
B 13.0 14.0
2012-01-02 00:00:00 A 21.0 22.0
B 23.0 24.0
2012-01-02 12:00:00 A 21.0 22.0
B 23.0 24.0
2012-01-03 00:00:00 A 31.0 32.0
B 33.0 34.0
# <- Lost 2012-01-03 12:00:00
在 X
上的表现>>> %timeit op_resample()
9.1 s ± 568 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit new_array()
1.86 s ± 23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)