2017-07-26 4 views
0

Ich habe einen Datenrahmen, die etwa wie folgt aussieht:Complex Pandas Dataframe Manipulation

import pandas as pd 
df= pd.DataFrame({'ID1':['A','B','C','D','E'],\ 
        'ID2':['B','A','D','C','E'],\ 
        'Account':['94000','94500','94000','18300','94500'],\ 
        'Amount':[100,-100,50,-50,100],\ 
        'Match':['-','-','-','-','-']}) 
df 

ich mit der effizientesten Art und Weise bin kämpfen, um zu identifizieren, wenn ein Element in ‚ID1‘ vorhanden ist in ‚ID2‘ mit einem bestimmter Wert von Konto. Zum Beispiel mit einer Bedingung Konto sollte = 94500 ergeben:

df= pd.DataFrame({'ID1':['A','B','C','D','E'],\ 
        'ID2':['B','A','D','C','E'],\ 
        'Account':['94000','94500','94000','18300','94500'],\   'Amount':[100,-100,50,-50,200],'Match':['True','-','-','-','-']}) 
df 

also nur die erste Zeile markiert werden soll, weil A (in ID2) Konto 94500

+0

funktioniert es nicht unter dem leicht modifizierten Datensatz, den ich gepostet habe –

+0

In Ihrem aktualisierten Beispiel E in 94500 und ID2 entspricht E in ID1, so dass die letzte Zeile auch True sein sollte, nein? – omdv

Antwort

2

Ihre Erklärung ist ein wenig unklar, aber ich glaube, Sie wollen dies:

mask = df[df.Account == '94500'].ID2 
df.loc[df.ID1.isin(mask),"Match"] = True 

    Account Amount ID1 ID2 Match 
0 94000  100 A B True 
1 94500 -100 B A  - 
2 94000  50 C D  - 
3 18300  -50 D C  - 
4 94500  100 E E True 

Vergleich auch beide richtige Antworten nur so zum Spaß.

%timeit -r 10 df['Match'] = df['ID1'].apply(lambda x: any((df['ID2']==x) & (df['Account']=='94500'))) 
100 loops, best of 10: 4.21 ms per loop 


%timeit -r 10 df.loc[df.ID1.isin(df[df.Account == '94500'].ID2),"Match"] = True 
1000 loops, best of 10: 1.48 ms per loop 

-Update einen neuen Anwendungsfall

Sie haben erwähnt, zu adressieren, dass Sie Probleme haben, wo es zwei Spalten, die Sie verwenden möchten. Wieder bin ich mir nicht sicher, ob ich es richtig verstanden habe, aber hier ist meine Meinung dazu. Angenommen, Sie haben eine andere Variable Prod und Sie möchten beide auf Account == 94500 und Prod == 6901 auswählen.

In diesem Fall:

df= pd.DataFrame({'ID1':['A','B','C','D','E'],\ 
        'ID2':['B','A','D','C','E'],\ 
        'Account':['94000','94500','94000','18300','94500'],\ 
        'Amount':[100,-100,50,-50,100],\ 
        'Match':['-','-','-','-','-'],\ 
        'Prod':[0,6901,0,0,0] 
       }) 

mask = df[(df.Account == '94500') & (df.Prod == 6901)].ID2 
df.loc[df.ID1.isin(mask),"Match"] = True 

Ergebnis:

Account Amount ID1 ID2 Match Prod 
0 94000  100 A B True  0 
1 94500 -100 B A  - 6901 
2 94000  50 C D  -  0 
3 18300  -50 D C  -  0 
4 94500  100 E E  -  0 

jetzt nur in ID1 'A' die Bedingung erfüllt, da 'A' in ID2 in 2. Reihe ist, so wird nur die erste Zeile ist ausgewählt.

+0

Ich stolperte, als ich versuchte, Ihren Code in einem etwas anderen Szenario zu verwenden. Wenn ich eine andere Spalte namens "Prod" habe und ich nun basierend auf beiden Konten 94500 und Prod 6901 übereinstimmen möchte, kann ich den Code nicht zum Funktionieren bringen! Pandas importieren als PD df = pd.DataFrame ({'ID1': ['A', 'B', 'C', 'D', 'E'], \ 'ID2': ['B' , 'A', 'D', 'C', 'E'], \ 'Konto': ['94000', '94500', '94000', '18300', '94500'], \ 'Prod ': [' 6901 ',' 0 ',' 0 ',' 0 ',' 0 '], \ ' Betrag ': [100, -100,50, -50,100], \ ' Übereinstimmung ': [' - ',' - ',' - ',' - ',' - ']}) df –

+0

Ich stolperte, als ich versuchte, Ihren Code in einem etwas anderen Szenario zu verwenden. Wenn ich eine andere Spalte namens "Prod" habe und ich nun basierend auf beiden Konten 94500 und Prod 6901 übereinstimmen möchte, kann ich den Code nicht zum Funktionieren bringen! df = pd.Datenrahmen ({'ID1': ['A', 'B', 'C', 'D', 'E'], 'ID2': ['B', 'A', 'D', 'C', "E"], "Konto": ["94000", "94500", "94000", "18300", "94500"], "Prod": ["6901", "0", "0", "0 ',' 0 '],' Betrag ': [100, -100,50, -50,100],' Übereinstimmung ': [' - ',' - ',' - ',' - ',' - ']}) . Es sollte keine Übereinstimmungen mit einem Prod von 6901 und einem Konto von 94500 geben –

+0

Changed die Bedingung, um Ihren Fall zu adressieren, wenn ich es richtig verstanden habe. – omdv

2

Spiele können Sie verwenden Pandas apply:

df['Match'] = df['ID1'].apply(lambda x: any((df['ID2']==x) & (df['Account']=='94500'))) 

Welche gibt:

Account Amount ID1 ID2 Match 
0 94000  100 A B True 
1 94500 -100 B A False 
2 94000  50 C D False 
3 18300  -50 D C False 
4 94500  100 E E True 

In Worten ist die Logik: „Für jedes Element in ID1 (apply), ob es zumindest (any) eine Zeile des Datenrahmen, wo ID2 = ID1 und Account = 94500“