Wie implementiert man 'in' und 'not in' für ein Pandas DataFrame?
Pandas bietet zwei Methoden: Series.isin
und DataFrame.isin
für Series und DataFrames.
Filtern des DataFrames basierend auf EINER Spalte (gilt auch für Series)
Das häufigste Szenario ist die Anwendung einer isin
-Bedingung auf eine bestimmte Spalte, um Zeilen in einem DataFrame zu filtern.
df = pd.DataFrame({'countries': ['US', 'UK', 'Germany', np.nan, 'China']})
df
countries
0 US
1 UK
2 Germany
3 China
c1 = ['UK', 'China'] # list
c2 = {'Germany'} # set
c3 = pd.Series(['China', 'US']) # Series
c4 = np.array(['US', 'UK']) # array
Series.isin
akzeptiert verschiedene Eingabetypen. Die folgenden sind alle gültige Arten, um das zu bekommen, was Sie wollen:
df['countries'].isin(c1)
0 False
1 True
2 False
3 False
4 True
Name: countries, dtype: bool
# `in` operation
df[df['countries'].isin(c1)]
countries
1 UK
4 China
# `not in` operation
df[~df['countries'].isin(c1)]
countries
0 US
2 Germany
3 NaN
# Filtern mit `set` (Tupel funktionieren ebenfalls)
df[df['countries'].isin(c2)]
countries
2 Germany
# Filtern mit einer weiteren Series
df[df['countries'].isin(c3)]
countries
0 US
4 China
# Filtern mit einem Array
df[df['countries'].isin(c4)]
countries
0 US
1 UK
Filtern auf VIELEN Spalten
Manchmal möchten Sie eine 'in'-Mitgliedschaftsprüfung mit einigen Suchbegriffen über mehrere Spalten anwenden,
df2 = pd.DataFrame({
'A': ['x', 'y', 'z', 'q'], 'B': ['w', 'a', 'NaN', 'x'], 'C': np.arange(4)})
df2
A B C
0 x w 0
1 y a 1
2 z NaN 2
3 q x 3
c1 = ['x', 'w', 'p']
Um die isin
-Bedingung auf die Spalten "A" und "B" anzuwenden, verwenden Sie DataFrame.isin
:
df2[['A', 'B']].isin(c1)
A B
0 True True
1 False False
2 False False
3 False True
Basierend darauf, um Zeilen zu behalten, in denen mindestens eine Spalte True
ist, können wir any
entlang der ersten Achse verwenden:
df2[['A', 'B']].isin(c1).any(axis=1)
0 True
1 False
2 False
3 True
dtype: bool
df2[df2[['A', 'B']].isin(c1).any(axis=1)]
A B C
0 x w 0
3 q x 3
Beachten Sie, dass wenn Sie in jeder Spalte suchen wollen, Sie einfach den Schritt zur Spaltenauswahl weglassen und machen Sie einfach
df2.isin(c1).any(axis=1)
Ebenso, um Zeilen zu behalten, in denen ALLE Spalten True
sind, verwenden Sie all
auf die gleiche Weise wie zuvor.
df2[df2[['A', 'B']].isin(c1).all(axis=1)]
A B C
0 x w 0
Erwähnenswert: numpy.isin
, query
, List Comprehensions (String-Daten)
Zusätzlich zu den oben beschriebenen Methoden können Sie auch das numpy-Äquivalent verwenden: numpy.isin
.
# `in` operation
df[np.isin(df['countries'], c1)]
countries
1 UK
4 China
# `not in` operation
df[np.isin(df['countries'], c1, invert=True)]
countries
0 US
2 Germany
3 NaN
Warum lohnt es sich, darüber nachzudenken? NumPy-Funktionen sind in der Regel etwas schneller als ihre Pandas-Äquivalente aufgrund eines geringeren Overheads. Da dies eine elementweise Operation ist, die nicht von der Indexausrichtung abhängt, gibt es sehr wenige Situationen, in denen diese Methode kein geeigneter Ersatz für das Pandas-isin
ist.
Pandas-Routinen sind in der Regel iterativ, wenn es um Strings geht, da Zeichenfolgenoperationen schwer zu vektorisieren sind. Es gibt viele Hinweise darauf, dass List Comprehensions hier schneller sein werden.. Wir greifen jetzt auf ein in
-Check zurück.
c1_set = set(c1) # Die Verwendung von `in` mit `Sets` ist eine Konstantzeitoperation...
# Das spielt für Pandas keine Rolle, da die Implementierung unterschiedlich ist.
# `in` operation
df[[x in c1_set for x in df['countries']]]
countries
1 UK
4 China
# `not in` operation
df[[x not in c1_set for x in df['countries']]]
countries
0 US
2 Germany
3 NaN
Es ist viel unhandlicher zu spezifizieren, also verwenden Sie es nicht, es sei denn, Sie wissen, was Sie tun.
Zuletzt gibt es auch DataFrame.query
, das in dieser Antwort behandelt wurde. Numexpr FTW!