Lección 11 de 12 · Nivel 3: Avanzado
Análisis de datos con pandas: de Excel a Python
En esta lección
- Cargar datos de CSV y Excel en un DataFrame y explorarlos.
- Filtrar, ordenar, crear columnas y limpiar datos.
- Resumir con
groupbyy tablas dinámicas, y unir tablas. - Exportar resultados a Excel y hacer un gráfico.
Si prefieres no generarlo con código, descárgalo y empieza directamente con pd.read_csv("ventas.csv").
- ventas.csv · el archivo de ventas de esta lección, listo para usar
pandas es la librería más usada del mundo para analizar datos. Hace lo mismo que Excel (filtrar, ordenar, tablas dinámicas, BUSCARV), pero con millones de filas, de forma automática y repetible. Si hiciste el curso de Excel, vas a reconocer cada concepto; si no, no pasa nada: empezamos desde cero.
Preparación
pip install pandas openpyxl matplotlib
(Dentro de tu entorno virtual, como viste en la lección 10. openpyxl permite leer y escribir Excel; matplotlib, hacer gráficos.) En Google Colab ya vienen instaladas.
Para practicar, este código crea un archivo de ventas de ejemplo:
import pandas as pd
datos = {
"fecha": ["2026-01-05", "2026-01-12", "2026-01-20", "2026-02-03", "2026-02-15",
"2026-02-21", "2026-03-02", "2026-03-10", "2026-03-18", "2026-03-25"],
"region": ["Norte", "Sur", "Norte", "Centro", "Sur", "Norte", "Centro", "Sur", "Norte", None],
"vendedor": ["Ana", "Luis", "Ana", "Eva", "Luis", "Ana", "Eva", "Luis", "Ana", "Eva"],
"producto": ["Café", "Té", "Café", "Café", "Té", "Chocolate", "Café", "Té", "Chocolate", "Café"],
"unidades": [120, 80, 95, 60, 110, 40, 75, 90, 55, 70],
"precio": [12.5, 9.0, 12.5, 12.5, 9.0, 15.0, 12.5, 9.0, 15.0, 12.5],
}
pd.DataFrame(datos).to_csv("ventas.csv", index=False)
DataFrame y Series
Un DataFrame es una tabla: filas y columnas con nombre, como una hoja de Excel. Cada columna es una Series.
df = pd.read_csv("ventas.csv", parse_dates=["fecha"])
# Para Excel: pd.read_excel("ventas.xlsx", sheet_name="Datos")
print(df.head()) # primeras 5 filas
print(df.shape) # (10, 6): filas y columnas
df.info() # columnas, tipos y valores no nulos
print(df.describe()) # estadísticas de las columnas numéricas
Explorar primero es la regla número uno: info() te muestra que la columna region tiene un valor vacío. Lo vamos a resolver enseguida.
Seleccionar y filtrar
df["vendedor"] # una columna
df[["vendedor", "unidades"]] # varias columnas (doble corchete)
df[df["region"] == "Norte"] # filtrar filas
df[(df["region"] == "Norte") & (df["unidades"] > 100)] # Y
df[(df["producto"] == "Té") | (df["producto"] == "Chocolate")] # O
df[df["producto"].isin(["Té", "Chocolate"])] # lo mismo, más corto
df.sort_values("unidades", ascending=False).head(3) # top 3
Fíjate en que cada condición va entre paréntesis y se combinan con & (y) y | (o). Es la misma lógica que la función FILTRAR de Excel.
1. ¿Cómo filtras las ventas del Sur con más de 85 unidades?
En pandas se usa & (no and) y cada condición va entre paréntesis.
Crear columnas y limpiar datos
df["importe"] = df["unidades"] * df["precio"] # columna calculada
df["mes"] = df["fecha"].dt.to_period("M") # 2026-01, 2026-02...
df["region"] = df["region"].fillna("Sin región") # rellenar vacíos
df["vendedor"] = df["vendedor"].str.strip().str.title() # limpiar textos
df = df.drop_duplicates() # quitar filas repetidas
Las operaciones se aplican a toda la columna a la vez, sin bucles: es mucho más rápido y legible que recorrer las filas con for.
Para el equivalente de SI de Excel usa numpy.where (numpy se instala junto con pandas):
import numpy as np
df["tipo"] = np.where(df["importe"] >= 1000, "Grande", "Normal")
Resumir: groupby y tablas dinámicas
df.groupby("vendedor")["importe"].sum().sort_values(ascending=False)
df.groupby("region").agg(
ventas=("importe", "sum"),
pedidos=("importe", "count"),
ticket_medio=("importe", "mean"),
)
pd.pivot_table(df, values="importe", index="producto",
columns="mes", aggfunc="sum", fill_value=0)
groupby es el SUMAR.SI.CONJUNTO de pandas; pivot_table, la tabla dinámica. El primer resultado muestra que Ana vendió 4.112,50; Eva, 2.562,50; y Luis, 2.520.
2. ¿Qué hace df.groupby("producto")["unidades"].sum()?
Agrupa las filas por producto y suma la columna unidades de cada grupo.
Unir tablas: el BUSCARV de pandas
metas = pd.DataFrame({"vendedor": ["Ana", "Luis", "Eva"],
"meta": [3000, 3000, 2500]})
resumen = df.groupby("vendedor", as_index=False)["importe"].sum()
resumen = resumen.merge(metas, on="vendedor", how="left")
resumen["cumplimiento"] = (resumen["importe"] / resumen["meta"]).round(3)
print(resumen)
merge une por una columna común. Con how="left" se conservan todas las filas de la tabla izquierda, aunque no encuentren pareja (como un BUSCARV que devuelve vacío). En el ejemplo, Ana cumple su meta al 137%, Eva al 102,5% y Luis se queda en el 84%.
Exportar y graficar
resumen.to_excel("resumen_ventas.xlsx", index=False) # a Excel
resumen.to_csv("resumen_ventas.csv", index=False) # a CSV
import matplotlib.pyplot as plt
por_mes = df.groupby("mes")["importe"].sum()
por_mes.plot(kind="bar", title="Ventas por mes")
plt.ylabel("Importe")
plt.tight_layout()
plt.savefig("ventas_por_mes.png") # o plt.show() para verlo en pantalla
KeyError: 'Region': los nombres de columna distinguen mayúsculas. Revisadf.columns.- Números leídos como texto (por ejemplo "1.250,50"): usa
pd.read_csv(..., decimal=",", thousands="."). - Archivos con tildes que se ven mal: prueba
encoding="utf-8"oencoding="latin-1". - CSV separados por punto y coma:
sep=";".
3. Un CSV exportado de Excel en español usa punto y coma como separador. ¿Cómo lo lees?
El parámetro sep indica el separador de columnas. Por defecto pandas espera comas.
Reto: el informe automático
Usando el archivo de ventas de ejemplo (o uno tuyo), escribe un script informe.py que:
- Cargue los datos, rellene las regiones vacías y calcule el importe.
- Calcule las ventas por región y por producto.
- Identifique el mejor mes y el vendedor con mayor ticket medio.
- Guarde un Excel con dos hojas (región y producto) y un gráfico PNG.
Ver una solución
import pandas as pd
df = pd.read_csv("ventas.csv", parse_dates=["fecha"])
df["region"] = df["region"].fillna("Sin región")
df["importe"] = df["unidades"] * df["precio"]
df["mes"] = df["fecha"].dt.to_period("M")
por_region = df.groupby("region")["importe"].sum().sort_values(ascending=False)
por_producto = df.groupby("producto")["importe"].sum().sort_values(ascending=False)
mejor_mes = df.groupby("mes")["importe"].sum().idxmax()
mejor_ticket = df.groupby("vendedor")["importe"].mean().idxmax()
print(f"Mejor mes: {mejor_mes} · Mayor ticket medio: {mejor_ticket}")
with pd.ExcelWriter("informe.xlsx") as writer:
por_region.to_excel(writer, sheet_name="Region")
por_producto.to_excel(writer, sheet_name="Producto")
ax = por_region.plot(kind="barh", title="Ventas por región")
ax.figure.tight_layout()
ax.figure.savefig("ventas_region.png")
Con los datos de ejemplo, el mejor mes es 2026-03 y el mayor ticket medio es el de Ana.
Resumen
pd.read_csv/pd.read_excelcargan datos;head,infoydescribelos exploran.- Filtra con condiciones entre paréntesis y
&/|; crea columnas operando sobre columnas enteras. groupbyypivot_tableresumen;mergeune tablas.to_excel,to_csvyplotcomunican los resultados.
En la última lección conectarás tus programas con el mundo exterior: APIs web, JSON y automatización de tareas.
Crea tu cuenta, marca tus avances y descarga el certificado al terminar el curso.