08. Filtrado y Selección de Datos
Domina loc, iloc, filtros condicionales y selección avanzada
Domina loc, iloc y filtros condicionales avanzados para seleccionar exactamente los datos que necesitas analizar.
Selección de columnas
Seleccionar una columna
import pandas as pd
import numpy as np
# Dataset de ejemplo
df = pd.DataFrame({
'producto': ['Laptop', 'Mouse', 'Teclado', 'Monitor', 'Tablet'],
'precio': [800, 25, 60, 300, 500],
'stock': [15, 50, 30, 20, 10],
'categoria': ['Computadoras', 'Accesorios', 'Accesorios', 'Monitores', 'Computadoras']
})
# Una columna (retorna Series)
precios = df['precio']
print(type(precios)) # <class 'pandas.core.series.Series'>
# Una columna (retorna DataFrame)
precios_df = df[['precio']]
print(type(precios_df)) # <class 'pandas.core.frame.DataFrame'>
Seleccionar múltiples columnas
# Múltiples columnas
subset = df[['producto', 'precio', 'stock']]
print(subset)
# Reordenar columnas
df_reordenado = df[['categoria', 'producto', 'stock', 'precio']]
# Excluir columnas
columnas_mantener = ['producto', 'precio']
df_filtrado = df[columnas_mantener]
loc: Selección por etiquetas
loc selecciona por etiquetas de índice y nombres de columnas:
# Seleccionar fila por índice
fila = df.loc[0]
print(fila)
# Seleccionar múltiples filas
filas = df.loc[0:2] # Incluye el 2
print(filas)
# Seleccionar filas y columnas específicas
valor = df.loc[0, 'precio'] # Precio de la fila 0
print(valor) # 800
# Múltiples filas y columnas
subset = df.loc[0:2, ['producto', 'precio']]
print(subset)
# Todas las filas, columnas específicas
productos_precios = df.loc[:, ['producto', 'precio']]
loc con índice personalizado
# DataFrame con índice personalizado
df_productos = pd.DataFrame({
'nombre': ['Laptop Pro', 'Mouse Gamer', 'Teclado RGB'],
'precio': [1200, 45, 80],
'stock': [5, 20, 15]
}, index=['PROD-001', 'PROD-002', 'PROD-003'])
# Seleccionar por índice
producto = df_productos.loc['PROD-001']
print(producto)
# Rango de índices
productos = df_productos.loc['PROD-001':'PROD-003']
# Seleccionar dato específico
precio = df_productos.loc['PROD-002', 'precio']
print(f"Precio: ${precio}") # 45
iloc: Selección por posición
iloc selecciona por posición numérica (como arrays):
# Primera fila
primera = df.iloc[0]
# Primeras 3 filas
primeras = df.iloc[0:3] # No incluye el 3
# Última fila
ultima = df.iloc[-1]
# Seleccionar por posiciones de filas y columnas
valor = df.iloc[0, 1] # Fila 0, Columna 1
print(valor) # 800
# Múltiples posiciones
subset = df.iloc[0:3, 0:2] # Primeras 3 filas, primeras 2 columnas
# Seleccionar columnas específicas por posición
columnas = df.iloc[:, [0, 2]] # Columnas 0 y 2
Filtrado condicional
Filtros simples
# Productos con precio > 100
caros = df[df['precio'] > 100]
print(caros)
# Stock bajo (< 20)
stock_bajo = df[df['stock'] < 20]
print(stock_bajo)
# Productos de categoría específica
computadoras = df[df['categoria'] == 'Computadoras']
print(computadoras)
# Productos que NO son accesorios
no_accesorios = df[df['categoria'] != 'Accesorios']
Filtros múltiples (AND)
# Productos caros Y con poco stock
filtro = df[(df['precio'] > 100) & (df['stock'] < 20)]
print(filtro)
# Computadoras con precio > 500
computadoras_caras = df[
(df['categoria'] == 'Computadoras') &
(df['precio'] > 500)
]
print(computadoras_caras)
Filtros múltiples (OR)
# Productos muy caros O muy baratos
extremos = df[(df['precio'] > 500) | (df['precio'] < 50)]
print(extremos)
# Computadoras O Monitores
categorias = df[
(df['categoria'] == 'Computadoras') |
(df['categoria'] == 'Monitores')
]
Filtros con isin()
# Productos específicos
productos_buscar = ['Laptop', 'Monitor', 'Tablet']
filtrado = df[df['producto'].isin(productos_buscar)]
print(filtrado)
# Categorías permitidas
categorias_validas = ['Computadoras', 'Accesorios']
validos = df[df['categoria'].isin(categorias_validas)]
# NOT isin (excluir)
no_accesorios = df[~df['categoria'].isin(['Accesorios'])]
Filtros con strings
# Productos que contienen "top"
laptops = df[df['producto'].str.contains('top', case=False, na=False)]
# Productos que empiezan con "M"
empieza_m = df[df['producto'].str.startswith('M')]
# Productos que terminan con "r"
termina_r = df[df['producto'].str.endswith('r')]
# Longitud del nombre
nombres_largos = df[df['producto'].str.len() > 5]
Filtros con between()
# Precios entre 50 y 500
rango_medio = df[df['precio'].between(50, 500)]
print(rango_medio)
# Stock entre 10 y 30
stock_medio = df[df['stock'].between(10, 30)]
Proyecto práctico: Análisis de ventas
# Dataset completo de ventas
np.random.seed(42)
ventas = pd.DataFrame({
'fecha': pd.date_range('2024-01-01', periods=200, freq='D'),
'producto': np.random.choice([
'Laptop Pro', 'Laptop Basic', 'Mouse Wireless',
'Teclado Mecánico', 'Monitor 24"', 'Monitor 27"',
'Tablet Pro', 'Tablet Basic', 'Webcam HD'
], 200),
'categoria': np.random.choice([
'Computadoras', 'Accesorios', 'Monitores', 'Tablets'
], 200),
'cantidad': np.random.randint(1, 10, 200),
'precio_unitario': np.random.choice([25, 45, 60, 80, 300, 400, 800, 1200], 200),
'region': np.random.choice(['Norte', 'Sur', 'Este', 'Oeste'], 200),
'vendedor': np.random.choice([
'Ana García', 'Carlos López', 'María Rodríguez',
'Luis Martínez', 'Carmen Fernández'
], 200),
'cliente_tipo': np.random.choice(['Nuevo', 'Regular', 'VIP'], 200, p=[0.3, 0.5, 0.2])
})
ventas['total'] = ventas['cantidad'] * ventas['precio_unitario']
ventas['mes'] = ventas['fecha'].dt.month
print("="*70)
print("ANÁLISIS DE VENTAS CON FILTROS AVANZADOS")
print("="*70)
# 1. Ventas grandes (> $2000)
ventas_grandes = ventas[ventas['total'] > 2000]
print(f"\n💰 Ventas > $2,000: {len(ventas_grandes)} transacciones")
print(f" Total: ${ventas_grandes['total'].sum():,.2f}")
# 2. Ventas de laptops en región Norte
laptops_norte = ventas[
(ventas['producto'].str.contains('Laptop')) &
(ventas['region'] == 'Norte')
]
print(f"\n💻 Laptops vendidas en Norte: {len(laptops_norte)}")
print(f" Ingresos: ${laptops_norte['total'].sum():,.2f}")
# 3. Clientes VIP que compraron computadoras o tablets
vip_tech = ventas[
(ventas['cliente_tipo'] == 'VIP') &
(ventas['categoria'].isin(['Computadoras', 'Tablets']))
]
print(f"\n⭐ Clientes VIP (Computadoras/Tablets): {len(vip_tech)}")
print(f" Ticket promedio: ${vip_tech['total'].mean():,.2f}")
# 4. Ventas del primer trimestre
q1 = ventas[ventas['mes'].isin([1, 2, 3])]
print(f"\n📅 Ventas Q1: {len(q1)} transacciones")
print(f" Total Q1: ${q1['total'].sum():,.2f}")
# 5. Top vendedor en cada región
print(f"\n🏆 TOP VENDEDOR POR REGIÓN:")
for region in ventas['region'].unique():
region_ventas = ventas[ventas['region'] == region]
por_vendedor = region_ventas.groupby('vendedor')['total'].sum()
top_vendedor = por_vendedor.idxmax()
top_monto = por_vendedor.max()
print(f" {region}: {top_vendedor} (${top_monto:,.2f})")
# 6. Productos de precio medio (entre $100 y $500)
precio_medio = ventas[ventas['precio_unitario'].between(100, 500)]
productos_medio = precio_medio.groupby('producto')['total'].agg([
('ventas', 'count'),
('ingresos', 'sum')
]).sort_values('ingresos', ascending=False)
print(f"\n📊 PRODUCTOS DE PRECIO MEDIO ($100-$500):")
print(productos_medio.head())
# 7. Análisis de clientes nuevos
nuevos = ventas[ventas['cliente_tipo'] == 'Nuevo']
print(f"\n👶 CLIENTES NUEVOS:")
print(f" Transacciones: {len(nuevos)}")
print(f" Ticket promedio: ${nuevos['total'].mean():,.2f}")
print(f" Categoría preferida: {nuevos['categoria'].value_counts().index[0]}")
# 8. Ventas problemáticas (cantidad alta pero total bajo)
problematicas = ventas[
(ventas['cantidad'] >= 5) &
(ventas['total'] < 300)
]
print(f"\n⚠️ Ventas con posible descuento excesivo: {len(problematicas)}")
if len(problematicas) > 0:
print(problematicas[['fecha', 'producto', 'cantidad', 'total']].head())
query(): Sintaxis SQL-like
# Alternativa más legible para filtros complejos
caros = df.query('precio > 500')
# Múltiples condiciones
filtro = df.query('precio > 100 and stock < 20')
# Con variables externas
precio_min = 100
filtro = df.query('precio > @precio_min')
# OR condition
filtro = df.query('categoria == "Computadoras" or precio > 500')
# IN condition
categorias = ['Computadoras', 'Monitores']
filtro = df.query('categoria in @categorias')
Modificar valores con loc
# Modificar un solo valor
df.loc[0, 'precio'] = 850
# Modificar múltiples valores
df.loc[0:2, 'precio'] = df.loc[0:2, 'precio'] * 1.10
# Modificar basado en condición
df.loc[df['stock'] < 20, 'stock'] = 20 # Stock mínimo 20
# Crear columna condicional
df.loc[df['precio'] > 500, 'categoria_precio'] = 'Premium'
df.loc[df['precio'] <= 500, 'categoria_precio'] = 'Estándar'
Selección avanzada
Seleccionar por tipo de dato
# Solo columnas numéricas
numericas = df.select_dtypes(include=['int64', 'float64'])
# Solo columnas de texto
texto = df.select_dtypes(include=['object'])
# Excluir ciertos tipos
no_numericas = df.select_dtypes(exclude=['int64', 'float64'])
Seleccionar por condiciones complejas
# Productos caros Y (con poco stock O categoría Premium)
complejo = df[
(df['precio'] > 500) &
((df['stock'] < 15) | (df['categoria'] == 'Computadoras'))
]
# Productos donde nombre contiene número
tiene_numero = df[df['producto'].str.contains(r'\d', regex=True)]
Sample: Muestreo aleatorio
# Muestra aleatoria de 5 filas
muestra = df.sample(n=5)
# Muestra del 20% del dataset
muestra = df.sample(frac=0.2)
# Muestra reproducible
muestra = df.sample(n=10, random_state=42)
Buenas prácticas
1. Usar paréntesis en filtros complejos
# ❌ Error común (no usar paréntesis)
# filtro = df[df['precio'] > 100 & df['stock'] < 20] # ERROR
# ✅ Correcto
filtro = df[(df['precio'] > 100) & (df['stock'] < 20)]
2. Usar copy() para evitar SettingWithCopyWarning
# ❌ Puede causar warnings
subset = df[df['precio'] > 500]
subset['descuento'] = 0.1
# ✅ Mejor práctica
subset = df[df['precio'] > 500].copy()
subset['descuento'] = 0.1
3. Validar filtros
# Verificar que el filtro no está vacío
filtrado = df[df['precio'] > 10000]
if len(filtrado) == 0:
print("⚠️ El filtro no retornó resultados")
else:
print(f"✅ {len(filtrado)} registros encontrados")
Resumen de la lección
✅ loc selecciona por etiquetas, iloc por posición numérica
✅ Filtros condicionales usan operadores: >, <, ==, !=, &, |
✅ isin() filtra por lista de valores permitidos
✅ query() ofrece sintaxis SQL-like más legible
✅ Siempre usar paréntesis en condiciones múltiples
✅ Usar copy() al crear subsets que modificarás
🎯 Próxima lección: 09. Limpieza de Datos
En la siguiente lección aprenderás a manejar valores faltantes, duplicados y datos inconsistentes. 🚀
¿Completaste esta lección?
Marca esta lección como completada. Tu progreso se guardará en tu navegador.