Python Pandas,如何避免使用iterrow(如何根据另一个数据帧中的值为数据帧中的新列赋值)
我有三个不同的实体:机会,账户,活动 我需要以一种特殊的方式将它们结合起来。让我解释一下它们之间的关系:Python Pandas,如何避免使用iterrow(如何根据另一个数据帧中的值为数据帧中的新列赋值),python,pandas,merge,iteration,left-join,Python,Pandas,Merge,Iteration,Left Join,我有三个不同的实体:机会,账户,活动 我需要以一种特殊的方式将它们结合起来。让我解释一下它们之间的关系: 机会N-1客户 账户1-N活动 另外,值得注意的是 Opportunity具有以下字段:{opp\u id;opp\u date;acc\u id} 活动具有以下字段:{act\u id;act\u date;acc\u id} 我想要实现的是,在Opportunity中插入Opportunity日期前X天完成的活动数量 我现在是这样做的: a_new_df = pd.DataFra
- 机会N-1客户
- 账户1-N活动
- Opportunity具有以下字段:
{opp\u id;opp\u date;acc\u id}
- 活动具有以下字段:
{act\u id;act\u date;acc\u id}
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)
这是我的活动表:
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
则预期输出为:
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
您可以使用一些内置函数来代替for循环。这个结果与您在问题中发布的“预期输出”略有不同,但我认为它符合您的描述 让我们调用第一个数据帧
df1
,然后调用第二个数据帧df2
我们可以通过将其写为函数并应用它(而不是在行上迭代)来计算符合您条件的活动数:
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
p、 我会使用
opp\u id
作为索引,使用df1。set\u index('opp\u id',inplace=True)
你能添加一些虚拟数据和它的输出吗?我相信你的代码中也有一些拼写错误(最后几行:accout
,opportunity
)。完成了,不容易,但完成了;)谢谢你给我看打字错误!在预期输出中,为什么第二行有0?acc2在该日期前一天执行了两个操作。一个操作在opportunity日期之后,而第二个操作返回0作为天,可能是因为一些近似值。这至少快了50倍,不,我不想检查确切的比率。谢谢!有没有关于如何改进标题的建议,以便其他用户可以找到这个问题?类似于“如何根据另一个数据帧中的值为数据帧中的新列赋值”这样的建议?