我有一个数据框,其中具有MultiIndex,其中索引的最后一列是日期。我试图对具有特定频率的列进行滚动操作。据我所知,如果我有一个TimeIndex,通常的pandas方法是使用频率字符串(例如'2D'表示窗口为两天)调用rolling函数。另一种建议是对TimeIndex进行重新采样,然后使用整数2应用rolling函数。本质上,我想要做到的是除了最后一列之外,按所有列进行分组,然后告诉rolling列使用最后一列进行timedelta-specific rolling。以下是一个示例以说明这一点:
毫无疑问,这是一种丑陋的hack方法,速度缓慢且容易出错。是否有更好的方法来实现我在此处所需的功能,而不需要进行广泛的操作呢?理想情况下,是否有某种方式可以告诉分组器使用时间戳列或自行填充缺失值呢?
from datetime import datetime
import pandas as pd
multi_index = pd.MultiIndex.from_tuples([
("A", datetime(2017, 1, 1)),
("A", datetime(2017, 1, 2)),
("A", datetime(2017, 1, 3)),
("A", datetime(2017, 1, 4)),
("B", datetime(2017, 1, 1)),
("B", datetime(2017, 1, 3)),
("B", datetime(2017, 1, 4))])
df = pd.DataFrame(index=multi_index, data={"colA": [1, 1, 1, 1, 1, 1, 1]})
display(df)
df.groupby([df.index.get_level_values(0), pd.Grouper(freq="1D", level=-1)]).sum().rolling(2).sum
上述代码并未创建一个行(B, datetime(2017, 1, 2)),因此滚动求和值将全部为两个。
一种不太优雅的解决方法是在滚动之前对数据进行unstack、fillna和stack操作,这仅适用于存在拥有所有日期的分组情况。
df.groupby([df.index.get_level_values(0), pd.Grouper(freq="1D", level=-1)]
).sum().unstack().fillna(0).stack().rolling(2).sum()
毫无疑问,这是一种丑陋的hack方法,速度缓慢且容易出错。是否有更好的方法来实现我在此处所需的功能,而不需要进行广泛的操作呢?理想情况下,是否有某种方式可以告诉分组器使用时间戳列或自行填充缺失值呢?
df.groupby(level=0).resample('1D', level=1).sum().fillna(0).groupby(level=0).apply(lambda x: x.rolling(2).sum())
- Sam Cohandf.groupby([df.index.get_level_values(0), pd.Grouper(freq="1D", level=-1)]).sum().unstack().fillna(0).stack().rolling(2).sum()
,则可以得到相同的输出。 - jezrael