簡體   English   中英

Pandas,如何避免使用 iterrow(如何根據來自另一個數據幀的值將值分配給 dataframe 中的新列)

[英]Pandas, how can I avoid the use of iterrow (how to assign values to a new column in a dataframe based on the values from another dataframe)

我有三個不同的實體: OpportunityAccountActivity

我需要以一種特殊的方式將它們結合起來。 讓我解釋一下它們之間的關系:

  • 機會N-1帳戶
  • 帳戶1-N活動

另外,值得注意的是

  • 機會具有以下字段: { opp_id; opp_date; acc_id} { opp_id; opp_date; acc_id}
  • 活動具有以下字段: { act_id; act_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)

最后,我在Opportunity和這個新的 df之間做了一個merge() 當然,手術需要很長時間。 但是,我不知道如何改善這一點。

主要問題是我需要在 Opportunity 中插入一些統計信息,這些統計信息需要來自 Opportunity 和 Activity 的數據,但我不能事先合並它們,因為對於每個機會我有多個活動要考慮(而且你不能做左連接當您有重復項時)

任何想法? 非常感謝!


編輯 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

那么預期的 output 是:

    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 循環。 這個結果與您在問題中發布的“預期輸出”有點不同,但我認為它符合您的描述。

讓我們稱您的第一個 dataframe df1和您的第二個df2
我們可以通過將其寫為 function 並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()

由於我們在上面的 function 中進行了計數,因此加入不是問題:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM