You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何完善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"}}
}

逻辑说明

  1. 首先忽略所有状态为refused的订单;
  2. 若同一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的逻辑:

  1. 先过滤掉status为refused的行;
  2. 去除item和client的重复项,保留最后一条记录;
  3. 按item和type分组,将每组的client和date转为字典;
  4. 最后整理成目标嵌套字典格式。

完整代码如下:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:37:05