Python e IA

Pronóstico de ventas con Python (proyecto principiante)

Proyecto de pronóstico de ventas en Python para principiantes: pandas, una referencia estacional, modelo Holt-Winters, error MAPE y exportación a Excel.

Por Equipo editorial de DashCore HubActualizado 8 min de lectura

Puedes armar un pronóstico de ventas útil en Python con unas 40 líneas de código: cargas las ventas mensuales con pandas, apartas los últimos 12 meses como prueba, comparas una referencia sencilla de "el mismo mes del año pasado" con un modelo Holt-Winters de statsmodels y pronosticas los próximos seis meses. Este proyecto para principiantes recorre cada paso y explica cómo saber si el pronóstico es lo bastante bueno para usarlo.

Lo que necesitas antes de empezar

  • Python 3 con pandas, statsmodels y matplotlib instalados (pip install pandas statsmodels matplotlib). Un notebook de Jupyter es el lugar más cómodo para correrlo.
  • Un CSV con dos columnas: month (una fecha como 2025-01-01) y sales (un número). Una fila por mes, sin huecos.
  • Al menos dos o tres años de historia. Los modelos estacionales necesitan ver cada mes varias veces para aprender el patrón. Con menos datos, quédate con métodos más simples.

Si tus datos están en transacciones diarias, agrúpalos primero por mes. En pandas eso es df.resample("MS", on="order_date")["amount"].sum(), o puedes hacerlo con una tabla dinámica en Excel y exportar el resultado.

Consejo: Pronostica al nivel en que se toman las decisiones. Si el equipo de compras pide mensualmente por categoría, pronostica por mes y por categoría, no por día y por producto. Los niveles más agregados suelen ser más estables y fáciles de pronosticar.

Paso 1: Cargar y revisar los datos

import pandas as pd

df = pd.read_csv("monthly_sales.csv", parse_dates=["month"])
df = df.set_index("month").asfreq("MS")   # MS = inicio de mes

print(df.shape)
print(df["sales"].isna().sum(), "meses faltantes")
print(df.tail())

asfreq("MS") le dice a pandas que los datos son mensuales. Si falta un mes en tu archivo, aparece como una fila vacía (NaN), y la línea siguiente la cuenta. Corrige los huecos antes de modelar: averigua por qué falta un mes en lugar de inventar un número.

Haz también un gráfico de la serie (df["sales"].plot()). Busca tres cosas: una tendencia general hacia arriba o hacia abajo, un patrón que se repite cada año y picos raros, como un pedido grande que no se repetirá. Esos picos pueden distorsionar el pronóstico, así que anótalos y decide con el negocio si conviene ajustarlos.

Paso 2: Separar los datos y crear una referencia

El hábito más importante en pronósticos es probar con datos que el modelo no ha visto. Escondemos los últimos 12 meses, pronosticamos usando solo los datos anteriores y comparamos con lo que realmente pasó.

test_months = 12
train = df.iloc[:-test_months]
test = df.iloc[-test_months:]

# Ingenuo estacional: "este mes se parecerá al mismo mes del año pasado"
naive_forecast = pd.Series(
    train["sales"].iloc[-12:].to_numpy(), index=test.index
)

La referencia ingenua estacional simplemente repite los valores del año anterior. Parece demasiado simple, pero es una comparación justa: si un modelo más sofisticado no la supera, no vale la pena usarlo. El .to_numpy() quita las fechas viejas para que los valores se alineen con los meses de prueba.

Paso 3: Ajustar un modelo Holt-Winters y medir el error

Holt-Winters (también llamado suavizado exponencial triple) estima tres componentes: el nivel actual, la tendencia y el patrón estacional. Los meses recientes pesan más que los antiguos. Es una opción clásica para ventas mensuales con un patrón anual, y pertenece a la misma familia de métodos que usa la función PRONOSTICO.ETS (FORECAST.ETS) de Excel.

from statsmodels.tsa.holtwinters import ExponentialSmoothing

model = ExponentialSmoothing(
    train["sales"],
    trend="add",
    seasonal="add",
    seasonal_periods=12,
).fit()
hw_forecast = model.forecast(test_months)

def mape(actual, predicted):
    return ((actual - predicted).abs() / actual).mean() * 100

print(f"Seasonal naive MAPE: {mape(test['sales'], naive_forecast):.1f}%")
print(f"Holt-Winters MAPE:   {mape(test['sales'], hw_forecast):.1f}%")

El MAPE (error porcentual absoluto medio) es el tamaño promedio del error como porcentaje de las ventas reales. Mientras más bajo, mejor, y es fácil de explicarle a un gerente: "en promedio, el pronóstico falló por alrededor de X %". Tus resultados dependen totalmente de tus datos, así que no los compares con cifras de otros proyectos; compáralos con tu propia referencia.

ParámetroUsa "add" cuando…Usa "mul" cuando…
trendLas ventas crecen más o menos la misma cantidad cada períodoLas ventas crecen más o menos el mismo porcentaje (requiere valores positivos)
seasonalLa variación estacional se mantiene del mismo tamañoLa variación estacional crece a medida que crecen las ventas (requiere valores positivos)

Prueba ambas opciones y quédate con la que tenga menor error de prueba. También puedes usar trend=None si no hay una tendencia clara.

Atajo con IA: Pega tus resultados de MAPE y una descripción del gráfico en un asistente y pide: "Mi modelo Holt-Winters tiene un MAPE de prueba de [X] % y la referencia ingenua estacional tiene [Y] %. Sugiere tres razones por las que el modelo podría estar fallando y tres experimentos concretos para probar, con el código de pandas o statsmodels para cada uno".

Paso 4: Pronosticar el futuro y compartirlo

Cuando estés conforme con los resultados de prueba, vuelve a ajustar el modelo con todos los datos (así aprende de los meses más recientes) y pronostica hacia adelante.

import matplotlib.pyplot as plt

final_model = ExponentialSmoothing(
    df["sales"], trend="add", seasonal="add", seasonal_periods=12
).fit()
future = final_model.forecast(6)

ax = df["sales"].plot(label="Real", figsize=(10, 4))
future.plot(ax=ax, label="Pronóstico", linestyle="--")
ax.set_title("Ventas mensuales y pronóstico a 6 meses")
ax.legend()
plt.tight_layout()
plt.show()

future.round(2).rename("forecast").rename_axis("month").to_csv("sales_forecast.csv")

El CSV se puede abrir directo en Excel o Power BI, donde puedes mostrar lo real y lo pronosticado en el mismo gráfico de líneas. Presenta el pronóstico como una estimación para planear, no como una promesa, y actualízalo cada mes cuando lleguen los datos nuevos.

Errores comunes de principiante

  • Probar con los datos de entrenamiento. Un modelo siempre se ve excelente con datos que ya conoce. Aparta siempre un período de prueba.
  • Ignorar eventos únicos. Las promociones, los quiebres de inventario y las caídas del sistema hay que anotarlos, y a veces ajustarlos, antes de modelar.
  • Pronosticar demasiado lejos. La incertidumbre crece con cada mes. De seis a doce meses es un horizonte razonable para este tipo de modelo.
  • Saltarse la referencia. Sin un punto de comparación, no puedes saber si el modelo aporta valor.

Paso 5: Pronosticar cada categoría en un solo ciclo

Un pronóstico del total es un buen comienzo, pero la mayoría de los equipos planea por categoría, región o tienda. Cuando el método ya funciona con una serie, puedes repetirlo para cada grupo con un ciclo corto. Este ejemplo supone un archivo con tres columnas: month, category y sales, donde todas las categorías tienen la historia completa.

import pandas as pd
from statsmodels.tsa.holtwinters import ExponentialSmoothing

sales = pd.read_csv("sales_by_category.csv", parse_dates=["month"])
results = []

for category, group in sales.groupby("category"):
    series = group.set_index("month")["sales"].asfreq("MS")
    fit = ExponentialSmoothing(
        series, trend="add", seasonal="add", seasonal_periods=12
    ).fit()
    fc = fit.forecast(6).rename("forecast").rename_axis("month").reset_index()
    fc["category"] = category
    results.append(fc)

all_forecasts = pd.concat(results, ignore_index=True)
all_forecasts.to_csv("forecast_by_category.csv", index=False)
print(all_forecasts.head())

El resultado es una tabla larga con una fila por categoría y mes, justo la forma que prefieren Power BI y las tablas dinámicas de Excel. Antes de confiar en ella, repite la prueba del Paso 3 para cada categoría. Algunas se pronosticarán bien; otras, sobre todo las pequeñas o nuevas, quizás no superen la referencia ingenua estacional. Para esas es perfectamente válido usar la referencia o un promedio simple. Un proceso que combina métodos según la categoría, elegidos por su error de prueba, es más honesto que forzar un solo modelo para todo.

Pon atención a las categorías con muy pocas ventas o muchos meses en cero. El suavizado exponencial funciona mejor con series de nivel estable, así que la demanda intermitente suele necesitar otros métodos o un nivel de agregación mayor.

Próximos pasos

Corre este proyecto con tus propios datos de ventas y luego intenta pronosticar por región o por categoría de producto. Si Python es nuevo para ti, empieza con Python para análisis de datos y nuestro tutorial de pandas para usuarios de Excel. Para comparar con un método sin código, lee pronósticos en Excel con PRONOSTICO.ETS, y cuando quieras modelos más avanzados, mira machine learning básico para analistas BI.

Mira: lecciones en video

Time Series Forecasting with XGBoost - Predict Store Revenue Using Python and Machine Learningpor Onur Baltaci · Ver en YouTube ↗Video en inglés — activa los subtítulos traducidos en YouTube si los necesitas.

Preguntas frecuentes

¿Cuántos datos necesito para pronosticar ventas en Python?

Para un modelo mensual estacional como Holt-Winters, procura tener al menos dos o tres años completos. Con menos historia, es más seguro usar una tendencia simple o un promedio móvil.

¿Qué es un buen MAPE para un pronóstico de ventas?

No hay una cifra universal; depende de qué tan variables sean tus ventas. La prueba práctica es si tu modelo supera una referencia sencilla, como repetir los valores del año anterior.

¿Holt-Winters es lo mismo que PRONOSTICO.ETS de Excel?

Pertenecen a la misma familia de métodos de suavizado exponencial, así que los resultados suelen parecerse pero no son idénticos. Python te da más control sobre los parámetros y las pruebas.

¿Puedo usar este pronóstico en Power BI?

Sí. Exporta el pronóstico a CSV como se muestra, o corre el script con la integración de Python de Power BI, y combínalo con los datos reales en un gráfico de líneas.

¿Aprendes con la Academia?
Marca esta lección como completada para seguir tu progreso.
Hacer el quiz