2017-08-15 36 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'更快的解決方案嗎? –