Saturating Forecasts

Saturating Growth

example_wp_log_R.csv
import pandas as pd
from fbprophet import Prophet

from fbprophet.plot import plot_plotly
import plotly.offline as py
py.init_notebook_mode()


url = "https://nextjournal.com/data/QmVbsLznbDsfbVnZBxR4JsFREXbvv63LkNytvk1fTxe9vu?content-type=text%2Fcsv&filename=example_wp_log_R.csv"
df = pd.read_csv(url)

df['cap'] = 8.5

m = Prophet(growth='logistic')
m.fit(df)

future = m.make_future_dataframe(periods=1826)
future['cap'] = 8.5
fcst = m.predict(future)
fig = m.plot(fcst)

Saturating Minimum

df['y'] = 10 - df['y']
df['cap'] = 6
df['floor'] = 1.5
future['cap'] = 6
future['floor'] = 1.5
m = Prophet(growth='logistic')
m.fit(df)
fcst = m.predict(future)
fig = m.plot(fcst)

Trend Changepoints

Automatic changepoint detection in Prophet

from fbprophet.plot import add_changepoints_to_plot
forecast = fcst

fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)

Adjusting trend flexibility

m = Prophet(changepoint_prior_scale=0.5)
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)

Decreasing it will make the trend less flexible:

m = Prophet(changepoint_prior_scale=0.001)
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)

Specifying the locations of the changepoints

m = Prophet(changepoints=['2014-01-01'])
forecast = m.fit(df).predict(future)
fig = m.plot(forecast)

Seasonality, Holiday Effects, And Regressors

Modeling Holidays and Special Events

playoffs = pd.DataFrame({
  'holiday': 'playoff',
  'ds': pd.to_datetime(['2008-01-13', '2009-01-03', '2010-01-16',
                        '2010-01-24', '2010-02-07', '2011-01-08',
                        '2013-01-12', '2014-01-12', '2014-01-19',
                        '2014-02-02', '2015-01-11', '2016-01-17',
                        '2016-01-24', '2016-02-07']),
  'lower_window': 0,
  'upper_window': 1,
})
superbowls = pd.DataFrame({
  'holiday': 'superbowl',
  'ds': pd.to_datetime(['2010-02-07', '2014-02-02', '2016-02-07']),
  'lower_window': 0,
  'upper_window': 1,
})
holidays = pd.concat((playoffs, superbowls))


m = Prophet(holidays=holidays)
forecast = m.fit(df).predict(future)

forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
        ['ds', 'playoff', 'superbowl']][-10:]
dsplayoffsuperbowl
21682014-02-02-0.041448910794072-0.061800063179915085
21692014-02-03-0.026776028605230330.031581560092876944
25102015-01-11-0.0414489107940720.0
25112015-01-12-0.026776028605230330.0
28792016-01-17-0.0414489107940720.0
28802016-01-18-0.026776028605230330.0
28862016-01-24-0.0414489107940720.0
28872016-01-25-0.026776028605230330.0
29002016-02-07-0.041448910794072-0.061800063179915085
29012016-02-08-0.026776028605230330.031581560092876944
10 items
fig = m.plot_components(forecast)

Built-in Country Holidays

m = Prophet(holidays=holidays)
m.add_country_holidays(country_name='US')
m.fit(df)

m.train_holiday_names
forecast = m.predict(future)
fig = m.plot_components(forecast)

Fourier Order for Seasonalities

from fbprophet.plot import plot_yearly
m = Prophet().fit(df)
a = plot_yearly(m)
m = Prophet(yearly_seasonality=20).fit(df)
a = plot_yearly(m)

Specifying Custom Seasonalities

m = Prophet(weekly_seasonality=False)
m.add_seasonality(name='monthly', period=30.5, fourier_order=5)
forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)

Seasonalities that depend on other factors

def is_nfl_season(ds):
    date = pd.to_datetime(ds)
    return (date.month > 8 or date.month < 2)

df['on_season'] = df['ds'].apply(is_nfl_season)
df['off_season'] = ~df['ds'].apply(is_nfl_season)

m = Prophet(weekly_seasonality=False)
m.add_seasonality(name='weekly_on_season', period=7, fourier_order=3, condition_name='on_season')
m.add_seasonality(name='weekly_off_season', period=7, fourier_order=3, condition_name='off_season')

future['on_season'] = future['ds'].apply(is_nfl_season)
future['off_season'] = ~future['ds'].apply(is_nfl_season)
forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)

Prior scale for holidays and seasonality

m = Prophet(holidays=holidays, holidays_prior_scale=0.05).fit(df)
forecast = m.predict(future)
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
    ['ds', 'playoff', 'superbowl']][-10:]
m = Prophet()
m.add_seasonality(
    name='weekly', period=7, fourier_order=3, prior_scale=0.1)
<fbprophet.fo...x7fae7e917e10>

Additional regressors

def nfl_sunday(ds):
    date = pd.to_datetime(ds)
    if date.weekday() == 6 and (date.month > 8 or date.month < 2):
        return 1
    else:
        return 0
df['nfl_sunday'] = df['ds'].apply(nfl_sunday)

m = Prophet()
m.add_regressor('nfl_sunday')
m.fit(df)

future['nfl_sunday'] = future['ds'].apply(nfl_sunday)

forecast = m.predict(future)
fig = m.plot_components(forecast)

Multiplicative Seasonality

example_air_passengers.csv
url = "https://nextjournal.com/data/QmNkm2vmD7CDajrKYqDkusji6aR7bhETyjvZXoJ15Vq194?content-type=text%2Fcsv&filename=example_air_passengers.csv"
df = pd.read_csv(url)
m = Prophet()
m.fit(df)
future = m.make_future_dataframe(50, freq='MS')
forecast = m.predict(future)
fig = m.plot(forecast)
m = Prophet(seasonality_mode='multiplicative')
m.fit(df)
forecast = m.predict(future)
fig = m.plot(forecast)
fig = m.plot_components(forecast)
m = Prophet(seasonality_mode='multiplicative')
m.add_seasonality('quarterly', period=91.25, fourier_order=8, mode='additive')
m.add_regressor('regressor', mode='additive')
<fbprophet.fo...x7fae7dea52b0>

Uncertainty Intervals

Uncertainty in the trend

forecast = Prophet(interval_width=0.95).fit(df).predict(future)

Uncertainty in seasonality

m = Prophet(mcmc_samples=300)
forecast = m.fit(df).predict(future)
fig = m.plot_components(forecast)

Outliers

example_wp_log_R_outliers1.csv
url = "https://nextjournal.com/data/QmasyK2jtb8dyCebuQQaDMKmFtsb9wQHkUCqBSGdAfs3rM?content-type=text%2Fcsv&filename=example_wp_log_R_outliers1.csv"
df = pd.read_csv(url)
m = Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=1096)
forecast = m.predict(future)
fig = m.plot(forecast)
df.loc[(df['ds'] > '2010-01-01') & (df['ds'] < '2011-01-01'), 'y'] = None
model = Prophet().fit(df)
fig = model.plot(model.predict(future))
example_wp_log_R_outliers2.csv
url = "https://nextjournal.com/data/QmPYAGdQsQyi5QkuzUWi4x4u3Bu82ew8uD3ANhEUhp7tDb?content-type=text%2Fcsv&filename=example_wp_log_R_outliers2.csv"
df = pd.read_csv(url)
m = Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=1096)
forecast = m.predict(future)
fig = m.plot(forecast)
df.loc[(df['ds'] > '2015-06-01') & (df['ds'] < '2015-06-30'), 'y'] = None
m = Prophet().fit(df)
fig = m.plot(m.predict(future))

Non-Daily Data

example_yosemite_temps.csv

Sub-daily data

url = "https://nextjournal.com/data/QmbKkFrpdLSFFXoMg7LXX7FHXv5jPRY6ohurkzpHz9JXLM?content-type=text%2Fcsv&filename=example_yosemite_temps.csv"
df = pd.read_csv(url)
m = Prophet(changepoint_prior_scale=0.01).fit(df)
future = m.make_future_dataframe(periods=300, freq='H')
fcst = m.predict(future)
fig = m.plot(fcst)
fig = m.plot_components(fcst)

Data with regular gaps

df2 = df.copy()
df2['ds'] = pd.to_datetime(df2['ds'])
df2 = df2[df2['ds'].dt.hour < 6]
m = Prophet().fit(df2)
future = m.make_future_dataframe(periods=300, freq='H')
fcst = m.predict(future)
fig = m.plot(fcst)
future2 = future.copy()
future2 = future2[future2['ds'].dt.hour < 6]
fcst = m.predict(future2)
fig = m.plot(fcst)
example_retail_sales.csv

Monthly data

url = "https://nextjournal.com/data/QmVAEmz1VSSESVw6aJsskdSacEPJV2m4BvJNoUCWzcApu1?content-type=text%2Fcsv&filename=example_retail_sales.csv"
df = pd.read_csv(url)
m = Prophet(seasonality_mode='multiplicative').fit(df)
future = m.make_future_dataframe(periods=3652)
fcst = m.predict(future)
fig = m.plot(fcst)
m = Prophet(seasonality_mode='multiplicative', mcmc_samples=300).fit(df)
fcst = m.predict(future)
fig = m.plot_components(fcst)
future = m.make_future_dataframe(periods=120, freq='M')
fcst = m.predict(future)
fig = m.plot(fcst)

Diagnostics

from fbprophet.diagnostics import cross_validation
df_cv = cross_validation(m, initial='730 days', period='180 days', horizon = '365 days')
df_cv.head()