Pandas DataFrame MultiIndex groupby 缺少日期的滚动操作

Sam*_*han 4 python pandas

我有一个数据框,它有一个 MultiIndex,其中索引的最后一列是日期。我正在尝试对具有特定频率的列进行滚动操作。据我了解,如果我有 TimeIndex,通常的 Pandas 方法是使用频率字符串调用滚动函数(例如,如果我希望窗口为两天,则为“2D”)。建议的另一种方法是对 TimeIndex 重新采样,然后使用整数 2 应用滚动函数。基本上我想要能够做的是按除最后一列之外的所有列进行分组,然后告诉滚动列使用最后一列timedelta 特定的滚动。下面是一个例子来证明这一点:

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
Run Code Online (Sandbox Code Playgroud)

上面的代码不会为 (B, datetime(2017, 1, 2)) 创建一行,因此滚动总和将为全部两个。

解决这个问题的一种丑陋的方法,只有在有一组整天都有的情况下才真正有效,那就是在滚动之前拆开、填充和堆叠:

df.groupby([df.index.get_level_values(0), pd.Grouper(freq="1D", level=-1)]
).sum().unstack().fillna(0).stack().rolling(2).sum()
Run Code Online (Sandbox Code Playgroud)

毋庸置疑,这是一个丑陋的黑客,缓慢且容易出错。有没有一种很好的方法可以在没有大量操作的情况下实现我在这里需要的东西?理想情况下,有什么方法可以告诉石斑鱼采用时间戳列或自行填充缺失值?

jez*_*ael 5

您可以使用groupby+ resample+ fillna- 需要版本熊猫 0.19.0

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, 2, 3, 4, 1, 2, 3]})
print (df)
              colA
A 2017-01-01     1
  2017-01-02     2
  2017-01-03     3
  2017-01-04     4
B 2017-01-01     1
  2017-01-03     2
  2017-01-04     3

b = df.groupby(level=0).resample('1D', level=1).sum().fillna(0).rolling(2).sum()
print (b)
              colA
A 2017-01-01   NaN
  2017-01-02   3.0
  2017-01-03   5.0
  2017-01-04   7.0
B 2017-01-01   5.0
  2017-01-02   1.0
  2017-01-03   2.0
  2017-01-04   5.0
Run Code Online (Sandbox Code Playgroud)