如何完善pandas的agg_items函数,实现详情模式的聚合输出?
问题:实现pandas DataFrame的两种聚合输出
原始数据
以下是全字符串类型的pandas DataFrame数据:
item client type status date 1 item1 bar O refused 13/05/2023 15:32:34 0 item1 foo A confirmed 01/01/2023 22:32:00 4 item1 foo A confirmed 14/05/2023 15:32:34 6 item2 baz A confirmed 11/06/2023 09:25:22 7 item2 baz O confirmed 15/02/2023 20:20:12 2 item2 qux O confirmed 02/04/2023 10:25:33 3 item3 baz A confirmed 07/06/2023 00:01:11 8 item3 foo O confirmed 18/11/2023 21:50:40 5 item3 qux O refused 03/05/2023 12:01:11
预排序操作
已执行以下排序(不确定是否必要):
df = df.sort_values(by=["item", "client", "date"])
期望输出
当details=False时
{ "item1": {"A": 1, "O": 0}, "item2": {"A": 0, "O": 2}, "item3": {"A": 1, "O": 1} }
当details=True时
{ "item1": {"A": {"foo": "14/05/2023 15:32:34"}, "O": {}}, "item2": {"A": {}, "O": {"baz": "15/02/2023 20:20:12", "qux": "02/04/2023 10:25:33"}}, "item3": {"A": {"baz": "07/06/2023 00:01:11"}, "O": {"foo": "18/11/2023 21:50:40"}} }
逻辑说明
- 首先忽略所有状态为
refused的订单; - 若同一
client订购同一item多次,仅保留最后一次订单的date值。
已实现代码
目前已完成details=False的部分,需要补充details=True的逻辑:
def agg_items(df, details=False): if not details: return ( df.loc[ (~df[["item", "client"]].duplicated(keep="last")) & df["status"].ne("refused") ] .pivot_table( index="item", columns="type", values="client", aggfunc="count", fill_value=0) .to_dict("index") ) else: # ... 待实现 pass
解决方案
可以按照以下步骤实现details=True的逻辑:
- 先过滤掉
status为refused的行; - 去除
item和client的重复项,保留最后一条记录; - 按
item和type分组,将每组的client和date转为字典; - 最后整理成目标嵌套字典格式。
完整代码如下:
def agg_items(df, details=False): # 先处理通用过滤和去重逻辑 filtered_df = df[df["status"] != "refused"] # 保留每个item+client的最后一条记录 unique_df = filtered_df.drop_duplicates(subset=["item", "client"], keep="last") if not details: return ( unique_df .pivot_table( index="item", columns="type", values="client", aggfunc="count", fill_value=0 ) .to_dict("index") ) else: # 先按item和type分组,将每组的client-date转为字典 grouped = unique_df.groupby(["item", "type"]).apply( lambda x: x.set_index("client")["date"].to_dict() ).unstack(fill_value={}) # 转为目标字典格式 return grouped.to_dict("index")
代码说明
- 通用部分:先统一过滤拒绝的订单,再去重保留最后一条,避免重复逻辑;
details=True时:用groupby结合apply将每个item-type组内的client作为键、date作为值生成字典,再通过unstack将type转为二级键,最后转成目标嵌套字典。
内容的提问来源于stack exchange,提问作者user21474411
相关产品推荐
相关产品推荐

