如何高效实现Pandas按时间重采样并取数量总值最大的value
问题描述
现有如下Pandas DataFrame df:
value quantity 2020-01-02 08:50:03 A 20 2020-01-02 08:52:39 B 29 2020-01-02 08:54:51 C 30 2020-01-02 08:55:03 C 20 2020-01-02 08:56:43 A 20 2020-01-02 08:59:59 B 10 2020-01-02 09:02:01 A 29 2020-01-02 09:03:29 B 27 2020-01-02 09:06:51 C 30 2020-01-02 09:07:03 C 20 2020-01-02 09:07:43 A 33 2020-01-02 09:09:59 B 10
需要按10分钟间隔对该DataFrame重采样,返回每个时间段内quantity总和最大的value及其对应的总数量,期望输出:
value quantity 2020-01-02 08:50:00 C 50 2020-01-02 09:00:00 A 62
当前实现方案能满足需求,但因冗余计算运行较慢:
def get_value_with_max_qty(df_rl): """ Returns the value and total quantity of the value with max qty Args: df_rl: A pandas rolling object Returns: A pandas series """ gper = df_rl.groupby(df_rl.value).quantity.sum() return pd.Series([gper.idxmax(), gper.max()])
执行代码:
df.resample('10T', label='right', closed='left').apply(get_value_with_max_qty)
请问是否存在无需在apply方法中使用groupby的更快速、更节省内存的实现方式?
优化方案
可以通过全局多层分组求和替代resample+apply的嵌套操作,避免逐段执行groupby的冗余计算,具体步骤如下:
- 给原DataFrame添加对应重采样时间段的标签列,用
pd.Grouper匹配时间规则:
df['time_bin'] = df.groupby(pd.Grouper(freq='10T', label='right', closed='left')).transform(lambda x: x.name)
- 按
time_bin和value分组,对quantity做求和聚合:
sum_df = df.groupby(['time_bin', 'value'])['quantity'].sum().reset_index()
- 筛选每个时间段内
quantity最大的行,推荐用排序后去重的方式,大数据量下性能更优:
result = sum_df.sort_values(['time_bin', 'quantity'], ascending=[True, False])\ .drop_duplicates('time_bin')\ .set_index('time_bin')
最终得到的result完全符合需求,这种方式把全局分组求和前置,避免了apply中逐段执行groupby的额外开销,内存占用和运行效率都会显著提升。
内容的提问来源于stack exchange,提问作者Vanillihoot
相关产品推荐
相关产品推荐

