Pandas,映射两个数据帧,根据条件计算

时间:2016-08-23 15:13:18

标签: python pandas dataframe

我编写了一些代码来映射两个数据帧的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可以多次包含样本ID,但值Tag

不同

(df1和df2是大型数据帧,df1为50,000行,df2为15,000)

1 个答案:

答案 0 :(得分:2)

您可以crosstab使用merge

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使用{{3}}:

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