Skip to content
Temas
Pandas
Pandas Filter Rows: Select Data by Condition in Python

Filtrar Filas en Pandas: Seleccionar Datos por Condición en Python

Updated on

Filtrar filas en DataFrames de pandas es una de las operaciones más comunes en análisis de datos. Ya sea que estés limpiando datos, explorando patrones o preparando conjuntos de datos para aprendizaje automático, necesitas seleccionar filas específicas basadas en condiciones. El desafío es elegir el método correcto entre los múltiples enfoques de filtrado de pandas, cada uno con diferente sintaxis, características de rendimiento y casos de uso.

Muchos científicos de datos luchan con la eficiencia del filtrado, especialmente cuando trabajan con grandes conjuntos de datos o condiciones complejas. Usar el método incorrecto puede ralentizar tu análisis en órdenes de magnitud. Entender cuándo usar indexación booleana versus .query() o .loc[] puede marcar la diferencia entre un script que se ejecuta en segundos versus uno que tarda minutos.

Esta guía cubre todos los métodos de filtrado de pandas con ejemplos prácticos, comparaciones de rendimiento y mejores prácticas. Aprenderás indexación booleana, el método .query(), selección .loc[], la función .where() y el método .filter(). Al final, sabrás exactamente qué enfoque usar para cualquier escenario de filtrado.

📚

Comprender los Métodos de Filtrado de Filas en Pandas

Pandas proporciona cinco métodos principales para filtrar filas de DataFrame, cada uno adecuado para diferentes escenarios:

MétodoMejor ParaEjemplo de SintaxisRendimiento
Indexación BooleanaCondiciones simples, legibilidaddf[df['age'] > 25]Rápido para datos pequeños-medianos
.query()Condiciones complejas, basado en stringsdf.query('age > 25 and city == "NYC"')Más rápido para datos grandes
.loc[]Basado en etiquetas con condicionesdf.loc[df['age'] > 25, ['name', 'age']]Selección flexible de columnas
.where()Mantener estructura, reemplazar valoresdf.where(df['age'] > 25, np.nan)Preserva forma del DataFrame
.filter()Filtrar por nombres de columna/índicedf.filter(like='total', axis=1)Patrones de nombres columna/índice

Exploremos cada método con ejemplos detallados.

Indexación Booleana: El Enfoque Más Común

La indexación booleana filtra filas creando una máscara booleana (valores True/False) y aplicándola al DataFrame. Este es el método más intuitivo para principiantes.

import pandas as pd
import numpy as np
 
# Crear DataFrame de ejemplo
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'age': [25, 30, 35, 28, 32],
    'city': ['NYC', 'LA', 'NYC', 'Chicago', 'LA'],
    'salary': [70000, 80000, 90000, 75000, 85000]
})
 
# Filtrar filas donde age es mayor que 30
filtered = df[df['age'] > 30]
print(filtered)
#       name  age city  salary
# 2  Charlie   35  NYC   90000
# 4      Eve   32   LA   85000
 
# Ver la máscara booleana
print(df['age'] > 30)
# 0    False
# 1    False
# 2     True
# 3    False
# 4     True

La indexación booleana funciona evaluando la condición df['age'] > 30, que devuelve una Serie de valores True/False. Cuando pasas esta máscara al DataFrame con df[mask], pandas devuelve solo las filas donde la máscara es True.

Filtrar con Múltiples Condiciones

Combina múltiples condiciones usando operadores lógicos. Importante: Usa & (y), | (o), ~ (no) en lugar de las palabras clave and, or, not de Python. Siempre envuelve cada condición entre paréntesis.

# Múltiples condiciones con AND
filtered = df[(df['age'] > 25) & (df['city'] == 'NYC')]
print(filtered)
#       name  age city  salary
# 2  Charlie   35  NYC   90000
 
# Múltiples condiciones con OR
filtered = df[(df['age'] > 30) | (df['salary'] > 80000)]
print(filtered)
#       name  age     city  salary
# 2  Charlie   35      NYC   90000
# 4      Eve   32       LA   85000
 
# Operador NOT
filtered = df[~(df['city'] == 'NYC')]
print(filtered)
#     name  age     city  salary
# 1    Bob   30       LA   80000
# 3  David   28  Chicago   75000
# 4    Eve   32       LA   85000

Usar .isin() para Múltiples Valores

Filtra filas donde una columna coincide con cualquier valor en una lista usando .isin():

# Filtrar filas donde city es NYC o LA
cities = ['NYC', 'LA']
filtered = df[df['city'].isin(cities)]
print(filtered)
#       name  age city  salary
# 0    Alice   25  NYC   70000
# 1      Bob   30   LA   80000
# 2  Charlie   35  NYC   90000
# 4      Eve   32   LA   85000
 
# Inverso: ciudades NO en la lista
filtered = df[~df['city'].isin(cities)]
print(filtered)
#     name  age     city  salary
# 3  David   28  Chicago   75000

Filtrar con .between()

El método .between() filtra valores dentro de un rango (inclusivo por defecto):

# Filtrar edades entre 28 y 32
filtered = df[df['age'].between(28, 32)]
print(filtered)
#     name  age     city  salary
# 1    Bob   30       LA   80000
# 3  David   28  Chicago   75000
# 4    Eve   32       LA   85000
 
# Límites exclusivos
filtered = df[df['age'].between(28, 32, inclusive='neither')]
print(filtered)
#   name  age city  salary
# 1  Bob   30   LA   80000

El Método .query(): Filtrado Basado en Strings

El método .query() acepta una expresión de string, haciéndolo legible para condiciones complejas. Es particularmente eficiente para DataFrames grandes porque usa numexpr para optimización.

# Consulta simple
filtered = df.query('age > 30')
print(filtered)
#       name  age city  salary
# 2  Charlie   35  NYC   90000
# 4      Eve   32   LA   85000
 
# Múltiples condiciones
filtered = df.query('age > 25 and city == "NYC"')
print(filtered)
#       name  age city  salary
# 2  Charlie   35  NYC   90000
 
# Usar variables con símbolo @
min_age = 30
filtered = df.query('age > @min_age')
print(filtered)
#       name  age city  salary
# 2  Charlie   35  NYC   90000
# 4      Eve   32   LA   85000

Expresiones Avanzadas .query()

# Usar .isin() en query
cities = ['NYC', 'LA']
filtered = df.query('city in @cities')
print(filtered)
 
# Condiciones de rango
filtered = df.query('28 <= age <= 32')
print(filtered)
 
# Métodos de string
filtered = df.query('city.str.contains("LA")', engine='python')
print(filtered)

.loc[] para Filtrado Basado en Etiquetas

El indexador .loc[] combina filtrado de filas con selección de columnas. Úsalo cuando necesites columnas específicas de filas filtradas.

# Filtrar filas y seleccionar columnas
filtered = df.loc[df['age'] > 30, ['name', 'age']]
print(filtered)
#       name  age
# 2  Charlie   35
# 4      Eve   32
 
# Múltiples condiciones
filtered = df.loc[(df['age'] > 25) & (df['salary'] > 75000), ['name', 'salary']]
print(filtered)
#       name  salary
# 1      Bob   80000
# 2  Charlie   90000
# 4      Eve   85000
 
# Todas las columnas
filtered = df.loc[df['city'] == 'NYC', :]
print(filtered)

Método .where(): Reemplazo Condicional de Valores

A diferencia de otros métodos, .where() preserva la forma del DataFrame reemplazando valores que no cumplen la condición con NaN (o un valor especificado).

# Mantener valores donde age > 30, reemplazar otros con NaN
result = df.where(df['age'] > 30)
print(result)
#       name   age city   salary
# 0      NaN   NaN  NaN      NaN
# 1      NaN   NaN  NaN      NaN
# 2  Charlie  35.0  NYC  90000.0
# 3      NaN   NaN  NaN      NaN
# 4      Eve  32.0   LA  85000.0
 
# Reemplazar con valor personalizado
result = df.where(df['age'] > 30, 'FILTERED')
print(result)
 
# Eliminar filas con NaN después de .where()
result = df.where(df['age'] > 30).dropna()
print(result)

Método .filter(): Filtrar por Nombres de Columna/Índice

El método .filter() filtra columnas o filas por sus etiquetas (nombres), no por valores. Úsalo para selección de columnas basada en patrones.

# Crear DataFrame con múltiples columnas
df_wide = pd.DataFrame({
    'total_sales': [100, 200, 300],
    'total_profit': [20, 40, 60],
    'monthly_sales': [10, 20, 30],
    'yearly_sales': [120, 240, 360],
    'region': ['East', 'West', 'North']
})
 
# Filtrar columnas que contienen 'total'
filtered = df_wide.filter(like='total')
print(filtered)
#    total_sales  total_profit
# 0          100            20
# 1          200            40
# 2          300            60
 
# Filtrar columnas usando regex
filtered = df_wide.filter(regex=r'.*sales$')
print(filtered)
#    total_sales  monthly_sales  yearly_sales
# 0          100             10           120
# 1          200             20           240
# 2          300             30           360
 
# Filtrar columnas por nombres exactos
filtered = df_wide.filter(items=['total_sales', 'region'])
print(filtered)

Filtrar Datos de String

Pandas proporciona métodos de string a través del accessor .str para filtrar columnas de texto.

# Crear DataFrame con datos de texto
df_text = pd.DataFrame({
    'name': ['Alice Smith', 'Bob Johnson', 'Charlie Brown', 'David Lee'],
    'email': ['alice@gmail.com', 'bob@yahoo.com', 'charlie@gmail.com', 'david@outlook.com']
})
 
# Filtrar filas donde name contiene 'Smith'
filtered = df_text[df_text['name'].str.contains('Smith')]
print(filtered)
#          name           email
# 0  Alice Smith  alice@gmail.com
 
# Búsqueda sin distinción de mayúsculas
filtered = df_text[df_text['name'].str.contains('smith', case=False)]
print(filtered)
 
# Filtrar por dominio de email
filtered = df_text[df_text['email'].str.endswith('gmail.com')]
print(filtered)
#            name              email
# 0   Alice Smith    alice@gmail.com
# 2  Charlie Brown  charlie@gmail.com
 
# Filtrar con regex
filtered = df_text[df_text['name'].str.match(r'^[A-C]')]
print(filtered)

Filtrar Valores Nulos y No Nulos

Usa .isna(), .notna(), .isnull() y .notnull() para filtrar basándose en datos faltantes.

# Crear DataFrame con valores faltantes
df_missing = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, 7, 8],
    'C': [9, 10, 11, 12]
})
 
# Filtrar filas donde columna A no es null
filtered = df_missing[df_missing['A'].notna()]
print(filtered)
#      A    B   C
# 0  1.0  5.0   9
# 1  2.0  NaN  10
# 3  4.0  8.0  12
 
# Filtrar filas donde CUALQUIER columna es null
filtered = df_missing[df_missing.isna().any(axis=1)]
print(filtered)
#      A    B   C
# 1  2.0  NaN  10
# 2  NaN  7.0  11
 
# Filtrar filas donde TODAS las columnas no son null
filtered = df_missing[df_missing.notna().all(axis=1)]
print(filtered)
#      A    B   C
# 0  1.0  5.0   9
# 3  4.0  8.0  12

Filtrar por Rangos de Fechas

Cuando trabajas con columnas datetime, puedes filtrar por rangos de fechas usando operadores de comparación estándar.

# Crear DataFrame con fechas
df_dates = pd.DataFrame({
    'date': pd.date_range('2026-01-01', periods=10, freq='D'),
    'value': range(10)
})
 
# Filtrar fechas después de una fecha específica
filtered = df_dates[df_dates['date'] > '2026-01-05']
print(filtered)
 
# Filtrar rango de fechas
start_date = '2026-01-03'
end_date = '2026-01-07'
filtered = df_dates[(df_dates['date'] >= start_date) & (df_dates['date'] <= end_date)]
print(filtered)
 
# Usar .between() para fechas
filtered = df_dates[df_dates['date'].between('2026-01-03', '2026-01-07')]
print(filtered)

Comparación de Rendimiento: DataFrames Grandes

Diferentes métodos de filtrado tienen diferentes características de rendimiento. Aquí hay una comparación para un DataFrame con 1 millón de filas:

import time
 
# Crear DataFrame grande
np.random.seed(42)
df_large = pd.DataFrame({
    'A': np.random.randint(0, 100, 1000000),
    'B': np.random.randint(0, 100, 1000000),
    'C': np.random.choice(['X', 'Y', 'Z'], 1000000)
})
 
# Indexación booleana
start = time.time()
result = df_large[(df_large['A'] > 50) & (df_large['B'] < 30)]
print(f"Indexación booleana: {time.time() - start:.4f} segundos")
 
# Método .query()
start = time.time()
result = df_large.query('A > 50 and B < 30')
print(f"Método .query(): {time.time() - start:.4f} segundos")
 
# Método .loc[]
start = time.time()
result = df_large.loc[(df_large['A'] > 50) & (df_large['B'] < 30)]
print(f"Método .loc[]: {time.time() - start:.4f} segundos")

Insights de rendimiento:

  • Indexación booleana: Rápida para condiciones simples, más lenta para filtros complejos multi-condición
  • .query(): Más rápido para DataFrames grandes con múltiples condiciones (usa optimización numexpr)
  • .loc[]: Similar a indexación booleana pero más flexible para selección de columnas
  • .where(): Más lento debido al recorrido completo del DataFrame, usar solo cuando necesites preservar la forma

Para conjuntos de datos de más de 100,000 filas con múltiples condiciones, .query() típicamente supera a la indexación booleana en un 20-40%.

Errores Comunes y Cómo Evitarlos

Error 1: Usar 'and' en Lugar de '&'

# INCORRECTO - lanza ValueError
# filtered = df[df['age'] > 25 and df['city'] == 'NYC']
 
# CORRECTO
filtered = df[(df['age'] > 25) & (df['city'] == 'NYC')]

Error 2: Olvidar Paréntesis

# INCORRECTO - problemas de precedencia de operadores
# filtered = df[df['age'] > 25 & df['city'] == 'NYC']
 
# CORRECTO - envolver cada condición
filtered = df[(df['age'] > 25) & (df['city'] == 'NYC')]

Error 3: Modificar DataFrame Original

# Filtrar crea una vista, no una copia
filtered = df[df['age'] > 30]
 
# INCORRECTO - SettingWithCopyWarning
# filtered['new_col'] = 100
 
# CORRECTO - crear copia explícita
filtered = df[df['age'] > 30].copy()
filtered['new_col'] = 100

Error 4: Filtrado de String sin Manejar NaN

df_with_nan = pd.DataFrame({
    'name': ['Alice', np.nan, 'Charlie']
})
 
# INCORRECTO - lanza error si hay NaN presente
# filtered = df_with_nan[df_with_nan['name'].str.contains('li')]
 
# CORRECTO - manejar NaN con parámetro na
filtered = df_with_nan[df_with_nan['name'].str.contains('li', na=False)]

Visualizar Datos Filtrados con PyGWalker

Después de filtrar tu DataFrame de pandas, visualizar los resultados ayuda a descubrir patrones e insights. PyGWalker (opens in a new tab) transforma DataFrames filtrados en una interfaz interactiva similar a Tableau directamente en notebooks de Python, sin necesidad de exportar datos o escribir código de gráficos complejo.

PyGWalker es particularmente útil cuando exploras conjuntos de datos filtrados porque te permite:

  • Arrastrar y soltar columnas para crear gráficos instantáneamente
  • Aplicar filtros adicionales visualmente sin escribir código
  • Cambiar entre tipos de gráficos (barras, línea, dispersión, mapa de calor) en segundos
  • Exportar visualizaciones para informes o presentaciones
import pygwalker as pyg
 
# Filtrar DataFrame
filtered_df = df[(df['age'] > 25) & (df['salary'] > 75000)]
 
# Lanzar visualización interactiva
pyg.walk(filtered_df)

Esto abre una interfaz interactiva donde puedes crear visualizaciones arrastrando columnas filtradas al constructor de gráficos. Para analistas de datos que trabajan con múltiples condiciones de filtro, PyGWalker elimina el ciclo de iteración de filtrar → graficar → ajustar → volver a graficar.

Preguntas Frecuentes

¿Cómo filtro filas de DataFrame de pandas por condición?

Usa indexación booleana con df[df['column'] > value] para condiciones simples. Para múltiples condiciones, usa & (y), | (o), ~ (no) con paréntesis: df[(df['A'] > 10) & (df['B'] < 20)]. Alternativamente, usa .query() para sintaxis legible: df.query('A > 10 and B < 20').

¿Cuál es la diferencia entre .loc[] e indexación booleana?

La indexación booleana (df[df['col'] > 5]) devuelve todas las columnas para filas filtradas. .loc[] permite selección de columnas simultáneamente: df.loc[df['col'] > 5, ['col1', 'col2']]. Ambos métodos tienen rendimiento similar, pero .loc[] es más explícito y soporta selección de filas basada en etiquetas.

¿Cómo filtrar DataFrame de pandas con múltiples condiciones?

Combina condiciones usando operadores & (y), | (o), ~ (no). Siempre envuelve cada condición entre paréntesis: df[(df['age'] > 25) & (df['city'] == 'NYC') | (df['salary'] > 80000)]. Para condiciones complejas, usa .query(): df.query('age > 25 and (city == "NYC" or salary > 80000)').

¿Cuándo debería usar .query() en lugar de indexación booleana?

Usa .query() para DataFrames grandes (>100k filas) con múltiples condiciones: es 20-40% más rápido debido a la optimización numexpr. También es más legible para condiciones complejas. Usa indexación booleana para filtros simples o cuando necesites máxima compatibilidad (.query() requiere expresiones de string que son más difíciles de depurar).

¿Cómo filtro filas donde el valor de columna está en una lista?

Usa el método .isin(): df[df['city'].isin(['NYC', 'LA', 'Chicago'])]. Para el inverso (no en lista), usa el operador ~: df[~df['city'].isin(['NYC', 'LA'])]. Esto es más eficiente que encadenar múltiples condiciones | para listas grandes.

Conclusión

Filtrar filas de DataFrame de pandas es una habilidad fundamental para el análisis de datos en Python. Ahora entiendes cinco métodos de filtrado: indexación booleana para simplicidad, .query() para rendimiento, .loc[] para selección flexible de columnas, .where() para reemplazo de valores y .filter() para patrones de nombres de columnas.

Conclusiones clave:

  • Usa indexación booleana para filtros rápidos y legibles en conjuntos de datos pequeños a medianos
  • Elige .query() para conjuntos de datos grandes con condiciones complejas (20-40% más rápido)
  • Aplica .loc[] cuando necesites tanto filtrado de filas como selección de columnas
  • Recuerda usar operadores &, |, ~ en lugar de and, or, not
  • Siempre envuelve las condiciones entre paréntesis para evitar problemas de precedencia de operadores

Domina estas técnicas de filtrado y manejarás cualquier escenario de selección de datos eficientemente. Para exploración interactiva de datos filtrados, considera usar PyGWalker para visualizar tus resultados sin escribir código de gráficos adicional.

📚