Pandas,如何避免使用iterrow(如何基于另一个数据帧的值为数据帧中的新列赋值)

2024-05-18 21:23:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有三个不同的实体:机会账户活动。你知道吗

我需要用一种特殊的方式把它们结合起来。我来解释一下它们之间的关系:

  • 机会N-1客户
  • 账户1-N活动

另外,值得注意的是

  • 机会具有以下字段:{ opp_id ; opp_date ; acc_id}
  • 活动有以下字段:{ act_id ; act_date ; acc_id }

我想实现的是,在Opportunity中插入Opportunity日期前X天完成的活动数。你知道吗

我现在是这样做的:

a_new_df = pd.DataFrame(columns=['acc_id',"opp_id", "opp_date", "act_90", "act_180"])

for index, opp_row in Opportunity.iterrows():
    account = opp_row["acc_id"]
    opportunity = opp_row["opp_id"]
    opp_date = opp_row["opp_date"]
    act_90, act_180 = 0, 0
    for index, act_row in activities_step_7.iterrows():
        if acc == act_row["acc_id"]:
            days = (pd.to_datetime(opp_date) - pd.to_datetime(act_row["act_date"])).days
            if days<=90:
                act_90+=1
            elif days<=180:
                act_180+=1
    events_df = events_df.append({
        "acc_id": account,
        "opp_id":  opportunity,
        "opp_date" : dat,
        "act_90" :  act_90,
        "act_180" : act_180,    
      }, ignore_index=True)

最后,我做了一个merge()介于机会和这个新的df之间。当然,手术需要很长时间。然而,我不知道如何改善这一点。你知道吗

主要的问题是,我需要在Opportunity中插入一些统计信息,这些统计信息需要来自Opportunity和Activity的数据,但我无法事先将它们合并,因为对于每个Opportunity,我要考虑的活动不止一个(而且在有重复项的情况下,不能执行左联接)

你知道吗?谢谢!你知道吗


编辑1

如果这是我的机会表:

    opp_date    acc_id  opp_id
0   05.08.2019  acc1    opp1
1   25.03.2019  acc2    opp2
2   27.08.2019  acc1    opp3
3   02.09.2019  acc1    opp4
4   22.07.2019  acc3    opp5

这是我的活动表:

    acc_id  act_date
0   acc1    25.07.2019
1   acc1    26.07.2019
2   acc1    31.07.2019 
3   acc1    28.07.2019
4   acc1    02.09.2019 
5   acc1    02.09.2019 
6   acc1    31.07.2019 
7   acc1    02.09.2019 
8   acc1    24.07.2019 
9   acc1    25.07.2019 
10  acc2    31.03.2019 
11  acc3    31.07.2019 
12  acc2    24.03.2019 
13  acc3    13.05.2019 
14  acc3    05.02.2019
15  acc3    30.05.2016 
16  acc3    30.11.2017 
17  acc3    11.04.2016 
18  acc3    19.01.2018 
19  acc3    19.01.2018 
20  acc2    24.03.2019 
21  acc1    04.08.2019
22  acc1    20.10.2019

则预期输出为:

    opp_date        acc_id  opp_id      act_90  act_180
0   05.08.2019      acc1    opp1        4       4   
1   25.03.2019      acc2    opp2        0       0   
2   27.08.2019      acc1    opp3        7       8   
3   02.09.2019      acc1    opp4        0       0   
4   22.07.2019      acc3    opp5        2       2   

Tags: iddfdateindexdaysact机会row
1条回答
网友
1楼 · 发布于 2024-05-18 21:23:21

您可以使用一些pandas内置函数来代替for循环。这个结果与您在问题中发布的“预期输出”有点不同,但我认为它符合您的描述。你知道吗

让我们调用第一个数据帧df1和第二个数据帧df2
我们可以通过将其写为函数并apply-遍历它来计算符合您的条件的活动数,而不是对行进行迭代:

def count_activities(row, act_df, days):
    return (act_df['act_date'].between(row['opp_date'] -pd.Timedelta(days=days), row['opp_date']) 
            & (act_df['acc_id']==row['acc_id'])).sum()

因为我们在上面的函数中进行计数,所以连接不是问题:

def add_count_activities_column(opp_df, act_df, days):
    return opp_df.join(opp_df.apply(lambda row: count_activities(row,act_df,days), axis=1).rename('act_{}'.format(days)))

结果是:

df3 = add_count_activities_column(df1, df2, 90)
df3 = add_count_activities_column(df3, df2, 180)

我的df3

    opp_date    acc_id  opp_id  act_90  act_180
0   2019-05-08  acc1    opp1    4   4
1   2019-03-25  acc2    opp2    2   2
2   2019-08-27  acc1    opp3    7   8
3   2019-02-09  acc1    opp4    3   3
4   2019-07-22  acc3    opp5    2   2

我会用opp_id作为索引,用df1.set_index('opp_id', inplace=True)。你知道吗

相关问题 更多 >

    热门问题