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.
Fantastisch - danke viel coldspeed. Lässt Sie die Sprache noch mehr schätzen. – user2097496
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
@ 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. –