首页 > 解决方案 > pandas Grouper 未按预期进行上采样

问题描述

考虑一个具有 MultiIndex 的系列,它在级别 0 上提供自然分组值,在级别 1 上提供时间序列:

s = pd.Series(range(12), index=pd.MultiIndex.from_product([['a','b','c'],
              pd.date_range(start='2019-01-01', freq='3D', periods=4)], names=['grp','ts']))
print(s)
grp  ts
a    2019-01-01     0
     2019-01-04     1
     2019-01-07     2
     2019-01-10     3
b    2019-01-01     4
     2019-01-04     5
     2019-01-07     6
     2019-01-10     7
c    2019-01-01     8
     2019-01-04     9
     2019-01-07    10
     2019-01-10    11
Length: 12, dtype: int64

我想对每个外部索引值的时间序列进行上采样,例如使用简单的前向填充操作:

s.groupby(['grp', pd.Grouper(level=1, freq='D')]).ffill()

这会产生意想不到的结果;也就是说,它什么也不做。结果正是s我想要的,而不是我想要的:

grp ts
a   2019-01-01   0
    2019-01-02   0
    2019-01-03   0
    2019-01-04   1
    2019-01-05   1
    2019-01-06   1
    2019-01-07   2
    2019-01-08   2
    2019-01-09   2
    2019-01-10   3
b   2019-01-01   4
    2019-01-02   4
    2019-01-03   4
    2019-01-04   5
    2019-01-05   5
    2019-01-06   5
    2019-01-07   6
    2019-01-08   6
    2019-01-09   6
    2019-01-10   7
c   2019-01-01   8
    2019-01-02   8
    2019-01-03   8
    2019-01-04   9
    2019-01-05   9
    2019-01-06   9
    2019-01-07  10
    2019-01-08  10
    2019-01-09  10
    2019-01-10  11
Length: 30, dtype: int64

我可以将 Grouper freq 或 resample 函数更改为相同的效果。我发现的一种解决方法是通过创造性的技巧在每个组上强制一个简单的时间序列索引(感谢 Allen 提供答案https://stackoverflow.com/a/44719843/3109201):

s.reset_index(level=1).groupby('grp').apply(lambda s: s.set_index('ts').resample('D').ffill())

这与我最初要求的略有不同,因为它返回一个 DataFrame:

                 0
grp ts
a   2019-01-01   0
    2019-01-02   0
    2019-01-03   0
    2019-01-04   1
    2019-01-05   1
    2019-01-06   1
    2019-01-07   2
    2019-01-08   2
    2019-01-09   2
    2019-01-10   3
b   2019-01-01   4
    2019-01-02   4
    2019-01-03   4
    2019-01-04   5
    2019-01-05   5
    2019-01-06   5
    2019-01-07   6
    2019-01-08   6
    2019-01-09   6
    2019-01-10   7
c   2019-01-01   8
    2019-01-02   8
    2019-01-03   8
    2019-01-04   9
    2019-01-05   9
    2019-01-06   9
    2019-01-07  10
    2019-01-08  10
    2019-01-09  10
    2019-01-10  11

[30 rows x 1 columns]

我可以并且将使用这种解决方法,但我想知道为什么更简单(坦率地说更优雅)的方法不起作用。

标签: pythonpandasgroupingpandas-groupbymulti-index

解决方案


使用series.asfreq()它来满足缺失的日期。

def filldates(s_in):
  s_in.reset_index(level="grp",drop=True,inplace=True)
  s_in= s_in.asfreq("1D",method='ffill')
  return s_in
s.groupby(level=0).apply(filldates)

推荐阅读