【问题标题】:Aggregate previous rows of into lists, depending on separate column将前几行聚合到列表中,具体取决于单独的列
【发布时间】:2021-04-16 17:11:27
【问题描述】:

我问了一个类似但更简单的问题previously,但后来意识到这并不能解决我的问题。我觉得对问题的必要编辑对于简单编辑问题来说太严格了,尤其是已经有两个有效答案,所以我会让它保持不变,而是问一个新的:

我有以下DataFrame 不同客户在不同时间的互动(查看和/或购买的产品):

import pandas as pd
rng = list(pd.date_range('2019-02-24', periods=5, freq='T')) + list(pd.date_range('2019-03-13', periods=2, freq='T')) + list(pd.date_range('2019-02-27', periods=1, freq='T'))
customers = ["c12987"]*5 + ["c89563"]*2 + ["c56733"]
articles = ["a8473", "a7631", "a1264", "a8473", "a5641", "a9813", "a7631", "a1132"]
action_type = ["viewed", "purchased", "viewed", "purchased", "viewed", "viewed", "purchased", "viewed"]

interaction_history = pd.DataFrame({'Customer_no': customers, 'Date': rng, 'Article_no': articles, "Interaction": action_type}) 
interaction_history

输出:

    Customer_no Date                Article_no  Interaction
0   c12987      2019-02-24 00:00:00 a8473       viewed
1   c12987      2019-02-24 00:01:00 a7631       purchased
2   c12987      2019-02-24 00:02:00 a1264       viewed
3   c12987      2019-02-24 00:03:00 a8473       purchased
4   c12987      2019-02-24 00:04:00 a5641       viewed
5   c89563      2019-03-13 00:00:00 a9813       viewed
6   c89563      2019-03-13 00:01:00 a7631       purchased
7   c56733      2019-02-27 00:00:00 a1132       viewed

我想为每个客户和行查看以前的文章以及购买的以前的文章。

预期输出:

    Customer_no Date                Article_no  Interaction Prev_viewed     Prev_purchased
0   c12987      2019-02-24 00:00:00 a8473       viewed      []              []
1   c12987      2019-02-24 00:01:00 a7631       purchased   [a8473]         []
2   c12987      2019-02-24 00:02:00 a1264       viewed      [a8473]         [a7631]
3   c12987      2019-02-24 00:03:00 a8473       purchased   [a8473, a1264]  [a7631]
4   c12987      2019-02-24 00:04:00 a5641       viewed      [a8473, a1264]  [a7631, a8473]
5   c89563      2019-03-13 00:00:00 a9813       viewed      []              []
6   c89563      2019-03-13 00:01:00 a7631       purchased   [a9813]         []
7   c56733      2019-02-27 00:00:00 a1132       viewed      []              []

我意识到我可以使用interaction_history.apply(lambda x: my_custom_function(x), axis=1) 之类的自定义函数遍历每一行,其中my_custom_function(x) 将为每一行过滤整个interaction_history 以找到匹配的Customer_no、Interaction 和适当的日期。我也意识到这种解决方案效率低下且非常复杂,因此希望有人有其他想法!

【问题讨论】:

  • groupby 允许按每个 customer_no 组织文件。如果 customer_no 对于每个人都是唯一的,您可以轻松地对每个客户执行操作以确定交易历史

标签: python python-3.x pandas numpy pandas-groupby


【解决方案1】:

您可以根据viewedpurchased 创建一个创建新列的函数。这里的关键是将-Article_no的行做成列表格式,这样你就可以使用cumsum根据查看或purchased将每个项目累积添加到列表中:

def previous(df, string):
    df['Article_no'] = df['Article_no'].str.split()
    col = 'Prev_' + string
    df[col] = (df[df['Interaction'].eq(string)].groupby('Customer_no')
               ['Article_no'].apply(lambda x: x.cumsum()))
    df[col] = df.groupby('Customer_no')[col].shift()
    df[col] = df.groupby('Customer_no')[col].ffill()
    df[col] = df[col].mask(df[col].isnull(), df[col].apply(lambda x: []))
    df['Article_no'] = df['Article_no'].str.join('')


previous(interaction_history, 'viewed')
previous(interaction_history, 'purchased')
Out[1]: 
    Customer_no Date                Article_no  Interaction Prev_viewed     Prev_purchased
0   c12987      2019-02-24 00:00:00 a8473       viewed      []              []
1   c12987      2019-02-24 00:01:00 a7631       purchased   [a8473]         []
2   c12987      2019-02-24 00:02:00 a1264       viewed      [a8473]         [a7631]
3   c12987      2019-02-24 00:03:00 a8473       purchased   [a8473, a1264]  [a7631]
4   c12987      2019-02-24 00:04:00 a5641       viewed      [a8473, a1264]  [a7631, a8473]
5   c89563      2019-03-13 00:00:00 a9813       viewed      []              []
6   c89563      2019-03-13 00:01:00 a7631       purchased   [a9813]         []
7   c56733      2019-02-27 00:00:00 a1132       viewed      []              []

【讨论】:

    【解决方案2】:
    • groupby() Customer_no 生成每个属性的列表
    • explode() 日期返回相同的行数
    • cumcount() 获取 Customer_no 内的相对索引
    • list 理解来构建您想要的列表
    import pandas as pd
    rng = list(pd.date_range('2019-02-24', periods=5, freq='T')) + list(pd.date_range('2019-03-13', periods=2, freq='T')) + list(pd.date_range('2019-02-27', periods=1, freq='T'))
    customers = ["c12987"]*5 + ["c89563"]*2 + ["c56733"]
    articles = ["a8473", "a7631", "a1264", "a8473", "a5641", "a9813", "a7631", "a1132"]
    action_type = ["viewed", "purchased", "viewed", "purchased", "viewed", "viewed", "purchased", "viewed"]
    
    df = pd.DataFrame({'Customer_no': customers, 'Date': rng, 'Article_no': articles, "Interaction": action_type}) 
    df = df.merge((df.groupby("Customer_no").agg(lambda x: list(x)).explode("Date")
            .reset_index(drop=False)
            .assign(i=lambda dfa: dfa.groupby("Customer_no").cumcount()
                ,prev_viewed=lambda dfa: dfa.apply(lambda r: [r["Article_no"][i] for i in range(r["i"]) if r["Interaction"][i]=="viewed"], axis=1)
                ,prev_purcahsed=lambda dfa: dfa.apply(lambda r: [r["Article_no"][i] for i in range(r["i"]) if r["Interaction"][i]=="purchased"], axis=1)
            )
            .drop(columns=["Article_no","Interaction","i"])
            )
        ,on=["Customer_no","Date"]
    )
    

    输出

    Customer_no                Date Article_no Interaction     prev_viewed  prev_purcahsed
         c12987 2019-02-24 00:00:00      a8473      viewed              []              []
         c12987 2019-02-24 00:01:00      a7631   purchased         [a8473]              []
         c12987 2019-02-24 00:02:00      a1264      viewed         [a8473]         [a7631]
         c12987 2019-02-24 00:03:00      a8473   purchased  [a8473, a1264]         [a7631]
         c12987 2019-02-24 00:04:00      a5641      viewed  [a8473, a1264]  [a7631, a8473]
         c89563 2019-03-13 00:00:00      a9813      viewed              []              []
         c89563 2019-03-13 00:01:00      a7631   purchased         [a9813]              []
         c56733 2019-02-27 00:00:00      a1132      viewed              []              []
    

    【讨论】:

    • 感谢您的努力。它按预期工作,尽管 David Erickson 的答案对于大型数据帧要快得多,因此我会接受这个答案。
    猜你喜欢
    • 2016-09-02
    • 1970-01-01
    • 2020-03-06
    • 2018-07-07
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多