大熊猫石斑鱼未按预期进行升采样

时间:2019-09-19 16:00:39

标签: python pandas grouping pandas-groupby multi-index

考虑一个具有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频率或重采样功能更改为相同的效果。我发现的一种解决方法是通过创造性的欺骗手段在每个组上使用简单的时间序列索引(感谢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]

我可以并且将使用此变通办法,但是我想知道为什么更简单(坦率地说更优雅)的方法不起作用。

2 个答案:

答案 0 :(得分:0)

这仅仅是因为其系列的频率小于每日一次,所以没有效果。为什么您认为我应该给出NaN值?

替代

您可以使用pandas.Series.repeat计算GroupBy.Series.diff重复的次数:

mult=s.reset_index().groupby('grp')['ts'].diff().dt.days.shift(-1).fillna(1)
s.repeat(mult)

grp  ts        
a    2019-01-01     0
     2019-01-01     0
     2019-01-01     0
     2019-01-04     1
     2019-01-04     1
     2019-01-04     1
     2019-01-07     2
     2019-01-07     2
     2019-01-07     2
     2019-01-10     3
b    2019-01-01     4
     2019-01-01     4
     2019-01-01     4
     2019-01-04     5
     2019-01-04     5
     2019-01-04     5
     2019-01-07     6
     2019-01-07     6
     2019-01-07     6
     2019-01-10     7
c    2019-01-01     8
     2019-01-01     8
     2019-01-01     8
     2019-01-04     9
     2019-01-04     9
     2019-01-04     9
     2019-01-07    10
     2019-01-07    10
     2019-01-07    10
     2019-01-10    11

答案 1 :(得分:0)

使用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)