2017-08-15 1 views
3

Mein Ziel ist es, die Pandas Äquivalent der unter R Code zu erhalten:Pandas/Python Äquivalent von komplexen ifelse Spiel in R

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

Wenn der Wert in der n-ten Reihe der Spalte String_1 von DF1 die erste Spalte entspricht von df2, wobei die nte Zeile der Spalte String_2 von df1 mit String_2 von df2 übereinstimmt, dann True in einer neuen Spalte String_1_check, sonst False in String_1_check.

df1 hat viele Instanzen der gleichen Werte in String_1 und String_2, und df2 hat nur eine Instanz jedes möglichen Werts in String_1. String_3 ist nicht eindeutig. Mit diesem Beispieldatenrahmen:

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 

Die gewünschte Ausgabe wäre:

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 

ich np.where versucht habe, isin, pd.match (veraltete jetzt), aber noch keine Lösung gefunden.

Antwort

1

Sie können map verwenden, ohne die Reihenfolge der ursprünglichen df ändern

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

Dies endete am besten für meine reale Datensituation. Vielen Dank! –

1

Zusammenführen der beiden Datenrahmen und prüfen, ob Strings 1 und 3 Spiel (herausgegeben einen Vorschlag von AChampion zu übernehmen):

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

Ich war auch mit merge versucht, aber beachten Sie, dass es um die Reihenfolge der df1 verliert. Ich weiß nicht, ob es wichtig ist. – ayhan

+0

Zeilen können bei Bedarf in beliebiger Reihenfolge sortiert werden. – DyZ

+1

Sie können die Reihenfolge beibehalten, wenn Sie 'df1.merge (df2, how = 'left')', also 'df1 ['String_1_check'] == df1.merge (df2, how = 'left') ['String_3' ] == df1 ['String_1'] ', ist gleichbedeutend mit dem ursprünglichen' R' Code, der das Ergebnis zurück zu 'df1' zugewiesen hat. – AChampion

5

Zuweisen des Werts zurück zu df1 wie das Original R können Sie tun:

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

Unter der Annahme, df2.String_3 ist einzigartig, schaffen eine Reihe von df2 und es in einem map verwenden gegen df1.String_2 zu vergleichen. Dies wird schnell sein unter Berücksichtigung map ist konstante Zeit nachschlagen im Vergleich zu merge.

Für den Fall, dass df2.String_3nicht eindeutig zuzuordnen sind, feststellen, dass OP erfordert, dass wir uns nur mit der Reihe betreffen, in dem wir das erste Spiel von df1.String_1 finden. Das heißt, wir df2.String_3 einzigartig unter Verwendung 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 

Modifizierte Version für Nicht-Eindeutigkeit

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

Verwenden pd.DataFrame.assign machen können eine Kopie df1 zu erstellen, die eine neue Spalte enthält.

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 

Zeit
In dieser Simulation Größe df2 ist statisch. Ich hatte keine Lust, einzigartige Werte zu modellieren.
Code unten

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

Ich wusste, dass "merge" nicht schnell sein würde - interessanterweise habe ich meine 'map' in umgekehrter Richtung erstellt;)' df1 ['String_2']. Map (df2.set_index ('String_2') ['String_3']) = = df1 ['String_1'] '- dasselbe Ergebnis. +1 – AChampion

+0

Ich nahm auch Freiheiten mit Ihrer Funktion und benutzte 'eval'. Das ist ein Leistungs-Handicap mit kleineren Daten und vorteilhaft bei größeren Daten. Aber es ist hübscher, wenn es in einem 'Lambda' verpackt ist. – piRSquared

+0

Ich mag das wirklich. Leider sind die Werte in String_3 nicht eindeutig. Ich habe meine Frage bearbeitet, um das zu reflektieren. Entschuldigung für jede Verwirrung. Hast du eine andere Lösung, die schneller ist als 'merge'? –