Data

Historic

Daily count of:

  • Incidents (Incidents).
  • Responses (Responses).
  • Calls (Calls and Calls_Other).
  • Sickness (Sickness).
  • Unplanned absence (Unplanned).

For the whole trust ['Trust'] and for each region ['Gloucestershire', 'BNSSG', 'Cornwall', 'Dorset', 'BSW', 'Somerset', 'Devon'].

Holidays

Bank holidays and school holiday dates per region, plus lower-upper window defining how many days before/after holiday the effect should be felt.

Models

Prophet

Version in use

predict_prophet_stf

  • changepoint_range is 1 for responses and 0.8 for other outcomes.
  • changepoint_prior_scale is 0.5 for responses and 0.05 for other outcomes.
  • Weekly and yearly seasonality.
if metric == "Responses" and alter_forecast == 1:
    changepoint_range_value = 1
    changepoint_prior_scale = 0.5
else:
    # default values
    changepoint_range_value = 0.8
    changepoint_prior_scale = 0.05

prophet = Prophet(
    holidays=holiday,
    changepoint_range=changepoint_range_value,
    changepoint_prior_scale=changepoint_prior_scale,
    interval_width=1 - 0.05,
    daily_seasonality=False,
    weekly_seasonality=True,
    yearly_seasonality=True,
)

Version currently not in use

Prophet model within ProphetARIMAEnsemble._fit_prophet().

prophet_default_alpha=0.05,

...

self.prophet_model = Prophet(
    holidays=self.holidays,
    interval_width=1 - alpha,
    daily_seasonality=False,
)  # , changepoint_range=1)

Same:

  • Same holidays
  • Same interval_width.
  • Should be same seasonality (by default, prophet will do weekly and yearly if sufficient data (i.e., 2+ weeks and 2+ years)).
  • changepoint_range for most metrics (as defaults to 0.8)
  • changepoint_prior_scale for most metrics (as defaults to 0.05).

Different:

  • The only difference is that Responses uses a custom changepoint_range and changepoint_prior_scale.

ARIMA

ARIMA model within the ensemble (ProphetARIMAEnsemble, get_best_arima_parameters):

  • Regression with ARIMA errors.
  • Non-seasonal order (p,d,q) = (1,1,3): 1 AR term, first-order differencing, 3 MA terms.
  • Seasonal order (P,D,Q,m) = (1,0,1,7): weekly seasonality with 1 seasonal AR term, 1 seasonal MA term, and no seasonal differencing.
  • Single binary holiday dummy flags whether a date falls in a holiday window. Collapses all holidays (e.g., New Years Day, Easter, Bank Holiday) into one undifferentiated effect rather than modelling each holiday type separately.
  • enforce_stationarity=False.

Ensemble

default_ensemble

The Prophet forecast from ProphetARIMAEnsemble is replaced with values generated by running predict_prophet_stf.

mask = (prophet_forecast.currency == curr) & (prophet_forecast.county == county)
df["prophet_mean"] = prophet_forecast.loc[mask].yhat.values
df["prophet_lower_95"] = prophet_forecast.loc[mask].yhat_lower.values
df["prophet_upper_95"] = prophet_forecast.loc[mask].yhat_upper.values

The point forecast error (y_hat) and prediction intervals (yhat_lower_95 and yhat_upper_95) are determined by finding the mean of the Prophet and ARIMA results.

df['yhat'] = (df['prophet_mean'].values + df['arima_mean'].values ) / 2
df['yhat_lower_95'] = (df['prophet_lower_95'].values + df['arima_lower_95'].values ) / 2
df['yhat_upper_95'] = (df['prophet_upper_95'].values + df['arima_upper_95'].values ) / 2

Forecast

42-day-ahead forecast. Starting point is last Monday (i.e., next Monday, minus seven days).

Responses and incidents are forecast for each region and for whole trust. Calls, sickness and unplanned absence are all only forecast at the trust level.

The forecast dataframe contains:

  • ARIMA results for Calls and Responses.
  • Ensemble results for all other outcomes.