基于时间的.rolling()在通过分组失败

2024-09-08 10:28:29 发布

您现在位置:Python中文网/ 问答频道 /正文

这是来自Pandas Issue #13966的代码片段

dates = pd.date_range(start='2016-01-01 09:30:00', periods=20, freq='s')
df = pd.DataFrame({'A': [1] * 20 + [2] * 12 + [3] * 8,
                   'B': np.concatenate((dates, dates)),
                   'C': np.arange(40)})

失败:

^{pr2}$

根据上面链接的问题,这似乎是一个bug。有人有好的解决办法吗?在


Tags: 代码dataframepandasdfdatenprangeissue
2条回答

首先将B设置为索引,以便对其使用Groupby.resample方法。在

df.set_index('B', inplace=True)

GroupbyA并根据秒频率重新采样。由于重采样不能直接用于滚动,请使用ffill(向前fillna,其中NaN限制为0)。 现在使用rolling函数,方法是将窗口大小指定为4(因为freq=4s)间隔,并在C列取平均值,如下所示:

^{pr2}$

获得的结果输出:

B
2016-01-01 09:30:00    NaN
2016-01-01 09:30:01    NaN
2016-01-01 09:30:02    NaN
2016-01-01 09:30:03    1.5
2016-01-01 09:30:04    2.5
2016-01-01 09:30:05    3.5
2016-01-01 09:30:06    4.5
2016-01-01 09:30:07    5.5
2016-01-01 09:30:08    6.5
2016-01-01 09:30:09    7.5
Freq: S, Name: C, dtype: float64
B
2016-01-01 09:30:00     NaN
2016-01-01 09:30:01     NaN
2016-01-01 09:30:02     NaN
2016-01-01 09:30:03    21.5
2016-01-01 09:30:04    22.5
2016-01-01 09:30:05    23.5
2016-01-01 09:30:06    24.5
2016-01-01 09:30:07    25.5
2016-01-01 09:30:08    26.5
2016-01-01 09:30:09    27.5
Freq: S, Name: C, dtype: float64
B
2016-01-01 09:30:12     NaN
2016-01-01 09:30:13     NaN
2016-01-01 09:30:14     NaN
2016-01-01 09:30:15    33.5
2016-01-01 09:30:16    34.5
2016-01-01 09:30:17    35.5
2016-01-01 09:30:18    36.5
2016-01-01 09:30:19    37.5
Freq: S, Name: C, dtype: float64

TL;DR

请在适当设置索引后使用^{}作为解决方法:

# tested in version - 0.19.1
df.groupby('A').apply(lambda grp: grp.resample('s').ffill(limit=0).rolling(4)['C'].mean())

(或)

# Tested in OP's version - 0.19.0
df.groupby('A').apply(lambda grp: grp.resample('s').ffill().rolling(4)['C'].mean())

两者都有用。在

>>> df.sort_values('B').set_index('B').groupby('A').rolling('4s').C.mean()

相关问题 更多 >