datarekha

Prophet

Learn how Meta's Prophet decomposes a time series into trend, seasonality, and holiday effects — and why its analyst-friendly API makes it a go-to for business forecasting.

9 min read Intermediate Time Series Lesson 12 of 14

What you'll learn

  • Prophet's additive model: trend + seasonality + holidays + noise, fit by curve-fitting rather than Box-Jenkins
  • Automatic changepoint detection: how Prophet finds trend shifts without manual parameter tuning
  • The Prophet API: preparing a ds/y DataFrame, calling fit and predict, and adding holidays or regressors

Before you start

Why Prophet exists

ARIMA is powerful, but it demands careful stationarity testing, ACF/PACF reading, and manual order selection. Scale that to dozens of series with business calendars and irregular gaps, and the workflow becomes expensive.

Prophet — released by Meta’s Core Data Science team in 2017 — was designed for exactly that situation. Its core insight is that most business time series are well described by a sum of interpretable components. Rather than modelling autocorrelation structure, Prophet fits a regression-style curve to each component separately. The result:

  • Gaps and outliers affect the curve-fit much less than they affect ARIMA.
  • Seasonality and holidays are first-class inputs, not afterthoughts.
  • Non-statisticians can configure and inspect results without reading a textbook.

Prophet’s additive model

Prophet decomposes every forecast into four pieces:

y(t) = trend(t) + seasonality(t) + holidays(t) + noise

Each term is explained below. The diagram after this section shows how they combine visually.

Trend with automatic changepoints

A changepoint is a moment when the underlying growth rate shifts — a product launch, a policy change, a market shock. In Prophet the trend is piecewise-linear (or optionally piecewise-logistic for series with a natural ceiling). Prophet scans a set of candidate changepoint locations — by default the first 80 % of the training data — and uses a sparse prior to select only the ones actually supported by the data. You rarely need to specify them by hand.

from prophet import Prophet

m = Prophet()

You can override defaults:

m = Prophet(
    growth="logistic",          # use when the series has a known cap
    changepoint_prior_scale=0.05,  # lower = smoother trend
    n_changepoints=25,          # number of candidate changepoints
)

Seasonality via Fourier terms

Rather than dummy variables, Prophet models seasonality with Fourier series — sums of sine and cosine waves at the relevant period. Yearly seasonality uses 10 Fourier pairs by default; weekly uses 3. This makes the seasonal pattern smooth and continuous, which is realistic for most business phenomena. You can add custom seasonalities (monthly, quarterly) with a single method call.

Holiday effects

Holiday effects are short, sharp pulses — a sales spike on a public holiday, a traffic drop on a long weekend. Prophet lets you pass a DataFrame of known dates, and it estimates a separate coefficient for each holiday window. This is far more reliable than hoping the model learns it from data alone.

Noise

The residual noise term absorbs everything not explained by the three structured components. Prophet assumes it is white noise; if your residuals show remaining autocorrelation, that is a signal to add a custom seasonality or regressor.

The inline-SVG diagram

Trendpiecewise-linear+ changepointsSeasonalityFourier terms(yearly/weekly)Holidaysknown datepulses++y(t)Forecast(+ noise)Componentsplot: inspecteach piece
Prophet sums trend, seasonality, and holiday effects into a single forecast. Each component can be plotted and inspected independently.

The Prophet API

Step 1 — Prepare the DataFrame

Prophet requires exactly two columns: ds (datestamp, as a pandas datetime) and y (the numeric target). Column names are mandatory; Prophet will raise an error if they are absent.

import pandas as pd
from prophet import Prophet

df = pd.read_csv("daily_sales.csv", parse_dates=["date"])
df = df.rename(columns={"date": "ds", "sales": "y"})

Missing rows are fine — Prophet interpolates across gaps during curve fitting.

Step 2 — Fit

m = Prophet(yearly_seasonality=True, weekly_seasonality=True)
m.fit(df)

Fitting calls Stan under the hood via L-BFGS (default) or MCMC for full uncertainty quantification.

Step 3 — Build the future DataFrame and predict

make_future_dataframe appends periods rows of future dates to the training dates. Calling predict returns a DataFrame with one row per date and columns including yhat (point forecast), yhat_lower, and yhat_upper (uncertainty intervals).

future = m.make_future_dataframe(periods=90, freq="D")
forecast = m.predict(future)

print(forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail())

Step 4 — Plot components

fig = m.plot_components(forecast)

This renders separate panels for trend, weekly seasonality, yearly seasonality, and any holidays — which is where Prophet earns its “interpretable” reputation.

Adding holidays

Pass a DataFrame with columns holiday (name string) and ds (date). Prophet fits a separate coefficient for each named holiday.

from prophet.make_holidays import make_holidays_df

holidays = make_holidays_df(year_list=[2023, 2024, 2025], country="US")
m = Prophet(holidays=holidays)
m.fit(df)

For non-standard events (a product launch, a campaign start), add them to the same holidays DataFrame with a custom name.

Adding external regressors

A regressor is an additional time-varying input — a price index, a temperature reading, a promotional flag — that you believe drives y. Prophet treats it as another additive term.

m = Prophet()
m.add_regressor("promo_flag")
m.fit(df)   # df must also contain a column named promo_flag

future["promo_flag"] = 0   # fill in future values of the regressor
forecast = m.predict(future)

The regressor must be known for the forecast horizon, which is the main practical constraint.

Strengths and limits

Where Prophet shines

  • Analyst-friendly: a non-statistician can configure seasonalities and holidays without touching ACF/PACF plots.
  • Interpretable components: the components plot separates what is trend from what is seasonal, making results auditable.
  • Robust to gaps and outliers: curve-fitting degrades gracefully; an ARIMA fit would fail or need imputation.
  • Scales horizontally: the same API runs on hundreds of product lines with minimal per-series tuning.

Real limits

Putting it together: a minimal working example

import pandas as pd
from prophet import Prophet

df = pd.read_csv("daily_sales.csv", parse_dates=["date"])
df = df.rename(columns={"date": "ds", "sales": "y"})

m = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    changepoint_prior_scale=0.05,
)
m.fit(df)

future = m.make_future_dataframe(periods=90, freq="D")
forecast = m.predict(future)

fig1 = m.plot(forecast)
fig2 = m.plot_components(forecast)

Run this, look at the components plot, sanity-check the trend, then evaluate on a held-out window before calling the model production-ready.


Quick check

0/3
Q1What does Prophet use instead of Box-Jenkins autocorrelation fitting to model seasonality?
Q2You call m.make_future_dataframe(periods=30) and then m.predict(future). What does the returned DataFrame's yhat column contain?
Q3A retail team builds a Prophet model for weekly store visits. The components plot shows a huge positive trend uptick in the final two weeks of training, but the business team sees no real-world cause. What is the most likely explanation, and what should the team do?

Practice this in an interview

All questions
When would you choose Prophet over ARIMA for a forecasting problem?

Prophet is a curve-fitting model that decomposes the series into trend, seasonality, and holidays; it handles missing data, multiple seasonalities, and non-uniform time grids with minimal tuning and is accessible to non-statisticians. ARIMA is a statistical model based on autocorrelation structure; it is more appropriate when the series is short, noise is small, and you need principled uncertainty intervals from an explicit stochastic process.

What are trend, seasonality, and residual in time series decomposition, and how do you extract them?

Decomposition separates a series into a trend component (long-run direction), a seasonal component (periodic, fixed-period pattern), and a residual (everything left over). Additive decomposition sums the three; multiplicative decomposition multiplies them, which is appropriate when seasonal swings grow with the level.

What is exponential smoothing, and how does Holt-Winters extend it to handle trend and seasonality?

Simple exponential smoothing computes a weighted average of all past observations where weights decay geometrically, controlled by a single smoothing parameter alpha. Holt's method adds a trend component with a second parameter beta; Holt-Winters (ETS) adds a seasonal component with a third parameter gamma, making it a strong baseline for series with both trend and seasonality.

When would you use MAPE versus MASE to evaluate a forecast, and what are the failure modes of each?

MAPE (Mean Absolute Percentage Error) is intuitive and scale-free but breaks when actuals are near zero and penalises under-forecasts more than over-forecasts. MASE (Mean Absolute Scaled Error) solves both issues by scaling errors against a naive seasonal benchmark, making it valid even with zero values and comparable across series with different scales.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Explore further

Related lessons

Skip to content