如何在Pandas中聚合DataFrame,获取物品首末次出现的Count值
Python Pandas 聚合DataFrame获取首次/末次出现的Count值
原始DataFrame
Item Date Count Item_1 01/06/2023 25 Item_1 02/06/2023 14 Item_1 03/06/2023 5 Item_1 04/06/2023 7 Item_2 03/06/2023 41 Item_2 04/06/2023 49 Item_2 05/06/2023 2 Item_2 06/06/2023 38
需求
聚合为每个Item一行的DataFrame,包含:
- 首次出现日期
- 首次出现时的Count值
- 末次出现日期
- 末次出现时的Count值
- 每个Item的Count最小值
- 每个Item的Count最大值
目标结果
Item Earliest_date Count_at_earliest_date Latest_date Count_at_latest_date Min_of_count Max_of_count Item_1 01/06/2023 25 04/06/2023 7 5 25 Item_2 03/06/2023 41 06/06/2023 38 2 49
(注:原目标结果中Count_at_latest_date值存在错误,已修正为对应日期的真实Count值)
已实现代码
你已完成部分需求的代码:
df2 = df.groupby('Item').agg( earliest_date =('Date', 'min'), latest_date =('Date', 'max'), min_count = ('Count', 'min'), max_count = ('Count', 'max') ) df2.reset_index(inplace=True)
解决方案
要获取首次/末次日期对应的Count值,不能直接用agg的min/max,需结合日期定位对应行的Count,提供两种可行方法:
方法1:通过idxmin/idxmax定位索引获取值
先将Date转为日期类型避免字符串排序错误,再通过索引匹配对应Count:
import pandas as pd # 转换Date列为datetime类型,确保日期排序逻辑正确 df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y') # 获取每个Item首次出现的Count earliest_counts = df.loc[df.groupby('Item')['Date'].idxmin(), ['Item', 'Count']].rename(columns={'Count': 'Count_at_earliest_date'}) # 获取每个Item末次出现的Count latest_counts = df.loc[df.groupby('Item')['Date'].idxmax(), ['Item', 'Count']].rename(columns={'Count': 'Count_at_latest_date'}) # 执行原有聚合逻辑,同时格式化日期为原字符串格式 df2 = df.groupby('Item').agg( Earliest_date=('Date', lambda x: x.min().strftime('%d/%m/%Y')), Latest_date=('Date', lambda x: x.max().strftime('%d/%m/%Y')), Min_of_count=('Count', 'min'), Max_of_count=('Count', 'max') ).reset_index() # 合并聚合结果与首次/末次Count列 df2 = df2.merge(earliest_counts, on='Item').merge(latest_counts, on='Item') # 调整列顺序匹配目标结果 df2 = df2[['Item', 'Earliest_date', 'Count_at_earliest_date', 'Latest_date', 'Count_at_latest_date', 'Min_of_count', 'Max_of_count']]
方法2:自定义聚合函数
直接在agg中使用自定义函数,定位对应日期的Count值:
import pandas as pd df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y') def get_earliest_count(group): earliest_date = group['Date'].min() return group[group['Date'] == earliest_date]['Count'].values[0] def get_latest_count(group): latest_date = group['Date'].max() return group[group['Date'] == latest_date]['Count'].values[0] df2 = df.groupby('Item').agg( Earliest_date=('Date', lambda x: x.min().strftime('%d/%m/%Y')), Count_at_earliest_date=('Count', get_earliest_count), Latest_date=('Date', lambda x: x.max().strftime('%d/%m/%Y')), Count_at_latest_date=('Count', get_latest_count), Min_of_count=('Count', 'min'), Max_of_count=('Count', 'max') ).reset_index()
两种方法均可实现需求:方法1性能更优,适合大数据量场景;方法2逻辑直观,易读性更强。
内容的提问来源于stack exchange,提问作者Ellen Coggin
相关产品推荐
相关产品推荐

