¿Cómo implementar 'en' y 'no en' para un DataFrame de pandas?
Pandas ofrece dos métodos: Series.isin
y DataFrame.isin
para Series y DataFrames, respectivamente.
Filtrar marco de datos basado en UNA columna (también se aplica a la serie)
El escenario más común es aplicar una isin
condición en una columna específica para filtrar filas en 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
acepta varios tipos como entradas. Las siguientes son formas válidas de obtener lo que desea:
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
Filtrar en MUCHAS columnas
A veces, querrá aplicar una verificación de membresía 'in' con algunos términos de búsqueda en varias columnas,
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']
Para aplicar la isin
condición a ambas columnas "A" y "B", use DataFrame.isin
:
df2[['A', 'B']].isin(c1)
A B
0 True True
1 False False
2 False False
3 False True
A partir de esto, para retener filas donde está al menos una columnaTrue
, podemos usar a lo any
largo del primer eje:
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
Tenga en cuenta que si desea buscar en cada columna, simplemente omita el paso de selección de columna y haga
df2.isin(c1).any(axis=1)
Del mismo modo, para retener las filas donde están TODAS las columnasTrue
, úselas all
de la misma manera que antes.
df2[df2[['A', 'B']].isin(c1).all(axis=1)]
A B C
0 x w 0
Notable Menciones: numpy.isin
, query
, listas por comprensión (datos de cadena)
Además de los métodos descritos anteriormente, también se puede utilizar el 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
¿Por qué vale la pena considerarlo? Las funciones NumPy suelen ser un poco más rápidas que sus equivalentes pandas debido a una menor sobrecarga. Dado que esta es una operación de elementos que no depende de la alineación del índice, hay muy pocas situaciones en las que este método no sea un reemplazo apropiado para los pandas ' isin
.
Las rutinas de pandas suelen ser iterativas cuando se trabaja con cadenas, porque las operaciones de cadena son difíciles de vectorizar. Hay mucha evidencia que sugiere que las comprensiones de listas serán más rápidas aquí. . Recurrimos a un in
cheque ahora.
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
Sin embargo, es mucho más difícil de especificar, así que no lo use a menos que sepa lo que está haciendo.
Por último, también hay algo DataFrame.query
que se ha cubierto en esta respuesta . numexpr FTW!