2016-08-23 133 views
1

我已經寫了一些代碼來映射兩個數據幀的ID,如果條件匹配,然後在現有數據幀的指定列中創建一個計數,我正在尋找一個更高效計算方法。熊貓,映射兩個數據幀,根據條件計數

樣本數據

import numpy as np 
import pandas as pd 
d = {'ID' : pd.Series([111, 222, 111, 444, 222, 111]), 'Tag' : pd.Series([1, 2, 3, 1, 2, 1])} 
df1 = (pd.DataFrame(d)) 
print(df1) 

    ID Tag 
0 111 1 
1 222 2 
2 111 3 
3 444 1 
4 222 2 
5 111 1 

d = {'ID' : pd.Series([111, 444, 666, 444, 777])} 
df2 = (pd.DataFrame(d)) 
print(df2)  
    ID 
0 111 
1 444 
2 666 
3 444 
4 777 

df2['tag1'] = 0 
df2['tag2'] = 0 
df2['tag3'] = 0 
​ 
for index, row in df2.iterrows(): 
    for i, t in df1.iterrows(): 
     if row['ID'] == t['ID']: 
      if t['Tag'] == 1: 
       df2.loc[index]["tag1"] += 1 
      elif t['Tag'] == 2: 
       df2.loc[index]["tag2"] += 1 
      elif t['Tag'] == 3: 
       df2.loc[index]["tag3"] += 1 

輸出

print(df2) 
    ID tag1 tag2 tag3 
0 111  2  0  1 
1 444  1  0  0 
2 666  0  0  0 
3 444  1  0  0 
4 777  0  0  0 

什麼是這樣做的,而不是反覆計算的最有效的方法是什麼?

注意,DF1可以與Tag不同的值ID多次包含樣品

(DF1和DF2大dataframes,在DF1 50,000行和DF2 15000)

回答

1

您可以使用crosstabmerge

print (pd.crosstab(df1.ID, df1.Tag)) 
Tag 1 2 3 
ID   
111 2 0 1 
222 0 2 0 
444 1 0 0 

print (pd.merge(df2, pd.crosstab(df1.ID, df1.Tag) 
         .add_prefix('tag') 
         .reset_index(), on='ID', how='left') 
     .fillna(0) 
     .astype(int)) 

    ID tag1 tag2 tag3 
0 111  2  0  1 
1 444  1  0  0 
2 666  0  0  0 
3 444  1  0  0 
4 777  0  0  0 

相反crosstab可以使用groupbysizeunstack

print (df1.groupby(['ID', 'Tag'])['Tag'].size().unstack()) 
Tag 1 2 3 
ID     
111 2.0 NaN 1.0 
222 NaN 2.0 NaN 
444 1.0 NaN NaN 

print (pd.merge(df2, df1.groupby(['ID', 'Tag'])['Tag'].size().unstack() 
         .add_prefix('tag') 
         .reset_index(), on='ID', how='left') 
     .fillna(0) 
     .astype(int)) 

    ID tag1 tag2 tag3 
0 111  2  0  1 
1 444  1  0  0 
2 666  0  0  0 
3 444  1  0  0 
4 777  0  0  0 
+0

感謝了迅速的回答@jezrael – user3939059

+0

很高興能幫助你,祝你好運! – jezrael