【问题标题】:Pandas find most bought item given ClientID ItemID ItemQuantityPandas 在给定客户 ID 项目 ID 项目数量的情况下找到购买最多的商品
【发布时间】:2020-11-02 19:20:27
【问题描述】:

在我的 DataFrame 的列中,我有 ClientID CartID FoodID 数量,我想找出客户购买最多的食物是什么。

我试过这个:

df.groupby(["ClientID", "FoodID"])['Quantity'].sum().max(level=['ClientID', 'FoodID']).reset_index()

但是得到了一个完全错误的输出:

    Client  FoodID  Quantity
1   10      16008   24
2   10      17021   36
3   10      20665   6
4   10      20719   40
... ... ... ...
267610  200 84920   4
267611  200 85039   96
267612  200 85039   120
267613  200 85040   48
267614  200 85173   48

编辑:我也试过

mbi.groupby("ClientID")["Quantity"].max()

但这会导致一对(ClientID,最购买食物的数量),我需要(Client,FoodID)

【问题讨论】:

    标签: python pandas


    【解决方案1】:
    df.groupby(["ClientID", "FoodID"])['Quantity'].sum().reset_index().sort_values(
        ["ClientID", 'Quantity'], ascending=False).drop_duplicates(
        ["ClientID"]).sort_values('ClientID')
    

    首先获取一个包含每个ClientIDFoodID 组合的总Quantity 的df。然后在ClientIDQuantity 上对df 进行排序,以便每个客户端最高的Quantity 出现在顶部,最后删除每个客户端的重复项,这将删除除顶部之外的所有客户端记录,顶部恰好是最大数量。

    测试用例:

    np.random.seed(0)
    
    df = pd.DataFrame({
        'ClientID' : np.random.randint(1,10, 1000),
        'FoodID' : np.random.randint(1,10, 1000),
        'Quantity' : np.random.randint(1,10, 1000),
    })
    
    df.groupby(["ClientID", "FoodID"])['Quantity'].sum().reset_index().sort_values(
        ["ClientID", 'Quantity'], ascending=False).drop_duplicates(
        ["ClientID"]).sort_values('ClientID')
    

    输出:

        ClientID    FoodID  Quantity
    3   1           4       97
    16  2           8       82
    26  3           9       100
    35  4           9       98
    44  5           9       85
    47  6           3       107
    54  7           1       94
    69  8           7       107
    73  9           2       109
    

    【讨论】:

    • 这与我在问题中第一次尝试得到的输出相同
    • @ninazzo 你确定因为drop_duplicates(["ClientID"] 部分你不应该看到重复的ClientIDs
    • 你知道我现在该如何修复索引列吗?调用 reset_index 还会使用旧索引添加一个名为 index 的列
    • @ninazzo 添加.reset_index(drop=True)
    【解决方案2】:

    编辑:

    正如您在评论中处理每个ClientIDFoodID 总和一样,您只需要在idxmax 的groupby 之前为sum 提供另一个groupby。这将返回元组。传递这些最大ClientIDFoodID 的元组来构造一个数据框。

    ix = df.groupby(['ClientID', 'FoodID']).Quantity.sum().groupby(level=0).idxmax()
    df_final = pd.DataFrame(ix.tolist(), columns=['ClientID', 'FoodID'])
    
    Out[58]:
       ClientID  FoodID
    0         1       4
    1         2       8
    2         3       9
    3         4       9
    4         5       9
    5         6       3
    6         7       1
    7         8       7
    8         9       2
    

    原文:

    使用idxmax获取ClientID的每组在Quantity的最大值上的索引。得到每组maxQuantity的索引后,传给loc,得到对应的行列。

    idxmax的文档

    ix = df.groupby('ClientID').Quantity.idxmax()
    df_final = df.loc[ix, ["ClientID", "FoodID"]]
    

    【讨论】:

    • 你能补充一个简单的解释吗?
    • 我认为这个答案是错误的,因为没有总结数量,这只是给出了一次性购物会话中购买数量最多的商品。
    • @ninazzo:哦,我误解了你的问题。修复很简单。但是,您已经接受了另一个答案,所以我将删除这个答案。
    • 不,保留它,因为我觉得它很有用
    • 可能会添加修复,以便我比较结果以确保一切正常
    【解决方案3】:

    以下将提供您想要的:

    pd.pivot_table(df, index=['ClientID', 'FoodID'], values='Quantity', aggfunc='sum').groupby('ClientID').max()
    

    【讨论】:

    • 感谢您的回答,但它给了我一对(ClientID,最买食物的数量),我需要(Client,最买食物的ID)
    【解决方案4】:

    groupby 之后可以使用“nlargest”方法。

     df.groupby(["ClientID", "FoodID"])['Quantity'].sum().nlargest(1)
    

    【讨论】:

    • 我收到了这个错误“nlargest() got an unexpected keyword argument 'columns'”
    • 好的!从 nlargest() 中省略 'columns' 参数。我编辑了我的答案。
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 2022-10-17
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2016-01-26
    相关资源
    最近更新 更多