Come implementare 'in' e 'non in' per un DataFrame Panda?
Pandas offre due metodi: Series.isin
e rispettivamente DataFrame.isin
per Series e DataFrames.
Filtra DataFrame in base a UNA colonna (vale anche per le serie)
Lo scenario più comune è l'applicazione di una isin
condizione su una colonna specifica per filtrare le righe in un DataFrame.
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
accetta vari tipi come input. Di seguito sono riportati tutti i modi validi per ottenere ciò che desideri:
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
# Filter with `set` (tuples work too)
df[df['countries'].isin(c2)]
countries
2 Germany
# Filter with another Series
df[df['countries'].isin(c3)]
countries
0 US
4 China
# Filter with array
df[df['countries'].isin(c4)]
countries
0 US
1 UK
Filtro su MOLTE colonne
A volte, ti consigliamo di applicare un controllo di appartenenza "in" con alcuni termini di ricerca su più colonne,
df2 = pd.DataFrame({
'A': ['x', 'y', 'z', 'q'], 'B': ['w', 'a', np.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']
Per applicare la isin
condizione a entrambe le colonne "A" e "B", utilizzare DataFrame.isin
:
df2[['A', 'B']].isin(c1)
A B
0 True True
1 False False
2 False False
3 False True
Da questo, per conservare le righe in cui si trova almeno una colonnaTrue
, possiamo usare any
lungo il primo asse:
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
Nota che se vuoi cercare in ogni colonna, dovresti semplicemente omettere il passaggio di selezione della colonna e farlo
df2.isin(c1).any(axis=1)
Allo stesso modo, per conservare le righe in cui si trovano TUTTE le colonneTrue
, utilizzare all
nello stesso modo di prima.
df2[df2[['A', 'B']].isin(c1).all(axis=1)]
A B C
0 x w 0
Notevole Menzioni: numpy.isin
, query
, list comprehension (string data)
Oltre ai metodi descritti in precedenza, è anche possibile utilizzare l'equivalente NumPy: 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
Perché vale la pena considerare? Le funzioni di NumPy sono in genere un po 'più veloci rispetto ai loro equivalenti panda a causa del sovraccarico inferiore. Dato che si tratta di un'operazione elementally che non dipende dall'allineamento dell'indice, ci sono pochissime situazioni in cui questo metodo non è un sostituto appropriato per i panda isin
.
Le routine di Panda sono generalmente iterative quando si lavora con le stringhe, poiché le operazioni sulle stringhe sono difficili da vettorializzare. Ci sono molte prove che suggeriscono che la comprensione dell'elenco sarà più veloce qui. . Facciamo ricorso a un in
assegno ora.
c1_set = set(c1) # Using `in` with `sets` is a constant time operation...
# This doesn't matter for pandas because the implementation differs.
# `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
È molto più ingombrante da specificare, tuttavia, quindi non usarlo se non sai cosa stai facendo.
Infine, c'è anche quello DataFrame.query
che è stato trattato in questa risposta . numexpr FTW!