07. Carga y Exploración de Datos
Lee CSV, Excel, JSON y explora tus datos con head, info, describe
Aprende a cargar datos desde múltiples fuentes (CSV, Excel, JSON, SQL) y explorar conjuntos de datos comoreales como un analista profesional.
Cargar datos desde archivos
CSV (Comma-Separated Values)
El formato más común en análisis de datos:
import pandas as pd
# Cargar CSV básico
df = pd.read_csv('ventas.csv')
# Opciones comunes
df = pd.read_csv(
'ventas.csv',
sep=',', # Separador (default: coma)
encoding='utf-8', # Encoding (utf-8 o latin1)
decimal='.', # Separador decimal
thousands=',', # Separador de miles
parse_dates=['fecha'], # Parsear columnas como fechas
index_col='id' # Usar columna como índice
)
# Ver primeras filas
print(df.head())
Excel
# Cargar archivo Excel (requiere openpyxl o xlrd)
df = pd.read_excel('ventas.xlsx')
# Especificar hoja
df = pd.read_excel('ventas.xlsx', sheet_name='Enero')
# Cargar múltiples hojas
dict_dfs = pd.read_excel('ventas.xlsx', sheet_name=None)
df_enero = dict_dfs['Enero']
df_febrero = dict_dfs['Febrero']
# Opciones avanzadas
df = pd.read_excel(
'ventas.xlsx',
sheet_name='Datos',
skiprows=2, # Saltar primeras 2 filas
usecols='A:E', # Solo columnas A a E
na_values=['N/A', '-'] # Valores a tratar como NaN
)
JSON
# JSON simple (una lista de objetos)
df = pd.read_json('data.json')
# JSON anidado
df = pd.read_json('data.json', orient='records')
# Desde string JSON
import json
json_string = '[{"nombre": "Juan", "edad": 28}, {"nombre": "María", "edad": 32}]'
df = pd.read_json(json_string)
# Normalizar JSON anidado
from pandas import json_normalize
df = json_normalize(json_data)
SQL
import pandas as pd
from sqlalchemy import create_engine
# Conectar a base de datos
engine = create_engine('postgresql://user:password@localhost/database')
# Cargar tabla completa
df = pd.read_sql_table('ventas', engine)
# Query personalizada
query = """
SELECT *
FROM ventas
WHERE fecha >= '2024-01-01'
AND monto > 1000
"""
df = pd.read_sql_query(query, engine)
# Forma más simple (SQLite)
import sqlite3
conn = sqlite3.connect('datos.db')
df = pd.read_sql_query("SELECT * FROM ventas", conn)
conn.close()
Ejemplo práctico: Cargar dataset de ventas
# Crear dataset de ejemplo y guardarlo
import pandas as pd
import numpy as np
# Generar datos de ejemplo
np.random.seed(42)
fechas = pd.date_range('2024-01-01', periods=100, freq='D')
ventas_data = {
'fecha': fechas,
'producto': np.random.choice(['Laptop', 'Mouse', 'Teclado', 'Monitor'], 100),
'categoria': np.random.choice(['Electrónica', 'Accesorios'], 100),
'cantidad': np.random.randint(1, 10, 100),
'precio_unitario': np.random.choice([25, 60, 300, 800], 100),
'region': np.random.choice(['Norte', 'Sur', 'Este', 'Oeste'], 100),
'vendedor': np.random.choice(['Ana', 'Carlos', 'Luis', 'María'], 100)
}
df_ventas = pd.DataFrame(ventas_data)
df_ventas['total'] = df_ventas['cantidad'] * df_ventas['precio_unitario']
# Guardar a CSV
df_ventas.to_csv('ventas_2024.csv', index=False)
print("✅ Dataset creado y guardado en ventas_2024.csv")
# Cargar el CSV
df = pd.read_csv('ventas_2024.csv', parse_dates=['fecha'])
print(f"\n📊 Dataset cargado: {df.shape[0]} filas, {df.shape[1]} columnas")
Exploración inicial de datos
El flujo EDA (Exploratory Data Analysis)
# 1. Ver primeras y últimas filas
print("Primeras 5 filas:")
print(df.head())
print("\nÚltimas 5 filas:")
print(df.tail())
# 2. Información general del DataFrame
print("\nInformación del DataFrame:")
print(df.info())
# 3. Estadísticas descriptivas
print("\nEstadísticas descriptivas:")
print(df.describe())
# 4. Dimensiones
print(f"\nFilas: {df.shape[0]}")
print(f"Columnas: {df.shape[1]}")
# 5. Nombres de columnas
print(f"\nColumnas: {list(df.columns)}")
# 6. Tipos de datos
print("\nTipos de datos:")
print(df.dtypes)
Inspeccionar valores únicos
# Valores únicos por columna
print(f"Productos únicos: {df['producto'].nunique()}")
print(f"Regiones únicas: {df['region'].nunique()}")
# Ver todos los valores únicos
print("\nProductos:")
print(df['producto'].unique())
# Contar frecuencia de cada valor
print("\nDistribución de productos:")
print(df['producto'].value_counts())
# Porcentajes
print("\nDistribución porcentual:")
print(df['producto'].value_counts(normalize=True) * 100)
Detectar valores faltantes
# Contar valores nulos por columna
print("Valores nulos:")
print(df.isnull().sum())
# Porcentaje de valores nulos
print("\nPorcentaje de valores nulos:")
print((df.isnull().sum() / len(df)) * 100)
# Verificar si hay algún nulo
print(f"\n¿Hay valores nulos?: {df.isnull().any().any()}")
# Ver filas con valores nulos
filas_con_nulos = df[df.isnull().any(axis=1)]
print(f"\nFilas con valores nulos: {len(filas_con_nulos)}")
Análisis exploratorio completo
def analizar_dataset(df, nombre="Dataset"):
"""
Realiza análisis exploratorio completo de un DataFrame.
"""
print("="*70)
print(f"ANÁLISIS EXPLORATORIO: {nombre}")
print("="*70)
# 1. Dimensiones
print(f"\n📏 DIMENSIONES:")
print(f" Filas: {df.shape[0]:,}")
print(f" Columnas: {df.shape[1]}")
print(f" Total celdas: {df.shape[0] * df.shape[1]:,}")
# 2. Tipos de datos
print(f"\n📊 TIPOS DE DATOS:")
print(df.dtypes.value_counts())
# 3. Valores nulos
print(f"\n❓ VALORES FALTANTES:")
nulos = df.isnull().sum()
if nulos.sum() == 0:
print(" ✅ No hay valores nulos")
else:
print(nulos[nulos > 0])
# 4. Duplicados
print(f"\n🔄 FILAS DUPLICADAS:")
duplicados = df.duplicated().sum()
if duplicados == 0:
print(" ✅ No hay filas duplicadas")
else:
print(f" ⚠️ {duplicados} filas duplicadas ({duplicados/len(df)*100:.1f}%)")
# 5. Columnas numéricas
print(f"\n🔢 COLUMNAS NUMÉRICAS:")
numericas = df.select_dtypes(include=['int64', 'float64']).columns
if len(numericas) > 0:
print(df[numericas].describe().round(2))
else:
print(" No hay columnas numéricas")
# 6. Columnas categóricas
print(f"\n📝 COLUMNAS CATEGÓRICAS:")
categoricas = df.select_dtypes(include=['object']).columns
for col in categoricas:
unicos = df[col].nunique()
print(f" {col}: {unicos} valores únicos")
if unicos <= 10:
print(f" {list(df[col].unique())}")
# 7. Muestra de datos
print(f"\n👀 MUESTRA DE DATOS:")
print(df.head(3))
# Usar la función
analizar_dataset(df, "Ventas 2024")
Estadísticas por grupos
# Agrupar por producto y calcular estadísticas
print("Ventas por producto:")
por_producto = df.groupby('producto')['total'].agg([
('cantidad_transacciones', 'count'),
('total_ventas', 'sum'),
('promedio', 'mean'),
('mediana', 'median'),
('maximo', 'max'),
('minimo', 'min')
]).round(2)
print(por_producto)
# Agrupar por múltiples columnas
print("\nVentas por región y producto:")
por_region_producto = df.groupby(['region', 'producto'])['total'].sum()
print(por_region_producto)
# Crear tabla pivot
print("\nTabla pivot: Región vs Producto:")
pivot = df.pivot_table(
values='total',
index='region',
columns='producto',
aggfunc='sum',
fill_value=0
)
print(pivot)
Filtrado básico durante exploración
# Filtrar datos para análisis específico
ventas_altas = df[df['total'] > 1000]
print(f"Ventas mayores a $1,000: {len(ventas_altas)}")
# Múltiples condiciones
ventas_laptops_norte = df[
(df['producto'] == 'Laptop') &
(df['region'] == 'Norte')
]
print(f"\nVentas de Laptops en región Norte: {len(ventas_laptops_norte)}")
# Filtrar por fechas
enero = df[df['fecha'].dt.month == 1]
print(f"\nVentas de enero: {len(enero)}")
# Top 10 ventas
top_ventas = df.nlargest(10, 'total')
print("\nTop 10 ventas:")
print(top_ventas[['fecha', 'producto', 'total']])
Proyecto práctico: Análisis de e-commerce
# Crear dataset de e-commerce
np.random.seed(42)
ecommerce_data = {
'order_id': range(1, 501),
'fecha': pd.date_range('2024-01-01', periods=500, freq='H'),
'cliente_id': np.random.randint(1000, 2000, 500),
'producto': np.random.choice([
'Laptop Pro', 'Laptop Basic', 'Mouse Wireless',
'Mouse Gaming', 'Teclado Mecánico', 'Teclado Estándar',
'Monitor 24"', 'Monitor 27"', 'Webcam HD'
], 500),
'categoria': np.random.choice([
'Computadoras', 'Accesorios', 'Periféricos'
], 500),
'cantidad': np.random.randint(1, 5, 500),
'precio_unitario': np.random.choice([
25, 45, 60, 80, 300, 400, 800, 1200
], 500),
'descuento_porcentaje': np.random.choice([0, 5, 10, 15, 20], 500),
'metodo_pago': np.random.choice([
'Tarjeta Crédito', 'Tarjeta Débito', 'PayPal', 'Transferencia'
], 500),
'envio': np.random.choice(['Estándar', 'Express', 'Premium'], 500)
}
df_ecom = pd.DataFrame(ecommerce_data)
# Calcular columnas derivadas
df_ecom['subtotal'] = df_ecom['cantidad'] * df_ecom['precio_unitario']
df_ecom['descuento_monto'] = df_ecom['subtotal'] * (df_ecom['descuento_porcentaje'] / 100)
df_ecom['total'] = df_ecom['subtotal'] - df_ecom['descuento_monto']
print("="*70)
print("ANÁLISIS DE E-COMMERCE - Q1 2024")
print("="*70)
# 1. Resumen general
print("\n📊 RESUMEN GENERAL:")
print(f"Total órdenes: {len(df_ecom):,}")
print(f"Total clientes únicos: {df_ecom['cliente_id'].nunique():,}")
print(f"Ingresos totales: ${df_ecom['total'].sum():,.2f}")
print(f"Ticket promedio: ${df_ecom['total'].mean():,.2f}")
print(f"Orden más alta: ${df_ecom['total'].max():,.2f}")
# 2. Por categoría
print("\n📦 ANÁLISIS POR CATEGORÍA:")
por_categoria = df_ecom.groupby('categoria').agg({
'order_id': 'count',
'total': ['sum', 'mean']
}).round(2)
por_categoria.columns = ['Órdenes', 'Ingresos Totales', 'Ticket Promedio']
print(por_categoria)
# 3. Por método de pago
print("\n💳 MÉTODOS DE PAGO:")
metodos = df_ecom.groupby('metodo_pago').agg({
'order_id': 'count',
'total': 'sum'
})
metodos['porcentaje'] = (metodos['order_id'] / len(df_ecom) * 100).round(1)
print(metodos)
# 4. Descuentos aplicados
print("\n🏷️ ANÁLISIS DE DESCUENTOS:")
con_descuento = df_ecom[df_ecom['descuento_porcentaje'] > 0]
print(f"Órdenes con descuento: {len(con_descuento)} ({len(con_descuento)/len(df_ecom)*100:.1f}%)")
print(f"Descuento promedio: {df_ecom[df_ecom['descuento_porcentaje']>0]['descuento_porcentaje'].mean():.1f}%")
print(f"Monto total descontado: ${df_ecom['descuento_monto'].sum():,.2f}")
# 5. Top productos
print("\n🏆 TOP 5 PRODUCTOS:")
top_productos = df_ecom.groupby('producto').agg({
'order_id': 'count',
'total': 'sum'
}).sort_values('total', ascending=False).head(5)
top_productos.columns = ['Ventas', 'Ingresos']
print(top_productos)
# 6. Tendencia temporal
print("\n📈 VENTAS POR DÍA:")
df_ecom['dia'] = df_ecom['fecha'].dt.date
ventas_diarias = df_ecom.groupby('dia')['total'].sum()
print(f"Promedio diario: ${ventas_diarias.mean():,.2f}")
print(f"Mejor día: {ventas_diarias.idxmax()} (${ventas_diarias.max():,.2f})")
print(f"Peor día: {ventas_diarias.idxmin()} (${ventas_diarias.min():,.2f})")
# 7. Análisis de envíos
print("\n📦 TIPOS DE ENVÍO:")
envios = df_ecom['envio'].value_counts()
print(envios)
print(f"\nCosto promedio por tipo de envío:")
costo_envio = {'Estándar': 0, 'Express': 10, 'Premium': 25}
df_ecom['costo_envio'] = df_ecom['envio'].map(costo_envio)
print(df_ecom.groupby('envio')['costo_envio'].mean())
Guardar datos procesados
# Guardar a CSV
df_ecom.to_csv('ecommerce_procesado.csv', index=False)
# Guardar a Excel (múltiples hojas)
with pd.ExcelWriter('reporte_completo.xlsx') as writer:
df_ecom.to_excel(writer, sheet_name='Datos Completos', index=False)
por_categoria.to_excel(writer, sheet_name='Por Categoría')
top_productos.to_excel(writer, sheet_name='Top Productos')
print("✅ Datos guardados correctamente")
# Guardar solo columnas específicas
columnas_importantes = ['order_id', 'fecha', 'producto', 'total']
df_ecom[columnas_importantes].to_csv('resumen_ventas.csv', index=False)
Buenas prácticas
1. Siempre explorar antes de analizar
# ❌ Mal: analizar sin explorar
df = pd.read_csv('datos.csv')
resultado = df['ventas'].mean() # ¿Hay nulos? ¿Outliers?
# ✅ Bien: explorar primero
df = pd.read_csv('datos.csv')
print(df.info())
print(df['ventas'].describe())
print(df['ventas'].isnull().sum())
# Ahora sí, analizar
resultado = df['ventas'].mean()
2. Documentar hallazgos
# Crear diccionario con hallazgos clave
hallazgos = {
'total_registros': len(df),
'fecha_inicio': df['fecha'].min(),
'fecha_fin': df['fecha'].max(),
'ingresos_totales': df['total'].sum(),
'ticket_promedio': df['total'].mean(),
'productos_unicos': df['producto'].nunique()
}
# Guardar hallazgos
import json
with open('hallazgos_exploracion.json', 'w') as f:
json.dump(hallazgos, f, indent=2, default=str)
3. Crear funciones reutilizables
def cargar_y_explorar(ruta_archivo):
"""Carga archivo y muestra resumen exploratorio"""
df = pd.read_csv(ruta_archivo)
print(f"✅ Archivo cargado: {ruta_archivo}")
print(f" Filas: {len(df):,}")
print(f" Columnas: {len(df.columns)}")
print(f"\n{df.head()}")
print(f"\n{df.info()}")
return df
# Usar la función
df = cargar_y_explorar('ventas.csv')
Resumen de la lección
✅ Pandas puede cargar datos desde CSV, Excel, JSON, SQL y más
✅ read_csv() y read_excel() son las funciones más comunes
✅ La exploración inicial siempre incluye: head(), info(), describe()
✅ Detectar valores nulos y duplicados es fundamental
✅ Agrupar datos con groupby() revela patrones importantes
✅ Siempre guardar datos procesados para análisis posteriores
🎯 Próxima lección: 08. Filtrado y Selección de Datos
En la siguiente lección dominarás loc, iloc y filtros avanzados para seleccionar exactamente los datos que necesitas. 🚀
¿Completaste esta lección?
Marca esta lección como completada. Tu progreso se guardará en tu navegador.