2017-08-15 33 views
3

我的目标是让大熊猫相当于下面的R代码里面的:熊猫/ Python的等效复ifelse比赛中的R

df1$String_1_check = ifelse(df1$String_1 == df2[match(df1$String_2, df2$String_2), 1], TRUE, FALSE) 

如果DF1的列STRING_1的第n行的值等于第一列df2的第n列第2行与df2的第2个字符串匹配,则在新列中为True,否则为String_1_check中的False。

df1在String_1和String_2中有许多相同值的实例,并且df2仅在String_1中具有每个可能值的一个实例。 String_3不是唯一的。与这些样品dataframes:

df1 = pd.DataFrame({'String_1': ['string 1', 'string 1', 'string 2', 'string 3', 'string 1'], 'String_2': ['string a', 'string a', 'string b', 'string a', 'string c']}) 
df2 = pd.DataFrame({'String_3': ['string 1', 'string 2', 'string 3'], 'String_2': ['string a', 'string b', 'string c']}) 

    String_1 String_2 
0 string 1 string a 
1 string 1 string a 
2 string 2 string b 
3 string 3 string a 
4 string 1 string c 

    String_3 String_2 
0 string 1 string a 
1 string 2 string b 
2 string 3 string c 

所需的输出将是:

String_1 String_2 String_1_check 
0 string 1 string a True 
1 string 1 string a True 
2 string 2 string b True 
3 string 3 string a False 
4 string 1 string c False 

我试图np.whereisinpd.match(废弃),但还没有找到一个解决方案。

回答

1

可以使用map没有改变原来的df

df1['String_1_check']=list(zip(df1['String_1'],df1['String_2'])) 
df2.index=list(zip(df2['String_3'],df2['String_2'])) 
df2['Check']=True 
df1['String_1_check']=df1['String_1_check'].map(df2['Check']).fillna(False) 

Out[764]: 
    String_1 String_2 String_1_check 
0 string 1 string a   True 
1 string 1 string a   True 
2 string 2 string b   True 
3 string 3 string a   False 
4 string 1 string c   False 
顺序
+1

这最终为我的真实数据情况提供了最好的工作。谢谢! –

1

合并两个dataframes并检查是否串1和3的比赛(编辑以纳入AChampion建议):

dfnew = df1.merge(df2, how='left') 
dfnew["String_1_check"] = (dfnew.String_1 == dfnew.String_3) 
del dfnew["String_3"] 
print(dfnew) 
# String_1 String_2 String_1_check 
#0 string 1 string a   True 
#1 string 1 string a   True 
#2 string 3 string a   False 
#3 string 2 string b   True 
#4 string 1 string c   False 
+0

我也试图合并,但请注意,它失去DF1的顺序。不知道它是否重要。 – ayhan

+0

如有必要,行可以按任意顺序排序。 – DyZ

+1

如果您执行了'df1.merge(df2,how ='left')',那么您可以保留该顺序,所以'df1 ['String_1_check'] == df1.merge(df2,how ='left')['String_3' ] == df1 ['String_1']',相当于原来的'R'代码,它将结果返回给'df1' – AChampion

5

将数值指定回df1,就像原来的R一样:

In []: 
df1['String_1_check'] = df1.merge(df2, how='left')['String_3'] == df1['String_1'] 
df1 

Out: 
    String_1 String_2 String_1_check 
0 string 1 string a   True 
1 string 1 string a   True 
2 string 2 string b   True 
3 string 3 string a   False 
4 string 1 string c   False 
1

假设df2.String_3是唯一的,请从df2中创建一个系列,并将其用于mapdf1.String_2进行比较。考虑到map是恒定时间查找,与merge相比,这将很快。

在这种df2.String_3独特的事件,注意到OP要求我们只与中,我们发现从df1.String_1的第一个匹配的行假惺惺。这意味着我们可以通过使用drop_duplicates

df1.String_1.map(df2.set_index('String_3').String_2).eq(df1.String_2) 

0  True 
1  True 
2  True 
3 False 
4 False 
dtype: bool 

改良版的非唯一性

df1.String_1.map(
    df2.drop_duplicates('String_3').set_index('String_3').String_2 
).eq(df1.String_2) 

使用pd.DataFrame.assign创建的df1副本,其中包括一个新列作df2.String_3独特。

df1.assign(
    String_1_check=df1.String_1.map(
     df2.drop_duplicates('String_3').set_index('String_3').String_2 
    ).eq(df1.String_2) 
) 

    String_1 String_2 String_1_check 
0 string 1 string a   True 
1 string 1 string a   True 
2 string 2 string b   True 
3 string 3 string a   False 
4 string 1 string c   False 

时序
在该仿真中,df2大小是静态的。我不想模拟独特的价值观。
下面的代码

enter image description here

pir = lambda df1, df2: df1.assign(String_1_check=df1.String_1.map(df2.drop_duplicates('String_3').set_index('String_3').String_2).eq(df1.String_2)) 
achamp = lambda df1, df2: df1.assign(String_1_check=df1.merge(df2, how='left').eval('String_3 == String_1')) 

results = pd.DataFrame(
    index=pd.Index([10, 30, 100, 300, 1000, 3000, 10000, 30000]), 
    columns='pir achamp'.split() 
) 

for i in results.index: 
    d1 = pd.concat([df1] * i, ignore_index=True) 
    for j in results.columns: 
     stmt = '{}(d1, df2)'.format(j) 
     setp = 'from __main__ import d1, df2, {}'.format(j) 
     results.set_value(i, j, timeit(stmt, setp, number=20)) 

results.plot(loglog=True) 
+1

我知道'merge'不会很快 - 有趣的是我建立了我的'map'反向;''df1 ['String_2']。map(df2.set_index('String_2')['String_3'])= = df1 ['String_1']' - 相同的结果。 +1 – AChampion

+0

我也为你的功能自由了,并使用了'eval'。这是一个性能障碍,数据量小,数据量大。但是当用'lambda'包装时它更漂亮。 – piRSquared

+0

我真的很喜欢这个。不幸的是,String_3中的值不是唯一的。我编辑了我的问题来反映这一点。对不起,有任何困惑。你有另一种比'merge'更快的解决方案吗? –