2017-12-28 13 views
-1

Ich habe einen Datenrahmen, der wie diesePandas Spalte mit einer anderen Liste Vergleich

item1 = {'category':'food::cafe::restaurant::business', 'name':'Bob Cafe'} 
item2 = {'category':'food::take away::restaurant::business', 'name':'John Take Away'} 
item3 = {'category':'cafeteria::business', 'name':'Annie Cafe'} 
item4 = {'category':'hotel::business', 'name':'Premier Inn'} 
df = pd.DataFrame([item1, item2, item3, item4]) 
lookup_table = ['cafe', 'cafeteria', 'restaurant'] 

ich eine neue Spalte in der DF erstellen möge sieht (Ja/Nein), der die Kategorie Spalte mit dem lookup_table übereinstimmt. Die Kategoriespalte muss durch '::' geteilt werden, um einzelne Kategorien zu erhalten und diese mit den verschiedenen Werten in der Liste zu vergleichen. Im obigen Beispiel sollte alles außer item4 True sein.

Ich möchte nicht jedes einzelne Element in der Spalte df.category durchlaufen und prüfen, ob es in der Tabelle vorhanden ist. Ich bin relativ neu zu Python .... so mehr als die Lösung, ich bin scharf auf den Denkprozess für die Lösung dieser "Python" Weg.

dank

Antwort

1

Option 1
str.contains

m = df.category.str.contains('|'.join(lookup_table)) 
df['Yes/No'] = np.where(m, 'Yes', 'No') 

df  
           category   name Yes/No 
0  food::cafe::restaurant::business  Bob Cafe Yes 
1 food::take away::restaurant::business John Take Away Yes 
2     cafeteria::business  Annie Cafe Yes 
3      hotel::business  Premier Inn  No 

nur ein "RegexMuster" passieren durch die Rohrleitung jeder Saite in lookup_table zu str.contains gebildet. Eine Maske wird dann zurückgegeben (basierend darauf, ob eine der Kategorien in der Zeile übereinstimmte). Diese Maske wird unter Verwendung der np.where in Yes/No Antworten konvertiert.


Option 2
str.split + isin + any

m = df.category.str.split('::', expand=True).isin(lookup_table).any(1) 
df['Yes/No'] = np.where(m, 'Yes', 'No') 

df  
           category   name Yes/No 
0  food::cafe::restaurant::business  Bob Cafe Yes 
1 food::take away::restaurant::business John Take Away Yes 
2     cafeteria::business  Annie Cafe Yes 
3      hotel::business  Premier Inn  No 

ähnlich wie bei der Option oben, aber das ist reines String-Matching, nicht Regex Matching. Unter Ausnutzung Ihrer Daten auf :: (Doppel Doppelpunkte) aufgeteilt, die in einem Datenrahmen ergibt sich wie folgt aussehen -

i = df.category.str.split('::', expand=True) 
i 
      0   1   2   3 
0  food  cafe restaurant business 
1  food take away restaurant business 
2 cafeteria business  None  None 
3  hotel business  None  None 

Nun rufen df.isin, die Durchführung einer „ist gleich?“ Überprüfen Sie jede Zeichenfolge in lookup_table. Daraus ergibt sich -

j = i.isin(lookup_table) 

     0  1  2  3 
0 False True True False 
1 False False True False 
2 True False False False 
3 False False False False 

Der nächste Schritt ist die Reihen haben diese Kategorie in jede Spalte zu finden ... so ... any verwenden.

j.any(axis=1) 

0  True 
1  True 
2  True 
3 False 
dtype: bool 

nach wie vor diese Maske zu Yes/No Antworten umgewandelt wird mit np.where, aber es gibt auch andere Möglichkeiten, dies zu tun (wie replace/str.replace).


Timings

df = pd.concat([df] * 100000, ignore_index=True) 

%%timeit 
m = df.category.str.contains('|'.join(lookup_table)) 
np.where(m, 'Yes', 'No') 

1 loop, best of 3: 536 ms per loop 

%%timeit 
m = df.category.str.split('::', expand=True).isin(lookup_table).any(1) 
df['Yes/No'] = np.where(m, 'Yes', 'No') 

1 loop, best of 3: 2.31 s per loop 

Ergebnisse für Ihre Daten, und für die Anzahl der Elemente invariieren kann.

+0

Fantastisch - danke viel coldspeed. Lässt Sie die Sprache noch mehr schätzen. – user2097496

+0

Vergessen zu erwähnen, meine Datenmenge ist riesig (> 20mn Reihen) ..... irgendwelche Kommentare zur Leistung gegen einen so großen Datensatz für die 2 Optionen? – user2097496

+0

@ user2097496 gute Frage. Die Antwort würde basierend auf Ihren Daten variieren, aber ich bin bereit zu wetten, dass die erste Option mehr _effizient_ ist, weil sie Ihre Spalte nicht wie die zweite erweitert. Wenn Sie interessiert sind, erstelle ich einige Testdaten und Zeit. –

Verwandte Themen