我有三个不同的实体:机会,帐户,活动。
我需要以一种特殊的方式将它们结合起来。让我解释一下它们之间的关系:
机会N-1帐户
帐户1-N活动
另外,值得注意的是
机会包含以下字段:{ opp_id ; opp_date ; acc_id}
活动具有以下字段:{ act_id ; act_date ; acc_id }
我想实现的是,在商机日期之前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)
最后,我在机会和新的df之间做了一个
merge()
。当然,该操作需要永远的时间。但是,我不知道如何改善这一点。主要问题是,我需要向“机会”中插入一些统计信息,这些统计信息需要同时包含“机会”和“活动”中的数据,但是我无法事先合并它们,因为对于每个机会,我都有多个活动要考虑(并且您不能进行左联接当您有重复项时)
任何的想法?非常感谢!
编辑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
最佳答案
您可以使用某些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
ps。 -我会使用
opp_id
作为df1.set_index('opp_id', inplace=True)
的索引。