¿Cómo puedo lograr los equivalentes de SQL IN
y NOT IN
?
Tengo una lista con los valores requeridos. Aquí está el escenario:
df = pd.DataFrame({'countries':['US','UK','Germany','China']})
countries = ['UK','China']
# pseudo-code:
df[df['countries'] not in countries]
Mi forma actual de hacer esto es la siguiente:
df = pd.DataFrame({'countries':['US','UK','Germany','China']})
countries = pd.DataFrame({'countries':['UK','China'], 'matched':True})
# IN
df.merge(countries,how='inner',on='countries')
# NOT IN
not_in = df.merge(countries,how='left',on='countries')
not_in = not_in[pd.isnull(not_in['matched'])]
Pero esto parece un horrible error. ¿Alguien puede mejorarlo?
python
pandas
dataframe
sql-function
LondonRob
fuente
fuente
Respuestas:
Puedes usar
pd.Series.isin
.Para uso "IN":
something.isin(somewhere)
O para "NO EN":
~something.isin(somewhere)
Como ejemplo trabajado:
fuente
isin
se agregó en .13.df = pd.Series({'countries':['US','UK','Germany','China']})
df
, tanto el mío como el suyo, es aDataFrame
.countries
es una listadf[~df.countries.isin(countries)]
produce aDataFrame
, no aSeries
, y parece funcionar incluso en 0.11.0.dev-14a04dd.countries
variable. Bueno, el OP lo hace, y eso se hereda, pero que algo se haga mal antes no justifica hacerlo mal ahora.Solución alternativa que utiliza el método .query () :
fuente
query
ya no es experimental.Pandas ofrece dos métodos:
Series.isin
yDataFrame.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.Series.isin
acepta varios tipos como entradas. Las siguientes son formas válidas de obtener lo que desea: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,
Para aplicar la
isin
condición a ambas columnas "A" y "B", useDataFrame.isin
:A partir de esto, para retener filas donde está al menos una columna
True
, podemos usar a loany
largo del primer eje:Tenga en cuenta que si desea buscar en cada columna, simplemente omita el paso de selección de columna y haga
Del mismo modo, para retener las filas donde están TODAS las columnas
True
, úselasall
de la misma manera que antes.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
.¿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.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!fuente
Por lo general, he estado haciendo filtros genéricos sobre filas como esta:
fuente
Quería filtrar las filas dfbc que tenían un BUSINESS_ID que también estaba en el BUSINESS_ID de dfProfilesBusIds
fuente
Recopilando posibles soluciones a partir de las respuestas:
Para IN:
df[df['A'].isin([3, 6])]
Para NO EN:
df[-df["A"].isin([3, 6])]
df[~df["A"].isin([3, 6])]
df[df["A"].isin([3, 6]) == False]
df[np.logical_not(df["A"].isin([3, 6]))]
fuente
logical_not
es un equivalente bocado del~
operador.implementar en :
implementar no como en el resto de países:
fuente