62_Pandas extrae condicionalmente filas de pandas.DataFrame
Utilice el método query() para extraer filas en función de las condiciones de los valores de columna de un pandas.DataFrame. Es conveniente porque puede describir especificaciones condicionales de forma sucinta utilizando operadores de comparación y métodos de cadena, así como combinaciones de varias condiciones.
Tabla de contenido
- Usar operadores de comparación para especificar condiciones
- Use el operador in para la especificación condicional (equivalente a isin())
- Especificar condiciones con métodos de cadena
- Cuando faltan valores NaN o Ninguno
- condición de índice
- Especificar varias condiciones
- Encierre los nombres de las columnas que contengan espacios o puntos con "`"
- Actualizar el objeto original con el parámetro en el lugar
Para conocer la especificación de la condición del índice booleano, consulte el siguiente artículo.
La versión pandas del código de muestra de este artículo es la versión 2.0.3. Tenga en cuenta que el comportamiento puede variar según la versión.
import pandas as pd
print(pd.__version__)
# 2.0.3
df = pd.read_csv('data/sample_pandas_normal.csv')
print(df)
# name age state point
# 0 Alice 24 NY 64
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
# 4 Ellen 24 CA 88
# 5 Frank 30 NY 57
Usar operadores de comparación para especificar condiciones
En pandas, puede usar operadores de comparación para extraer filas así:
print(df[df['age'] < 25])
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
Se pueden especificar condiciones similares a través de cadenas usando el método query().
print(df.query('age < 25'))
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
Prefije un nombre de variable con @ para usar esa variable en una cadena de condición.
val = 25
print(df.query('age < @val'))
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
Los rangos se pueden especificar usando dos operadores de comparación, al igual que las especificaciones condicionales de Python.
print(df.query('30 <= age < 50'))
# name age state point
# 1 Bob 42 CA 92
# 5 Frank 30 NY 57
También puede comparar columnas y compararlas realizando cálculos utilizando operadores aritméticos.
print(df.query('age < point / 3'))
# name age state point
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
==, != indican coincidencia y no coincidencia. Tenga en cuenta que las cadenas en la cadena de condición deben estar entrecomilladas.
Las comillas dobles " se pueden usar en cadenas entre comillas simples ' y las comillas simples ' se pueden usar en cadenas entre comillas dobles ". Se puede usar la misma notación escapándola con una barra invertida \.
print(df.query('state == "CA"'))
# name age state point
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
No se preocupe por las comillas cuando use variables.
s = 'CA'
print(df.query('state != @s'))
# name age state point
# 0 Alice 24 NY 64
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57
Use el operador in para la especificación condicional (equivalente a isin())
isin() es un método que devuelve bool (Verdadero, Falso) para determinar si el elemento de la columna (pandas.Series) está contenido en la lista de parámetros. Esto se puede usar para extraer filas donde los elementos en una columna coinciden con un valor específico.
print(df[df['state'].isin(['NY', 'TX'])])
# name age state point
# 0 Alice 24 NY 64
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57
El equivalente se puede hacer usando in en el método query().
print(df.query('state in ["NY", "TX"]'))
# name age state point
# 0 Alice 24 NY 64
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57
Como uso especial, == para listas se maneja de la misma manera.
print(df.query('state == ["NY", "TX"]'))
# name age state point
# 0 Alice 24 NY 64
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57
También puede utilizar variables de lista.
l = ['NY', 'TX']
print(df.query('state in @l'))
# name age state point
# 0 Alice 24 NY 64
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57
Especificar condiciones con métodos de cadena
Las condiciones para la coincidencia de cadena completa se pueden especificar usando == o arriba, pero las condiciones de coincidencia parcial se pueden especificar usando los métodos de cadena str.xxx().
Consulte el siguiente método:
- str.contains(): contiene una cadena específica
- str.endswith(): termina con una cadena específica
- str.startswith(): comienza con una cadena específica
- str.match(): Coinciden con patrones de expresiones regulares.
También se pueden usar en query(), aunque no son más compactos que la indexación booleana.
print(df.query('name.str.endswith("e")'))
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
print(df.query('name.str.contains("li")'))
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
Los métodos de cadena se pueden usar convirtiendo una columna de tipo dtype que no sea cadena a cadena de tipo str usando astype(). Esto también se puede especificar con query().
print(df.query('age.astype("str").str.endswith("8")'))
# name age state point
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
Cuando faltan valores NaN o Ninguno
Tenga en cuenta que si usa métodos de cadena como condiciones para columnas con valores faltantes NaN o Ninguno, obtendrá un error.
df.at[0, 'name'] = None
print(df)
# name age state point
# 0 None 24 NY 64
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
# 4 Ellen 24 CA 88
# 5 Frank 30 NY 57
# print(df.query('name.str.endswith("e")'))
# ValueError: unknown type object
Muchos métodos de cadena permiten que el parámetro na especifique un valor para reemplazar el resultado de Ninguno o el valor faltante NaN. Especifique True para extraer filas que contengan valores faltantes o False para no extraer filas que contengan valores faltantes.
print(df[df['name'].str.endswith('e', na=False)])
# name age state point
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
Los argumentos se pueden especificar de la misma manera que query().
print(df.query('name.str.endswith("e", na=False)'))
# name age state point
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
condición de índice
Los criterios (nombres de fila) se pueden especificar usando index.index.
df = pd.read_csv('data/sample_pandas_normal.csv')
print(df.query('index % 2 == 0'))
# name age state point
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
Si el índice tiene un nombre, puede ser ese nombre o el índice.
df_name = df.set_index('name')
print(df_name)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
print(df_name.query('name.str.endswith("e")'))
# age state point
# name
# Alice 24 NY 64
# Charlie 18 CA 70
# Dave 68 TX 70
print(df_name.query('index.str.endswith("e")'))
# age state point
# name
# Alice 24 NY 64
# Charlie 18 CA 70
# Dave 68 TX 70
Especificar varias condiciones
Cuando se especifican varias condiciones con un índice booleano, la descripción es la siguiente.
print(df[(df['age'] < 25) & (df['point'] > 65)])
# name age state point
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
El método query() se puede escribir de la siguiente manera. No se requieren paréntesis para cada condición, Y (y) puede ser & o y.
print(df.query('age < 25 & point > 65'))
# name age state point
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
print(df.query('age < 25 and point > 65'))
# name age state point
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
O (o), | o o son todos aceptables.
print(df.query('age < 20 | point > 80'))
# name age state point
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
print(df.query('age < 20 or point > 80'))
# name age state point
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
NO (negativo) no.
print(df.query('not age < 25 and not point > 65'))
# name age state point
# 5 Frank 30 NY 57
Lo mismo es válido para tres o más condiciones, pero los resultados varían según el orden, por ejemplo, & tiene precedencia sobre |, por lo que es más seguro encerrar explícitamente entre paréntesis la parte que se procesa primero.
print(df.query('age == 24 | point > 80 & state == "CA"'))
# name age state point
# 0 Alice 24 NY 64
# 1 Bob 42 CA 92
# 4 Ellen 24 CA 88
print(df.query('(age == 24 | point > 80) & state == "CA"'))
# name age state point
# 1 Bob 42 CA 92
# 4 Ellen 24 CA 88
Encierre los nombres de las columnas que contengan espacios o puntos con "`"
Tenga cuidado con los nombres de las columnas cuando utilice el método query(). Por ejemplo, cambie los nombres de las columnas de la siguiente manera.
df.columns = ['0name', 'age.year', 'state name', 3]
print(df)
# 0name age.year state name 3
# 0 Alice 24 NY 64
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
# 4 Ellen 24 CA 88
# 5 Frank 30 NY 57
El uso de un nombre de columna que no sea válido como nombre de variable de Python generará un error. Por ejemplo, los nombres de columna que comienzan con un número, los nombres de columna que contienen . o espacios son incorrectos.
# print(df.query('0name.str.endswith("e")'))
# SyntaxError: invalid syntax
# print(df.query('age.year < 25'))
# UndefinedVariableError: name 'age' is not defined
# print(df.query('state name == "CA"'))
# SyntaxError: invalid syntax
Debe estar entre "`".
print(df.query('`0name`.str.endswith("e")'))
# 0name age.year state name 3
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
print(df.query('`age.year` < 25'))
# 0name age.year state name 3
# 0 Alice 24 NY 64
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
print(df.query('`state name` == "CA"'))
# 0name age.year state name 3
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 4 Ellen 24 CA 88
Se produce un error incluso si los nombres de las columnas numéricas están entre "`". Si especifica la condición mediante la indexación booleana, no hay problema.
# print(df.query('3 > 75'))
# KeyError: False
# print(df.query('`3` > 75'))
# UndefinedVariableError: name 'BACKTICK_QUOTED_STRING_3' is not defined
print(df[df[3] > 75])
# 0name age.year state name 3
# 1 Bob 42 CA 92
# 4 Ellen 24 CA 88
Actualizar el objeto original con el parámetro en el lugar
En los ejemplos hasta ahora, se devuelve un nuevo pandas.DataFrame que contiene las filas extraídas a través de query() y los objetos originales se dejan intactos. El parámetro inplace=True cambiará el propio objeto original.
df = pd.read_csv('data/sample_pandas_normal.csv')
df.query('age > 25', inplace=True)
print(df)
# name age state point
# 1 Bob 42 CA 92
# 3 Dave 68 TX 70
# 5 Frank 30 NY 57