¿Cómo seleccionar filas de una DataFrame
base en valores en alguna columna en Python Pandas?
En SQL, usaría:
SELECT *
FROM table
WHERE colume_name = some_value
Traté de mirar la documentación de los pandas pero no encontré la respuesta de inmediato.
Respuestas:
Para seleccionar filas cuyo valor de columna sea igual a un escalar
some_value
, use==
:Para seleccionar filas cuyo valor de columna esté en un iterable
some_values
, useisin
:Combina múltiples condiciones con
&
:Tenga en cuenta los paréntesis. Debido a las reglas de precedencia del operador de Python , se
&
une con más fuerza que<=
y>=
. Por lo tanto, los paréntesis en el último ejemplo son necesarios. Sin los paréntesisse analiza como
lo que resulta en un valor de verdad de una serie es un error ambiguo .
Para seleccionar filas cuyo valor de columna no sea igual
some_value
, use!=
:isin
devuelve una serie booleana, por lo que para seleccionar filas cuyo valor no está ensome_values
, niegue la serie booleana usando~
:Por ejemplo,
rendimientos
Si tiene varios valores que desea incluir, colóquelos en una lista (o más generalmente, cualquier iterable) y use
isin
:rendimientos
Sin embargo, tenga en cuenta que si desea hacer esto muchas veces, es más eficiente hacer un índice primero y luego usar
df.loc
:rendimientos
o, para incluir múltiples valores del uso del índice
df.index.isin
:rendimientos
fuente
df.where(condition)
, la condición tiene que tener la misma forma quedf
.df[df['column_name'] == some_value]
funciona, ¿por qué necesitamos agregar.loc
aquí?Hay varias formas de seleccionar filas de un marco de datos de pandas:
df[df['col'] == value
])df.iloc[...]
)df.xs(...)
)df.query(...)
APIA continuación les muestro ejemplos de cada uno, con consejos sobre cuándo usar ciertas técnicas. Supongamos que nuestro criterio es la columna
'A'
=='foo'
(Nota sobre el rendimiento: para cada tipo de base, podemos simplificar las cosas mediante el uso de la API de pandas o podemos aventurarnos fuera de la API, por lo general
numpy
, y acelerar las cosas).Configuración
Lo primero que necesitaremos es identificar una condición que actuará como nuestro criterio para seleccionar filas. Comenzaremos con el caso del OP
column_name == some_value
e incluiremos algunos otros casos de uso comunes.Préstamo de @unutbu:
1. indexación booleana
... la indexación booleana requiere encontrar el valor verdadero de la
'A'
columna de cada fila que sea igual'foo'
, y luego usar esos valores de verdad para identificar qué filas mantener. Por lo general, nos nombramos esta serie, una serie de valores de verdad,mask
. Lo haremos aquí también.Entonces podemos usar esta máscara para cortar o indexar el marco de datos
Esta es una de las formas más simples de realizar esta tarea y si el rendimiento o la intuición no son un problema, este debería ser el método elegido. Sin embargo, si el rendimiento es una preocupación, es posible que desee considerar una forma alternativa de crear el
mask
.2. indexación posicional
La indexación posicional (
df.iloc[...]
) tiene sus casos de uso, pero este no es uno de ellos. Para identificar dónde dividir, primero debemos realizar el mismo análisis booleano que hicimos anteriormente. Esto nos deja realizando un paso adicional para lograr la misma tarea.3. Indización de etiquetas
La indexación de etiquetas puede ser muy útil, pero en este caso, nuevamente estamos haciendo más trabajo sin beneficio
4.
df.query()
APIpd.DataFrame.query
es una forma muy elegante / intuitiva de realizar esta tarea, pero a menudo es más lenta. Sin embargo , si presta atención a los tiempos a continuación, para datos grandes, la consulta es muy eficiente. Más que el enfoque estándar y de magnitud similar a mi mejor sugerencia.Mi preferencia es usar el
Boolean
mask
Se pueden hacer mejoras reales modificando cómo creamos nuestro
Boolean
mask
.mask
alternativa 1Use la
numpy
matriz subyacente y renuncie a la sobrecarga de crear otrapd.Series
Mostraré pruebas de tiempo más completas al final, pero solo eche un vistazo a las ganancias de rendimiento que obtenemos con el marco de datos de muestra. Primero, observamos la diferencia en la creación de
mask
Evaluar
mask
con elnumpy
conjunto es ~ 30 veces más rápido. Esto se debe en parte a que lanumpy
evaluación a menudo es más rápida. También se debe en parte a la falta de sobrecarga necesaria para construir un índice y unpd.Series
objeto correspondiente .A continuación, veremos el momento para cortar con uno
mask
versus el otro.Las ganancias de rendimiento no son tan pronunciadas. Veremos si esto se mantiene sobre pruebas más robustas.
mask
alternativa 2Podríamos haber reconstruido el marco de datos también. Hay una gran advertencia al reconstruir un marco de datos: debe tener cuidado
dtypes
al hacerlo.En lugar de
df[mask]
haremos estoSi el marco de datos es de tipo mixto, que es nuestro ejemplo, cuando obtengamos
df.values
la matriz resultante es dedtype
object
y, en consecuencia, todas las columnas del nuevo marco de datos serán dedtype
object
. Por lo tanto, requiereastype(df.dtypes)
y elimina cualquier ganancia potencial de rendimiento.Sin embargo, si el marco de datos no es de tipo mixto, esta es una forma muy útil de hacerlo.
Dado
Versus
Cortamos el tiempo a la mitad.
mask
La alternativa 3@unutbu también nos muestra cómo usar
pd.Series.isin
para dar cuenta de cada elemento dedf['A']
estar en un conjunto de valores. Esto evalúa lo mismo si nuestro conjunto de valores es un conjunto de un valor, a saber'foo'
. Pero también generaliza para incluir conjuntos de valores más grandes si es necesario. Resulta que esto sigue siendo bastante rápido, aunque es una solución más general. La única pérdida real está en la intuición para aquellos que no están familiarizados con el concepto.Sin embargo, como antes, podemos utilizar
numpy
para mejorar el rendimiento sin sacrificar prácticamente nada. Usaremosnp.in1d
El tiempo
incluiré otros conceptos mencionados en otras publicaciones también como referencia.
Código abajo
Cada columna en esta tabla representa un marco de datos de longitud diferente sobre el cual probamos cada función. Cada columna muestra el tiempo relativo tomado, con la función más rápida dada un índice base de
1.0
.Notarás que los tiempos más rápidos parecen ser compartidos entre
mask_with_values
ymask_with_in1d
Las funciones
Pruebas
Momento especial
Observando el caso especial cuando tenemos un único no objeto
dtype
para todo el marco de datos. Código abajoResulta que la reconstrucción no vale la pena más allá de unos cientos de filas.
Las funciones
Pruebas
fuente
.iloc(numpy.where(..))
compararía en este esquema? ii) ¿esperaría que las clasificaciones sean las mismas cuando se usan múltiples condiciones?pd.Series.isin
, tenga en cuenta que hace usonp.in1d
bajo el capó de un escenario específico, usos khash en otros, e implícitamente se aplica una solución de compromiso entre el coste de hash frente al rendimiento en situaciones específicas. Esta respuesta tiene más detalles.[{P|EXP}TIME]
- y[{C|P|EXP}SPACE]
- los costos de la utilización de las anteriores formas propuestas de bloque de sintaxis (el procesamiento de arriba hacia abajo las tramas de datos enteros a la vez) crecer , es decir, cuando escalado a algunos~1E6, ~1E9, ~1E12
recuentos de filas? Gracias por mostrarnos la imagen completa, señor. Lecturas de referencia cuantitativa con[min, Avg, MAX, StDev]
siempre son bienvenidos, ya que tanto elmin
yMAX
valores acompañan elMean/StDev
alivio del lote.tl; dr
Los pandas equivalentes a
es
Múltiples condiciones:
o
Ejemplo de código
En el código anterior, es la línea
df[df.foo == 222]
que proporciona las filas según el valor de la columna,222
en este caso.Múltiples condiciones también son posibles:
Pero en ese punto, recomendaría usar la función de consulta , ya que es menos detallada y produce el mismo resultado:
fuente
query
es la única respuesta aquí que es compatible con el método de encadenamiento. Parece que es el pandas análogo afilter
in dplyr.[
no corchetes(
en el exterior.|
era para AND, pero por supuesto es operador OR ...df[condition1][condition2]
df.query('`my col` == 124')
Encuentro que la sintaxis de las respuestas anteriores es redundante y difícil de recordar. Pandas introdujo el
query()
método en v0.13 y lo prefiero mucho. Para su pregunta, podría hacerdf.query('col == val')
Reproducido de http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query
También puede acceder a variables en el entorno anteponiendo un
@
.fuente
numexpr
instalado.Más flexibilidad
.query
conpandas >= 0.25.0
:Respuesta actualizada de agosto de 2019
Como
pandas >= 0.25.0
podemos usar elquery
método para filtrar marcos de datos con métodos pandas e incluso nombres de columnas que tienen espacios. Normalmente, los espacios en los nombres de columna darían un error, pero ahora podemos resolver eso usando un backtick (`) ver GitHub :Usando
.query
con el métodostr.endswith
:Salida
También podemos usar variables locales prefijándolas con un
@
en nuestra consulta:Salida
fuente
Se pueden lograr resultados más rápidos usando numpy.where .
Por ejemplo, con la configuración de unubtu :
Comparaciones de tiempo:
fuente
Aquí hay un ejemplo simple
fuente
Para seleccionar solo columnas específicas de varias columnas para un valor dado en pandas:
Opciones:
o
fuente
Para agregar a esta famosa pregunta (aunque un poco tarde): También puede
df.groupby('column_name').get_group('column_desired_value').reset_index()
hacer un nuevo marco de datos con una columna específica que tenga un valor particular. P.ejEjecute esto da:
fuente
get_group()
devolverá automáticamente un marco de datos. También puede decir "drop = True" como parámetro dereset_index()
. En otras palabras, se puede acortar a:b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
También puedes usar .apply:
Realmente funciona en fila (es decir, aplica la función a cada fila).
La salida es
Los resultados son los mismos que los mencionados en @unutbu.
fuente