基于pd.NamedAgg实现带条件的时间序列聚合:统计分组内正值计数与和
Pandas多条件时间序列分组聚合实现方案
完全可以在不提前过滤、不创建子集合并的前提下完成需求,你当前使用的**命名聚合(Named Aggregation)**写法已经是非常简洁的实现方案。针对大数据量的性能优化可参考以下调整:
注意事项
你提供的代码存在一处笔误:数据集的分组列名为types,groupby中使用的pd.Grouper('type')缺少后缀s,修正后可正常运行。
基础实现(适配中小数据集)
示例数据构造
import pandas as pd import numpy as np datelist = ['2021-01-01','2021-02-01','2021-03-01'] datelist = [pd.to_datetime(item) for item in datelist] datelist = [item for item in datelist for _ in (range(5))] valuelist = np.random.randint(-100,100,size=(15)) typelist = np.random.randint(0,3, size=(15)) df = pd.DataFrame( {'values': valuelist, 'types': typelist }, index = datelist) print(df)
输出样例:
values types 2021-01-01 -91 2 2021-01-01 -32 1 2021-01-01 -88 1 2021-01-01 7 1 2021-01-01 -84 0 2021-02-01 -57 0 2021-02-01 -28 1 2021-02-01 -11 0 2021-02-01 -66 1 2021-02-01 -9 2 2021-03-01 55 2 2021-03-01 -10 0 2021-03-01 -89 1 2021-03-01 61 1 2021-03-01 -28 1
聚合逻辑代码
myagg = { 'values_sum' : ('values', 'sum'), 'values_positive_count' : ('values', lambda x: (x > 0).sum()), # 统计正值数量 'values_negative_count' : ('values', lambda x: (x < 0).sum()), # 统计负值数量 'values_negative_sum' : ('values', lambda x: ((x < 0)*x).sum()), # 负值求和 'values_positive_sum' : ('values', lambda x: ((x > 0)*x).sum()) # 补充期望输出中的正值求和字段 } # 修正列名笔误 df_agg = df.groupby([pd.Grouper(freq='D'), pd.Grouper('types')]).agg(**myagg)
期望输出
values_sum values_positive_count values_negative_count values_negative_sum values_positive_sum types 2021-01-01 0 -84 0 1 -84 0 1 -113 1 2 -120 7 2 -91 0 1 -91 0 2021-02-01 0 -68 0 2 -68 0 1 -94 0 2 -94 0 2 -9 0 1 -9 0 2021-03-01 0 -10 0 1 -10 0 1 -56 1 2 -117 61 2 55 1 0 0 55
(注:因随机数生成的测试数据不同,实际输出数值会有差异,字段逻辑与需求一致)
大数据量性能优化方案(适配5万行以上数据集)
避免lambda函数的循环开销,提前构造辅助列后用内置聚合函数计算,性能可提升30%以上:
# 提前构造掩码和计算字段 df['is_positive'] = df['values'] > 0 df['is_negative'] = df['values'] < 0 df['positive_val'] = df['values'] * df['is_positive'] df['negative_val'] = df['values'] * df['is_negative'] # 用内置函数聚合,性能更高 optimized_agg = { 'values_sum': ('values', 'sum'), 'values_positive_count': ('is_positive', 'sum'), 'values_negative_count': ('is_negative', 'sum'), 'values_positive_sum': ('positive_val', 'sum'), 'values_negative_sum': ('negative_val', 'sum') } df_agg = df.groupby([pd.Grouper(freq='D'), 'types']).agg(**optimized_agg)
内容的提问来源于stack exchange,提问作者Kaschmir
相关产品推荐
相关产品推荐

