Merge pull request #296 from facebookincubator/v0.2
Merge in v0.2 branch
|
|
@ -1,16 +1,16 @@
|
|||
Package: prophet
|
||||
Title: Automatic Forecasting Procedure
|
||||
Version: 0.1.1
|
||||
Date: 2017-04-17
|
||||
Version: 0.2
|
||||
Date: 2017-09-02
|
||||
Authors@R: c(
|
||||
person("Sean", "Taylor", email = "sjt@fb.com", role = c("cre", "aut")),
|
||||
person("Ben", "Letham", email = "bletham@fb.com", role = "aut")
|
||||
)
|
||||
Description: Implements a procedure for forecasting time series data based on
|
||||
an additive model where non-linear trends are fit with yearly and weekly
|
||||
seasonality, plus holidays. It works best with daily periodicity data with
|
||||
at least one year of historical data. Prophet is robust to missing data,
|
||||
shifts in the trend, and large outliers.
|
||||
an additive model where non-linear trends are fit with yearly and weekly
|
||||
seasonality, plus holidays. It works best with daily periodicity data with
|
||||
at least one year of historical data. Prophet is robust to missing data,
|
||||
shifts in the trend, and large outliers.
|
||||
Depends:
|
||||
R (>= 3.2.3),
|
||||
Rcpp (>= 0.12.0)
|
||||
|
|
@ -22,9 +22,7 @@ Imports:
|
|||
rstan (>= 2.14.0),
|
||||
scales,
|
||||
stats,
|
||||
tidyr (>= 0.6.1),
|
||||
utils,
|
||||
zoo
|
||||
tidyr (>= 0.6.1)
|
||||
Suggests:
|
||||
knitr,
|
||||
testthat,
|
||||
|
|
@ -33,3 +31,4 @@ License: BSD_3_clause + file LICENSE
|
|||
LazyData: true
|
||||
RoxygenNote: 6.0.1
|
||||
VignetteBuilder: knitr
|
||||
SystemRequirements: C++11
|
||||
|
|
|
|||
|
|
@ -2,9 +2,15 @@
|
|||
|
||||
S3method(plot,prophet)
|
||||
S3method(predict,prophet)
|
||||
export(add_regressor)
|
||||
export(add_seasonality)
|
||||
export(cross_validation)
|
||||
export(fit.prophet)
|
||||
export(make_future_dataframe)
|
||||
export(plot_forecast_component)
|
||||
export(predictive_samples)
|
||||
export(prophet)
|
||||
export(prophet_plot_components)
|
||||
export(simulated_historical_forecasts)
|
||||
import(Rcpp)
|
||||
importFrom(dplyr,"%>%")
|
||||
|
|
|
|||
144
R/R/diagnostics.R
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
## Copyright (c) 2017-present, Facebook, Inc.
|
||||
## All rights reserved.
|
||||
|
||||
## This source code is licensed under the BSD-style license found in the
|
||||
## LICENSE file in the root directory of this source tree. An additional grant
|
||||
## of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
## Makes R CMD CHECK happy due to dplyr syntax below
|
||||
globalVariables(c(
|
||||
"ds", "y", "cap", "yhat", "yhat_lower", "yhat_upper"))
|
||||
|
||||
#' Generate cutoff dates
|
||||
#'
|
||||
#' @param df Dataframe with historical data
|
||||
#' @param horizon timediff forecast horizon
|
||||
#' @param k integer number of forecast points
|
||||
#' @param period timediff Simulated forecasts are done with this period.
|
||||
#'
|
||||
#' @return Array of datetimes
|
||||
#'
|
||||
#' @keywords internal
|
||||
generate_cutoffs <- function(df, horizon, k, period) {
|
||||
# Last cutoff is (latest date in data) - (horizon).
|
||||
cutoff <- max(df$ds) - horizon
|
||||
if (cutoff < min(df$ds)) {
|
||||
stop('Less data than horizon.')
|
||||
}
|
||||
tzone <- attr(cutoff, "tzone") # Timezone is wiped by putting in array
|
||||
result <- c(cutoff)
|
||||
if (k > 1) {
|
||||
for (i in 2:k) {
|
||||
cutoff <- cutoff - period
|
||||
# If data does not exist in data range (cutoff, cutoff + horizon]
|
||||
if (!any((df$ds > cutoff) & (df$ds <= cutoff + horizon))) {
|
||||
# Next cutoff point is 'closest date before cutoff in data - horizon'
|
||||
closest.date <- max(df$ds[df$ds <= cutoff])
|
||||
cutoff <- closest.date - horizon
|
||||
}
|
||||
if (cutoff < min(df$ds)) {
|
||||
warning('Not enough data for requested number of cutoffs! Using ', i)
|
||||
break
|
||||
}
|
||||
result <- c(result, cutoff)
|
||||
}
|
||||
}
|
||||
# Reset timezones
|
||||
attr(result, "tzone") <- tzone
|
||||
return(rev(result))
|
||||
}
|
||||
|
||||
#' Simulated historical forecasts.
|
||||
#'
|
||||
#' Make forecasts from k historical cutoff points, working backwards from
|
||||
#' (end - horizon) with a spacing of period between each cutoff.
|
||||
#'
|
||||
#' @param model Fitted Prophet model.
|
||||
#' @param horizon Integer size of the horizon
|
||||
#' @param units String unit of the horizon, e.g., "days", "secs".
|
||||
#' @param k integer number of forecast points
|
||||
#' @param period Integer amount of time between cutoff dates. Same units as
|
||||
#' horizon. If not provided, will use 0.5 * horizon.
|
||||
#'
|
||||
#' @return A dataframe with the forecast, actual value, and cutoff date.
|
||||
#'
|
||||
#' @export
|
||||
simulated_historical_forecasts <- function(model, horizon, units, k,
|
||||
period = NULL) {
|
||||
df <- model$history
|
||||
horizon <- as.difftime(horizon, units = units)
|
||||
if (is.null(period)) {
|
||||
period <- horizon / 2
|
||||
} else {
|
||||
period <- as.difftime(period, units = units)
|
||||
}
|
||||
cutoffs <- generate_cutoffs(df, horizon, k, period)
|
||||
predicts <- data.frame()
|
||||
for (i in 1:length(cutoffs)) {
|
||||
cutoff <- cutoffs[i]
|
||||
# Copy the model
|
||||
m <- prophet_copy(model, cutoff)
|
||||
# Train model
|
||||
history.c <- dplyr::filter(df, ds <= cutoff)
|
||||
m <- fit.prophet(m, history.c)
|
||||
# Calculate yhat
|
||||
df.predict <- dplyr::filter(df, ds > cutoff, ds <= cutoff + horizon)
|
||||
columns <- c('ds')
|
||||
if (m$growth == 'logistic') {
|
||||
columns <- c(columns, 'cap')
|
||||
if (m$logistic.floor) {
|
||||
columns <- c(columns, 'floor')
|
||||
}
|
||||
}
|
||||
future <- df[columns]
|
||||
yhat <- stats::predict(m, future)
|
||||
# Merge yhat, y, and cutoff.
|
||||
df.c <- dplyr::inner_join(df.predict, yhat, by = "ds")
|
||||
df.c <- dplyr::select(df.c, ds, y, yhat, yhat_lower, yhat_upper)
|
||||
df.c$cutoff <- cutoff
|
||||
predicts <- rbind(predicts, df.c)
|
||||
}
|
||||
return(predicts)
|
||||
}
|
||||
|
||||
#' Cross-validation for time series.
|
||||
#'
|
||||
#' Computes forecasts from historical cutoff points. Beginning from initial,
|
||||
#' makes cutoffs with a spacing of period up to (end - horizon).
|
||||
#'
|
||||
#' When period is equal to the time interval of the data, this is the
|
||||
#' technique described in https://robjhyndman.com/hyndsight/tscv/ .
|
||||
#'
|
||||
#' @param model Fitted Prophet model.
|
||||
#' @param horizon Integer size of the horizon
|
||||
#' @param units String unit of the horizon, e.g., "days", "secs".
|
||||
#' @param period Integer amount of time between cutoff dates. Same units as
|
||||
#' horizon. If not provided, 0.5 * horizon is used.
|
||||
#' @param initial Integer size of the first training period. If not provided,
|
||||
#' 3 * horizon is used. Same units as horizon.
|
||||
#'
|
||||
#' @return A dataframe with the forecast, actual value, and cutoff date.
|
||||
#'
|
||||
#' @export
|
||||
cross_validation <- function(
|
||||
model, horizon, units, period = NULL, initial = NULL) {
|
||||
te <- max(model$history$ds)
|
||||
ts <- min(model$history$ds)
|
||||
if (is.null(period)) {
|
||||
period <- 0.5 * horizon
|
||||
}
|
||||
if (is.null(initial)) {
|
||||
initial <- 3 * horizon
|
||||
}
|
||||
horizon.dt <- as.difftime(horizon, units = units)
|
||||
initial.dt <- as.difftime(initial, units = units)
|
||||
period.dt <- as.difftime(period, units = units)
|
||||
k <- ceiling(
|
||||
as.double((te - horizon.dt) - (ts + initial.dt), units='secs') /
|
||||
as.double(period.dt, units = 'secs')
|
||||
)
|
||||
if (k < 1) {
|
||||
stop('Not enough data for specified horizon, period, and initial.')
|
||||
}
|
||||
return(simulated_historical_forecasts(model, horizon, units, k, period))
|
||||
}
|
||||
970
R/R/prophet.R
|
|
@ -7,7 +7,7 @@ data {
|
|||
matrix[T, S] A; // Split indicators
|
||||
real t_change[S]; // Index of changepoints
|
||||
matrix[T,K] X; // season vectors
|
||||
real<lower=0> sigma; // scale on seasonality prior
|
||||
vector[K] sigmas; // scale on seasonality prior
|
||||
real<lower=0> tau; // scale on changepoints prior
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ model {
|
|||
m ~ normal(0, 5);
|
||||
delta ~ double_exponential(0, tau);
|
||||
sigma_obs ~ normal(0, 0.5);
|
||||
beta ~ normal(0, sigma);
|
||||
beta ~ normal(0, sigmas);
|
||||
|
||||
// Likelihood
|
||||
y ~ normal((k + A * delta) .* t + (m + A * gamma) + X * beta, sigma_obs);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ data {
|
|||
matrix[T, S] A; // Split indicators
|
||||
real t_change[S]; // Index of changepoints
|
||||
matrix[T,K] X; // season vectors
|
||||
real<lower=0> sigma; // scale on seasonality prior
|
||||
vector[K] sigmas; // scale on seasonality prior
|
||||
real<lower=0> tau; // scale on changepoints prior
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ model {
|
|||
m ~ normal(0, 5);
|
||||
delta ~ double_exponential(0, tau);
|
||||
sigma_obs ~ normal(0, 0.1);
|
||||
beta ~ normal(0, sigma);
|
||||
beta ~ normal(0, sigmas);
|
||||
|
||||
// Likelihood
|
||||
y ~ normal(cap ./ (1 + exp(-(k + A * delta) .* (t - (m + A * gamma)))) + X * beta, sigma_obs);
|
||||
|
|
|
|||
24
R/man/add_group_component.Rd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{add_group_component}
|
||||
\alias{add_group_component}
|
||||
\title{Adds a component with given name that contains all of the components
|
||||
in group.}
|
||||
\usage{
|
||||
add_group_component(components, name, group)
|
||||
}
|
||||
\arguments{
|
||||
\item{components}{Dataframe with components.}
|
||||
|
||||
\item{name}{Name of new group component.}
|
||||
|
||||
\item{group}{List of components that form the group.}
|
||||
}
|
||||
\value{
|
||||
Dataframe with components.
|
||||
}
|
||||
\description{
|
||||
Adds a component with given name that contains all of the components
|
||||
in group.
|
||||
}
|
||||
\keyword{internal}
|
||||
31
R/man/add_regressor.Rd
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{add_regressor}
|
||||
\alias{add_regressor}
|
||||
\title{Add an additional regressor to be used for fitting and predicting.}
|
||||
\usage{
|
||||
add_regressor(m, name, prior.scale = NULL, standardize = "auto")
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{name}{String name of the regressor}
|
||||
|
||||
\item{prior.scale}{Float scale for the normal prior. If not provided,
|
||||
holidays.prior.scale will be used.}
|
||||
|
||||
\item{standardize}{Bool, specify whether this regressor will be standardized
|
||||
prior to fitting. Can be 'auto' (standardize if not binary), True, or
|
||||
False.}
|
||||
}
|
||||
\value{
|
||||
The prophet model with the regressor added.
|
||||
}
|
||||
\description{
|
||||
The dataframe passed to `fit` and `predict` will have a column with the
|
||||
specified name to be used as a regressor. When standardize='auto', the
|
||||
regressor will be standardized unless it is binary. The regression
|
||||
coefficient is given a prior with the specified scale parameter.
|
||||
Decreasing the prior scale will add additional regularization. If no
|
||||
prior scale is provided, holidays.prior.scale will be used.
|
||||
}
|
||||
33
R/man/add_seasonality.Rd
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{add_seasonality}
|
||||
\alias{add_seasonality}
|
||||
\title{Add a seasonal component with specified period, number of Fourier
|
||||
components, and prior scale.}
|
||||
\usage{
|
||||
add_seasonality(m, name, period, fourier.order, prior.scale = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{name}{String name of the seasonality component.}
|
||||
|
||||
\item{period}{Float number of days in one period.}
|
||||
|
||||
\item{fourier.order}{Int number of Fourier components to use.}
|
||||
|
||||
\item{prior.scale}{Float prior scale for this component.}
|
||||
}
|
||||
\value{
|
||||
The prophet model with the seasonality added.
|
||||
}
|
||||
\description{
|
||||
Increasing the number of Fourier components allows the seasonality to change
|
||||
more quickly (at risk of overfitting). Default values for yearly and weekly
|
||||
seasonalities are 10 and 3 respectively.
|
||||
}
|
||||
\details{
|
||||
Increasing prior scale will allow this seasonality component more
|
||||
flexibility, decreasing will dampen it. If not provided, will use the
|
||||
seasonality.prior.scale provided on Prophet initialization (defaults to 10).
|
||||
}
|
||||
|
|
@ -16,3 +16,4 @@ Stan model.
|
|||
\description{
|
||||
Compile Stan model
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
32
R/man/cross_validation.Rd
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/diagnostics.R
|
||||
\name{cross_validation}
|
||||
\alias{cross_validation}
|
||||
\title{Cross-validation for time series.}
|
||||
\usage{
|
||||
cross_validation(model, horizon, units, period = NULL, initial = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{model}{Fitted Prophet model.}
|
||||
|
||||
\item{horizon}{Integer size of the horizon}
|
||||
|
||||
\item{units}{String unit of the horizon, e.g., "days", "secs".}
|
||||
|
||||
\item{period}{Integer amount of time between cutoff dates. Same units as
|
||||
horizon. If not provided, 0.5 * horizon is used.}
|
||||
|
||||
\item{initial}{Integer size of the first training period. If not provided,
|
||||
3 * horizon is used. Same units as horizon.}
|
||||
}
|
||||
\value{
|
||||
A dataframe with the forecast, actual value, and cutoff date.
|
||||
}
|
||||
\description{
|
||||
Computes forecasts from historical cutoff points. Beginning from initial,
|
||||
makes cutoffs with a spacing of period up to (end - horizon).
|
||||
}
|
||||
\details{
|
||||
When period is equal to the time interval of the data, this is the
|
||||
technique described in https://robjhyndman.com/hyndsight/tscv/ .
|
||||
}
|
||||
|
|
@ -14,3 +14,4 @@ df_for_plotting(m, fcst)
|
|||
\description{
|
||||
Merge history and forecast for plotting.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ Matrix with seasonality features.
|
|||
\description{
|
||||
Provides Fourier series components with the specified frequency and order.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
24
R/man/generate_cutoffs.Rd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/diagnostics.R
|
||||
\name{generate_cutoffs}
|
||||
\alias{generate_cutoffs}
|
||||
\title{Generate cutoff dates}
|
||||
\usage{
|
||||
generate_cutoffs(df, horizon, k, period)
|
||||
}
|
||||
\arguments{
|
||||
\item{df}{Dataframe with historical data}
|
||||
|
||||
\item{horizon}{timediff forecast horizon}
|
||||
|
||||
\item{k}{integer number of forecast points}
|
||||
|
||||
\item{period}{timediff Simulated forecasts are done with this period.}
|
||||
}
|
||||
\value{
|
||||
Array of datetimes
|
||||
}
|
||||
\description{
|
||||
Generate cutoff dates
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -15,3 +15,4 @@ array of indexes.
|
|||
\description{
|
||||
Gets changepoint matrix for history dataframe.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ Stan model.
|
|||
\description{
|
||||
Load compiled Stan model
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
22
R/man/initialize_scales_fn.Rd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{initialize_scales_fn}
|
||||
\alias{initialize_scales_fn}
|
||||
\title{Initialize model scales.}
|
||||
\usage{
|
||||
initialize_scales_fn(m, initialize_scales, df)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{initialize_scales}{Boolean set the scales or not.}
|
||||
|
||||
\item{df}{Dataframe for setting scales.}
|
||||
}
|
||||
\value{
|
||||
Prophet object with scales set.
|
||||
}
|
||||
\description{
|
||||
Sets model scaling factors using df.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -19,3 +19,4 @@ Provides a strong initialization for linear growth by calculating the
|
|||
growth and offset parameters that pass the function through the first and
|
||||
last points in the time series.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ Provides a strong initialization for logistic growth by calculating the
|
|||
growth and offset parameters that pass the function through the first and
|
||||
last points in the time series.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,25 @@
|
|||
% Please edit documentation in R/prophet.R
|
||||
\name{make_all_seasonality_features}
|
||||
\alias{make_all_seasonality_features}
|
||||
\title{Dataframe with seasonality features.}
|
||||
\title{Dataframe with seasonality features.
|
||||
Includes seasonality features, holiday features, and added regressors.}
|
||||
\usage{
|
||||
make_all_seasonality_features(m, df)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{df}{Dataframe with dates for computing seasonality features.}
|
||||
\item{df}{Dataframe with dates for computing seasonality features and any
|
||||
added regressors.}
|
||||
}
|
||||
\value{
|
||||
Dataframe with seasonality.
|
||||
List with items
|
||||
seasonal.features: Dataframe with regressor features,
|
||||
prior.scales: Array of prior scales for each colum of the features
|
||||
dataframe.
|
||||
}
|
||||
\description{
|
||||
Dataframe with seasonality features.
|
||||
Includes seasonality features, holiday features, and added regressors.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
\alias{make_future_dataframe}
|
||||
\title{Make dataframe with future dates for forecasting.}
|
||||
\usage{
|
||||
make_future_dataframe(m, periods, freq = "d", include_history = TRUE)
|
||||
make_future_dataframe(m, periods, freq = "day", include_history = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet model object.}
|
||||
|
||||
\item{periods}{Int number of periods to forecast forward.}
|
||||
|
||||
\item{freq}{'day', 'week', 'month', 'quarter', or 'year'.}
|
||||
\item{freq}{'day', 'week', 'month', 'quarter', 'year', 1(1 sec), 60(1 minute) or 3600(1 hour).}
|
||||
|
||||
\item{include_history}{Boolean to include the historical dates in the data
|
||||
frame for predictions.}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ make_holiday_features(m, dates)
|
|||
\item{dates}{Vector with dates used for computing seasonality.}
|
||||
}
|
||||
\value{
|
||||
A dataframe with a column for each holiday.
|
||||
A list with entries
|
||||
holiday.features: dataframe with a column for each holiday.
|
||||
prior.scales: array of prior scales for each holiday column.
|
||||
}
|
||||
\description{
|
||||
Construct a matrix of holiday features.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -21,3 +21,4 @@ Dataframe with seasonality.
|
|||
\description{
|
||||
Data frame with seasonality features.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
27
R/man/parse_seasonality_args.Rd
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{parse_seasonality_args}
|
||||
\alias{parse_seasonality_args}
|
||||
\title{Get number of Fourier components for built-in seasonalities.}
|
||||
\usage{
|
||||
parse_seasonality_args(m, name, arg, auto.disable, default.order)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{name}{String name of the seasonality component.}
|
||||
|
||||
\item{arg}{'auto', TRUE, FALSE, or number of Fourier components as
|
||||
provided.}
|
||||
|
||||
\item{auto.disable}{Bool if seasonality should be disabled when 'auto'.}
|
||||
|
||||
\item{default.order}{Int default Fourier order.}
|
||||
}
|
||||
\value{
|
||||
Number of Fourier components, or 0 for disabled.
|
||||
}
|
||||
\description{
|
||||
Get number of Fourier components for built-in seasonalities.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -23,3 +23,4 @@ Vector y(t).
|
|||
\description{
|
||||
Evaluate the piecewise linear function.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -25,3 +25,4 @@ Vector y(t).
|
|||
\description{
|
||||
Evaluate the piecewise logistic function.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
24
R/man/plot_forecast_component.Rd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{plot_forecast_component}
|
||||
\alias{plot_forecast_component}
|
||||
\title{Plot a particular component of the forecast.}
|
||||
\usage{
|
||||
plot_forecast_component(fcst, name, uncertainty = TRUE, plot_cap = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{fcst}{Dataframe output of `predict`.}
|
||||
|
||||
\item{name}{String name of the component to plot (column of fcst).}
|
||||
|
||||
\item{uncertainty}{Boolean to plot uncertainty intervals.}
|
||||
|
||||
\item{plot_cap}{Boolean indicating if the capacity should be shown in the
|
||||
figure, if available.}
|
||||
}
|
||||
\value{
|
||||
A ggplot2 plot.
|
||||
}
|
||||
\description{
|
||||
Plot a particular component of the forecast.
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{plot_holidays}
|
||||
\alias{plot_holidays}
|
||||
\title{Plot the holidays component of the forecast.}
|
||||
\usage{
|
||||
plot_holidays(m, df, uncertainty = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet model}
|
||||
|
||||
\item{df}{Forecast dataframe for plotting.}
|
||||
|
||||
\item{uncertainty}{Boolean to plot uncertainty intervals.}
|
||||
}
|
||||
\value{
|
||||
A ggplot2 plot.
|
||||
}
|
||||
\description{
|
||||
Plot the holidays component of the forecast.
|
||||
}
|
||||
22
R/man/plot_seasonality.Rd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{plot_seasonality}
|
||||
\alias{plot_seasonality}
|
||||
\title{Plot a custom seasonal component.}
|
||||
\usage{
|
||||
plot_seasonality(m, name, uncertainty = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet model object.}
|
||||
|
||||
\item{name}{String name of the seasonality.}
|
||||
|
||||
\item{uncertainty}{Boolean to plot uncertainty intervals.}
|
||||
}
|
||||
\value{
|
||||
A ggplot2 plot.
|
||||
}
|
||||
\description{
|
||||
Plot a custom seasonal component.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{plot_trend}
|
||||
\alias{plot_trend}
|
||||
\title{Plot the prophet trend.}
|
||||
\usage{
|
||||
plot_trend(df, uncertainty = TRUE, plot_cap = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{df}{Forecast dataframe for plotting.}
|
||||
|
||||
\item{uncertainty}{Boolean to plot uncertainty intervals.}
|
||||
|
||||
\item{plot_cap}{Boolean indicating if the capacity should be shown in the
|
||||
figure, if available.}
|
||||
}
|
||||
\value{
|
||||
A ggplot2 plot.
|
||||
}
|
||||
\description{
|
||||
Plot the prophet trend.
|
||||
}
|
||||
|
|
@ -21,3 +21,4 @@ A ggplot2 plot.
|
|||
\description{
|
||||
Plot the weekly component of the forecast.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -21,3 +21,4 @@ A ggplot2 plot.
|
|||
\description{
|
||||
Plot the yearly component of the forecast.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
% Please edit documentation in R/prophet.R
|
||||
\name{predict_seasonal_components}
|
||||
\alias{predict_seasonal_components}
|
||||
\title{Predict seasonality broken down into components.}
|
||||
\title{Predict seasonality components, holidays, and added regressors.}
|
||||
\usage{
|
||||
predict_seasonal_components(m, df)
|
||||
}
|
||||
|
|
@ -15,5 +15,6 @@ predict_seasonal_components(m, df)
|
|||
Dataframe with seasonal components.
|
||||
}
|
||||
\description{
|
||||
Predict seasonality broken down into components.
|
||||
Predict seasonality components, holidays, and added regressors.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -17,3 +17,4 @@ Vector with trend on prediction dates.
|
|||
\description{
|
||||
Predict trend using the prophet model.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
% Please edit documentation in R/prophet.R
|
||||
\name{predict_uncertainty}
|
||||
\alias{predict_uncertainty}
|
||||
\title{Prophet uncertainty intervals.}
|
||||
\title{Prophet uncertainty intervals for yhat and trend}
|
||||
\usage{
|
||||
predict_uncertainty(m, df)
|
||||
}
|
||||
|
|
@ -15,5 +15,6 @@ predict_uncertainty(m, df)
|
|||
Dataframe with uncertainty intervals.
|
||||
}
|
||||
\description{
|
||||
Prophet uncertainty intervals.
|
||||
Prophet uncertainty intervals for yhat and trend
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
22
R/man/predictive_samples.Rd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{predictive_samples}
|
||||
\alias{predictive_samples}
|
||||
\title{Sample from the posterior predictive distribution.}
|
||||
\usage{
|
||||
predictive_samples(m, df)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{df}{Dataframe with dates for predictions (column ds), and capacity
|
||||
(column cap) if logistic growth.}
|
||||
}
|
||||
\value{
|
||||
A list with items "trend", "seasonal", and "yhat" containing
|
||||
posterior predictive samples for that component. "seasonal" is the sum
|
||||
of seasonalities, holidays, and added regressors.
|
||||
}
|
||||
\description{
|
||||
Sample from the posterior predictive distribution.
|
||||
}
|
||||
|
|
@ -4,17 +4,20 @@
|
|||
\alias{prophet}
|
||||
\title{Prophet forecaster.}
|
||||
\usage{
|
||||
prophet(df = df, growth = "linear", changepoints = NULL,
|
||||
prophet(df = NULL, growth = "linear", changepoints = NULL,
|
||||
n.changepoints = 25, yearly.seasonality = "auto",
|
||||
weekly.seasonality = "auto", holidays = NULL,
|
||||
seasonality.prior.scale = 10, holidays.prior.scale = 10,
|
||||
changepoint.prior.scale = 0.05, mcmc.samples = 0, interval.width = 0.8,
|
||||
uncertainty.samples = 1000, fit = TRUE, ...)
|
||||
weekly.seasonality = "auto", daily.seasonality = "auto",
|
||||
holidays = NULL, seasonality.prior.scale = 10,
|
||||
holidays.prior.scale = 10, changepoint.prior.scale = 0.05,
|
||||
mcmc.samples = 0, interval.width = 0.8, uncertainty.samples = 1000,
|
||||
fit = TRUE, ...)
|
||||
}
|
||||
\arguments{
|
||||
\item{df}{Dataframe containing the history. Must have columns ds (date type)
|
||||
and y, the time series. If growth is logistic, then df must also have a
|
||||
column cap that specifies the capacity at each ds.}
|
||||
\item{df}{(optional) Dataframe containing the history. Must have columns ds
|
||||
(date type) and y, the time series. If growth is logistic, then df must
|
||||
also have a column cap that specifies the capacity at each ds. If not
|
||||
provided, then the model object will be instantiated but not fit; use
|
||||
fit.prophet(m, df) to fit the model.}
|
||||
|
||||
\item{growth}{String 'linear' or 'logistic' to specify a linear or logistic
|
||||
trend.}
|
||||
|
|
@ -28,21 +31,28 @@ if input `changepoints` is supplied. If `changepoints` is not supplied,
|
|||
then n.changepoints potential changepoints are selected uniformly from the
|
||||
first 80 percent of df$ds.}
|
||||
|
||||
\item{yearly.seasonality}{Fit yearly seasonality; 'auto', TRUE, or FALSE.}
|
||||
\item{yearly.seasonality}{Fit yearly seasonality. Can be 'auto', TRUE,
|
||||
FALSE, or a number of Fourier terms to generate.}
|
||||
|
||||
\item{weekly.seasonality}{Fit weekly seasonality; 'auto', TRUE, or FALSE.}
|
||||
\item{weekly.seasonality}{Fit weekly seasonality. Can be 'auto', TRUE,
|
||||
FALSE, or a number of Fourier terms to generate.}
|
||||
|
||||
\item{daily.seasonality}{Fit daily seasonality. Can be 'auto', TRUE,
|
||||
FALSE, or a number of Fourier terms to generate.}
|
||||
|
||||
\item{holidays}{data frame with columns holiday (character) and ds (date
|
||||
type)and optionally columns lower_window and upper_window which specify a
|
||||
range of days around the date to be included as holidays. lower_window=-2
|
||||
will include 2 days prior to the date as holidays.}
|
||||
will include 2 days prior to the date as holidays. Also optionally can have
|
||||
a column prior_scale specifying the prior scale for each holiday.}
|
||||
|
||||
\item{seasonality.prior.scale}{Parameter modulating the strength of the
|
||||
seasonality model. Larger values allow the model to fit larger seasonal
|
||||
fluctuations, smaller values dampen the seasonality.}
|
||||
fluctuations, smaller values dampen the seasonality. Can be specified for
|
||||
individual seasonalities using add_seasonality.}
|
||||
|
||||
\item{holidays.prior.scale}{Parameter modulating the strength of the holiday
|
||||
components model.}
|
||||
components model, unless overridden in the holidays input.}
|
||||
|
||||
\item{changepoint.prior.scale}{Parameter modulating the flexibility of the
|
||||
automatic changepoint selection. Large values will allow many changepoints,
|
||||
|
|
|
|||
22
R/man/prophet_copy.Rd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{prophet_copy}
|
||||
\alias{prophet_copy}
|
||||
\title{Copy Prophet object.}
|
||||
\usage{
|
||||
prophet_copy(m, cutoff = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet model object.}
|
||||
|
||||
\item{cutoff}{Date, possibly as string. Changepoints are only retained if
|
||||
changepoints <= cutoff.}
|
||||
}
|
||||
\value{
|
||||
An unfitted Prophet model object with the same parameters as the
|
||||
input model.
|
||||
}
|
||||
\description{
|
||||
Copy Prophet object.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -21,3 +21,4 @@ List of trend, seasonality, and yhat, each a vector like df$t.
|
|||
\description{
|
||||
Simulate observations from the extrapolated generative model.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
20
R/man/sample_posterior_predictive.Rd
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{sample_posterior_predictive}
|
||||
\alias{sample_posterior_predictive}
|
||||
\title{Prophet posterior predictive samples.}
|
||||
\usage{
|
||||
sample_posterior_predictive(m, df)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{df}{Prediction dataframe.}
|
||||
}
|
||||
\value{
|
||||
List with posterior predictive samples for each component.
|
||||
}
|
||||
\description{
|
||||
Prophet posterior predictive samples.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -19,3 +19,4 @@ Vector of simulated trend over df$t.
|
|||
\description{
|
||||
Simulate the trend using the extrapolated generative model.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
20
R/man/seasonality_plot_df.Rd
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{seasonality_plot_df}
|
||||
\alias{seasonality_plot_df}
|
||||
\title{Prepare dataframe for plotting seasonal components.}
|
||||
\usage{
|
||||
seasonality_plot_df(m, ds)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{ds}{Array of dates for column ds.}
|
||||
}
|
||||
\value{
|
||||
A dataframe with seasonal components on ds.
|
||||
}
|
||||
\description{
|
||||
Prepare dataframe for plotting seasonal components.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -16,4 +16,7 @@ The prophet model with seasonalities set.
|
|||
Turns on yearly seasonality if there is >=2 years of history.
|
||||
Turns on weekly seasonality if there is >=2 weeks of history, and the
|
||||
spacing between dates in the history is <7 days.
|
||||
Turns on daily seasonality if there is >=2 days of history, and the spacing
|
||||
between dates in the history is <1 day.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -20,3 +20,4 @@ Sets m$changepoints to the dates of changepoints. Either:
|
|||
2) We are generating a grid of them.
|
||||
3) The user prefers no changepoints be used.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
20
R/man/set_date.Rd
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{set_date}
|
||||
\alias{set_date}
|
||||
\title{Convert date vector}
|
||||
\usage{
|
||||
set_date(ds = NULL, tz = "GMT")
|
||||
}
|
||||
\arguments{
|
||||
\item{ds}{Date vector, can be consisted of characters}
|
||||
|
||||
\item{tz}{string time zone}
|
||||
}
|
||||
\value{
|
||||
vector of POSIXct object converted from date
|
||||
}
|
||||
\description{
|
||||
Convert the date to POSIXct object
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -9,7 +9,8 @@ setup_dataframe(m, df, initialize_scales = FALSE)
|
|||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{df}{Data frame with columns ds, y, and cap if logistic growth.}
|
||||
\item{df}{Data frame with columns ds, y, and cap if logistic growth. Any
|
||||
specified additional regressors must also be present.}
|
||||
|
||||
\item{initialize_scales}{Boolean set scaling factors in m from df.}
|
||||
}
|
||||
|
|
@ -21,3 +22,4 @@ Adds a time index and scales y. Creates auxillary columns 't', 't_ix',
|
|||
'y_scaled', and 'cap_scaled'. These columns are used during both fitting
|
||||
and predicting.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
27
R/man/simulated_historical_forecasts.Rd
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/diagnostics.R
|
||||
\name{simulated_historical_forecasts}
|
||||
\alias{simulated_historical_forecasts}
|
||||
\title{Simulated historical forecasts.}
|
||||
\usage{
|
||||
simulated_historical_forecasts(model, horizon, units, k, period = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{model}{Fitted Prophet model.}
|
||||
|
||||
\item{horizon}{Integer size of the horizon}
|
||||
|
||||
\item{units}{String unit of the horizon, e.g., "days", "secs".}
|
||||
|
||||
\item{k}{integer number of forecast points}
|
||||
|
||||
\item{period}{Integer amount of time between cutoff dates. Same units as
|
||||
horizon. If not provided, will use 0.5 * horizon.}
|
||||
}
|
||||
\value{
|
||||
A dataframe with the forecast, actual value, and cutoff date.
|
||||
}
|
||||
\description{
|
||||
Make forecasts from k historical cutoff points, working backwards from
|
||||
(end - horizon) with a spacing of period between each cutoff.
|
||||
}
|
||||
22
R/man/time_diff.Rd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{time_diff}
|
||||
\alias{time_diff}
|
||||
\title{Time difference between datetimes}
|
||||
\usage{
|
||||
time_diff(ds1, ds2, units = "days")
|
||||
}
|
||||
\arguments{
|
||||
\item{ds1}{POSIXct object}
|
||||
|
||||
\item{ds2}{POSIXct object}
|
||||
|
||||
\item{units}{string units of difference, e.g. 'days' or 'secs'.}
|
||||
}
|
||||
\value{
|
||||
numeric time difference
|
||||
}
|
||||
\description{
|
||||
Compute time difference of two POSIXct objects
|
||||
}
|
||||
\keyword{internal}
|
||||
24
R/man/validate_column_name.Rd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/prophet.R
|
||||
\name{validate_column_name}
|
||||
\alias{validate_column_name}
|
||||
\title{Validates the name of a seasonality, holiday, or regressor.}
|
||||
\usage{
|
||||
validate_column_name(m, name, check_holidays = TRUE,
|
||||
check_seasonalities = TRUE, check_regressors = TRUE)
|
||||
}
|
||||
\arguments{
|
||||
\item{m}{Prophet object.}
|
||||
|
||||
\item{name}{string}
|
||||
|
||||
\item{check_holidays}{bool check if name already used for holiday}
|
||||
|
||||
\item{check_seasonalities}{bool check if name already used for seasonality}
|
||||
|
||||
\item{check_regressors}{bool check if name already used for regressor}
|
||||
}
|
||||
\description{
|
||||
Validates the name of a seasonality, holiday, or regressor.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
@ -12,3 +12,4 @@ validate_inputs(m)
|
|||
\description{
|
||||
Validates the inputs to Prophet.
|
||||
}
|
||||
\keyword{internal}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
|
||||
CXX_STD = CXX11
|
||||
|
|
|
|||
864
R/tests/testthat/data2.csv
Normal file
|
|
@ -0,0 +1,864 @@
|
|||
ds,y
|
||||
2017-01-01 00:05:00,0.0
|
||||
2017-01-01 00:10:00,0.0
|
||||
2017-01-01 00:15:00,0.0
|
||||
2017-01-01 00:20:00,0.0
|
||||
2017-01-01 00:25:00,-0.1
|
||||
2017-01-01 00:30:00,-0.1
|
||||
2017-01-01 00:35:00,-0.1
|
||||
2017-01-01 00:40:00,-0.1
|
||||
2017-01-01 00:45:00,-0.1
|
||||
2017-01-01 00:50:00,-0.1
|
||||
2017-01-01 00:55:00,-0.3
|
||||
2017-01-01 01:00:00,-0.2
|
||||
2017-01-01 01:05:00,-0.3
|
||||
2017-01-01 01:10:00,-0.4
|
||||
2017-01-01 01:15:00,-0.4
|
||||
2017-01-01 01:20:00,-0.3
|
||||
2017-01-01 01:25:00,-0.3
|
||||
2017-01-01 01:30:00,-0.2
|
||||
2017-01-01 01:35:00,-0.3
|
||||
2017-01-01 01:40:00,-0.3
|
||||
2017-01-01 01:45:00,-0.3
|
||||
2017-01-01 01:50:00,-0.3
|
||||
2017-01-01 01:55:00,-0.3
|
||||
2017-01-01 02:00:00,-0.3
|
||||
2017-01-01 02:05:00,-0.3
|
||||
2017-01-01 02:10:00,-0.3
|
||||
2017-01-01 02:15:00,-0.3
|
||||
2017-01-01 02:20:00,-0.3
|
||||
2017-01-01 02:25:00,-0.3
|
||||
2017-01-01 02:30:00,-0.3
|
||||
2017-01-01 02:35:00,-0.3
|
||||
2017-01-01 02:40:00,-0.3
|
||||
2017-01-01 02:45:00,-0.3
|
||||
2017-01-01 02:50:00,-0.3
|
||||
2017-01-01 02:55:00,-0.3
|
||||
2017-01-01 03:00:00,-0.3
|
||||
2017-01-01 03:05:00,-0.3
|
||||
2017-01-01 03:10:00,-0.3
|
||||
2017-01-01 03:15:00,-0.3
|
||||
2017-01-01 03:20:00,-0.3
|
||||
2017-01-01 03:25:00,-0.4
|
||||
2017-01-01 03:30:00,-0.6
|
||||
2017-01-01 03:35:00,-0.4
|
||||
2017-01-01 03:40:00,-0.3
|
||||
2017-01-01 03:45:00,-0.4
|
||||
2017-01-01 03:50:00,-0.7
|
||||
2017-01-01 03:55:00,-0.8
|
||||
2017-01-01 04:00:00,-0.4
|
||||
2017-01-01 04:05:00,-0.3
|
||||
2017-01-01 04:10:00,-0.4
|
||||
2017-01-01 04:15:00,-0.4
|
||||
2017-01-01 04:20:00,-0.4
|
||||
2017-01-01 04:25:00,-0.5
|
||||
2017-01-01 04:30:00,-0.5
|
||||
2017-01-01 04:35:00,-0.5
|
||||
2017-01-01 04:40:00,-0.4
|
||||
2017-01-01 04:45:00,-0.5
|
||||
2017-01-01 04:50:00,-0.5
|
||||
2017-01-01 04:55:00,-0.5
|
||||
2017-01-01 05:00:00,-0.6
|
||||
2017-01-01 05:05:00,-0.9
|
||||
2017-01-01 05:10:00,-0.9
|
||||
2017-01-01 05:15:00,-1.2
|
||||
2017-01-01 05:20:00,-1.4
|
||||
2017-01-01 05:25:00,-1.8
|
||||
2017-01-01 05:30:00,-2.0
|
||||
2017-01-01 05:35:00,-2.2
|
||||
2017-01-01 05:40:00,-1.6
|
||||
2017-01-01 05:45:00,-1.2
|
||||
2017-01-01 05:50:00,-1.2
|
||||
2017-01-01 05:55:00,-1.4
|
||||
2017-01-01 06:00:00,-1.2
|
||||
2017-01-01 06:05:00,-0.9
|
||||
2017-01-01 06:10:00,-0.9
|
||||
2017-01-01 06:15:00,-0.9
|
||||
2017-01-01 06:20:00,-0.9
|
||||
2017-01-01 06:25:00,-0.9
|
||||
2017-01-01 06:30:00,-1.2
|
||||
2017-01-01 06:35:00,-1.1
|
||||
2017-01-01 06:40:00,-1.2
|
||||
2017-01-01 06:45:00,-1.3
|
||||
2017-01-01 06:50:00,-1.4
|
||||
2017-01-01 06:55:00,-1.7
|
||||
2017-01-01 07:00:00,-1.7
|
||||
2017-01-01 07:05:00,-1.7
|
||||
2017-01-01 07:10:00,-1.8
|
||||
2017-01-01 07:15:00,-2.4
|
||||
2017-01-01 07:20:00,-2.9
|
||||
2017-01-01 07:25:00,-3.2
|
||||
2017-01-01 07:30:00,-3.4
|
||||
2017-01-01 07:35:00,-3.6
|
||||
2017-01-01 07:40:00,-3.6
|
||||
2017-01-01 07:45:00,-3.5
|
||||
2017-01-01 07:50:00,-3.5
|
||||
2017-01-01 07:55:00,-3.5
|
||||
2017-01-01 08:00:00,-3.6
|
||||
2017-01-01 08:05:00,-3.7
|
||||
2017-01-01 08:10:00,-3.6
|
||||
2017-01-01 08:15:00,-3.6
|
||||
2017-01-01 08:20:00,-3.8
|
||||
2017-01-01 08:25:00,-4.0
|
||||
2017-01-01 08:30:00,-3.9
|
||||
2017-01-01 08:35:00,-3.9
|
||||
2017-01-01 08:40:00,-4.1
|
||||
2017-01-01 08:45:00,-4.0
|
||||
2017-01-01 08:50:00,-4.1
|
||||
2017-01-01 08:55:00,-4.1
|
||||
2017-01-01 09:00:00,-4.2
|
||||
2017-01-01 09:05:00,-4.1
|
||||
2017-01-01 09:10:00,-4.2
|
||||
2017-01-01 09:15:00,-4.1
|
||||
2017-01-01 09:20:00,-4.0
|
||||
2017-01-01 09:25:00,-4.0
|
||||
2017-01-01 09:30:00,-4.0
|
||||
2017-01-01 09:35:00,-4.1
|
||||
2017-01-01 09:40:00,-4.1
|
||||
2017-01-01 09:45:00,-4.2
|
||||
2017-01-01 09:50:00,-4.3
|
||||
2017-01-01 09:55:00,-4.4
|
||||
2017-01-01 10:00:00,-4.5
|
||||
2017-01-01 10:05:00,-4.6
|
||||
2017-01-01 10:10:00,-4.7
|
||||
2017-01-01 10:15:00,-4.6
|
||||
2017-01-01 10:20:00,-4.6
|
||||
2017-01-01 10:25:00,-4.6
|
||||
2017-01-01 10:30:00,-4.5
|
||||
2017-01-01 10:35:00,-4.6
|
||||
2017-01-01 10:40:00,-4.6
|
||||
2017-01-01 10:45:00,-4.6
|
||||
2017-01-01 10:50:00,-4.6
|
||||
2017-01-01 10:55:00,-4.7
|
||||
2017-01-01 11:00:00,-4.7
|
||||
2017-01-01 11:05:00,-4.6
|
||||
2017-01-01 11:10:00,-4.5
|
||||
2017-01-01 11:15:00,-4.7
|
||||
2017-01-01 11:20:00,-4.7
|
||||
2017-01-01 11:25:00,-4.8
|
||||
2017-01-01 11:30:00,-4.8
|
||||
2017-01-01 11:35:00,-4.8
|
||||
2017-01-01 11:40:00,-4.8
|
||||
2017-01-01 11:45:00,-4.7
|
||||
2017-01-01 11:50:00,-4.6
|
||||
2017-01-01 11:55:00,-4.6
|
||||
2017-01-01 12:00:00,-4.8
|
||||
2017-01-01 12:05:00,-4.9
|
||||
2017-01-01 12:10:00,-4.9
|
||||
2017-01-01 12:15:00,-4.9
|
||||
2017-01-01 12:20:00,-5.0
|
||||
2017-01-01 12:25:00,-4.9
|
||||
2017-01-01 12:30:00,-4.9
|
||||
2017-01-01 12:35:00,-5.0
|
||||
2017-01-01 12:40:00,-5.1
|
||||
2017-01-01 12:45:00,-5.3
|
||||
2017-01-01 12:50:00,-5.5
|
||||
2017-01-01 12:55:00,-5.7
|
||||
2017-01-01 13:00:00,-5.8
|
||||
2017-01-01 13:05:00,-5.9
|
||||
2017-01-01 13:10:00,-5.9
|
||||
2017-01-01 13:15:00,-6.1
|
||||
2017-01-01 13:20:00,-6.1
|
||||
2017-01-01 13:25:00,-6.1
|
||||
2017-01-01 13:30:00,-6.2
|
||||
2017-01-01 13:35:00,-6.3
|
||||
2017-01-01 13:40:00,-6.4
|
||||
2017-01-01 13:45:00,-6.5
|
||||
2017-01-01 13:50:00,-6.6
|
||||
2017-01-01 13:55:00,-6.7
|
||||
2017-01-01 14:00:00,-6.7
|
||||
2017-01-01 14:05:00,-6.7
|
||||
2017-01-01 14:10:00,-6.6
|
||||
2017-01-01 14:15:00,-6.7
|
||||
2017-01-01 14:20:00,-6.7
|
||||
2017-01-01 14:25:00,-6.6
|
||||
2017-01-01 14:30:00,-6.7
|
||||
2017-01-01 14:35:00,-6.6
|
||||
2017-01-01 14:40:00,-6.6
|
||||
2017-01-01 14:45:00,-6.4
|
||||
2017-01-01 14:50:00,-6.5
|
||||
2017-01-01 14:55:00,-6.5
|
||||
2017-01-01 15:00:00,-6.4
|
||||
2017-01-01 15:05:00,-6.4
|
||||
2017-01-01 15:10:00,-6.3
|
||||
2017-01-01 15:15:00,-6.3
|
||||
2017-01-01 15:20:00,-6.4
|
||||
2017-01-01 15:25:00,-6.5
|
||||
2017-01-01 15:30:00,-6.6
|
||||
2017-01-01 15:35:00,-6.6
|
||||
2017-01-01 15:40:00,-6.6
|
||||
2017-01-01 15:45:00,-6.6
|
||||
2017-01-01 15:50:00,-6.5
|
||||
2017-01-01 15:55:00,-6.4
|
||||
2017-01-01 16:00:00,-6.3
|
||||
2017-01-01 16:05:00,-6.3
|
||||
2017-01-01 16:10:00,-6.2
|
||||
2017-01-01 16:15:00,-6.1
|
||||
2017-01-01 16:20:00,-6.0
|
||||
2017-01-01 16:25:00,-5.9
|
||||
2017-01-01 16:30:00,-5.8
|
||||
2017-01-01 16:35:00,-5.7
|
||||
2017-01-01 16:40:00,-5.4
|
||||
2017-01-01 16:45:00,-5.3
|
||||
2017-01-01 16:50:00,-5.1
|
||||
2017-01-01 16:55:00,-5.0
|
||||
2017-01-01 17:00:00,-4.8
|
||||
2017-01-01 17:05:00,-4.6
|
||||
2017-01-01 17:10:00,-4.3
|
||||
2017-01-01 17:15:00,-4.1
|
||||
2017-01-01 17:20:00,-3.9
|
||||
2017-01-01 17:25:00,-3.6
|
||||
2017-01-01 17:30:00,-3.3
|
||||
2017-01-01 17:35:00,-3.1
|
||||
2017-01-01 17:40:00,-2.8
|
||||
2017-01-01 17:45:00,-2.7
|
||||
2017-01-01 17:50:00,-2.4
|
||||
2017-01-01 17:55:00,-2.0
|
||||
2017-01-01 18:00:00,-1.6
|
||||
2017-01-01 18:05:00,-1.3
|
||||
2017-01-01 18:10:00,-1.1
|
||||
2017-01-01 18:15:00,-0.9
|
||||
2017-01-01 18:20:00,-0.7
|
||||
2017-01-01 18:25:00,-0.4
|
||||
2017-01-01 18:30:00,-0.4
|
||||
2017-01-01 18:35:00,-0.2
|
||||
2017-01-01 18:40:00,0.0
|
||||
2017-01-01 18:45:00,0.3
|
||||
2017-01-01 18:50:00,0.6
|
||||
2017-01-01 18:55:00,0.6
|
||||
2017-01-01 19:00:00,1.0
|
||||
2017-01-01 19:05:00,1.0
|
||||
2017-01-01 19:10:00,1.1
|
||||
2017-01-01 19:15:00,1.3
|
||||
2017-01-01 19:20:00,1.0
|
||||
2017-01-01 19:25:00,1.2
|
||||
2017-01-01 19:30:00,1.3
|
||||
2017-01-01 19:35:00,0.9
|
||||
2017-01-01 19:40:00,1.1
|
||||
2017-01-01 19:45:00,1.3
|
||||
2017-01-01 19:50:00,1.5
|
||||
2017-01-01 19:55:00,1.3
|
||||
2017-01-01 20:00:00,1.6
|
||||
2017-01-01 20:05:00,1.6
|
||||
2017-01-01 20:10:00,1.8
|
||||
2017-01-01 20:15:00,1.4
|
||||
2017-01-01 20:20:00,1.4
|
||||
2017-01-01 20:25:00,1.6
|
||||
2017-01-01 20:30:00,1.6
|
||||
2017-01-01 20:35:00,1.5
|
||||
2017-01-01 20:40:00,1.5
|
||||
2017-01-01 20:45:00,1.8
|
||||
2017-01-01 20:50:00,1.6
|
||||
2017-01-01 20:55:00,1.7
|
||||
2017-01-01 21:00:00,1.5
|
||||
2017-01-01 21:05:00,1.8
|
||||
2017-01-01 21:10:00,1.6
|
||||
2017-01-01 21:15:00,1.7
|
||||
2017-01-01 21:20:00,1.9
|
||||
2017-01-01 21:25:00,1.6
|
||||
2017-01-01 21:30:00,1.8
|
||||
2017-01-01 21:35:00,1.8
|
||||
2017-01-01 21:40:00,1.5
|
||||
2017-01-01 21:45:00,1.6
|
||||
2017-01-01 21:50:00,1.6
|
||||
2017-01-01 21:55:00,1.4
|
||||
2017-01-01 22:00:00,1.1
|
||||
2017-01-01 22:05:00,1.5
|
||||
2017-01-01 22:10:00,1.5
|
||||
2017-01-01 22:15:00,1.6
|
||||
2017-01-01 22:20:00,1.5
|
||||
2017-01-01 22:25:00,1.1
|
||||
2017-01-01 22:30:00,1.0
|
||||
2017-01-01 22:35:00,1.0
|
||||
2017-01-01 22:40:00,1.1
|
||||
2017-01-01 22:45:00,1.1
|
||||
2017-01-01 22:50:00,0.7
|
||||
2017-01-01 22:55:00,0.6
|
||||
2017-01-01 23:00:00,0.5
|
||||
2017-01-01 23:05:00,0.3
|
||||
2017-01-01 23:10:00,0.5
|
||||
2017-01-01 23:15:00,0.2
|
||||
2017-01-01 23:20:00,0.2
|
||||
2017-01-01 23:25:00,0.0
|
||||
2017-01-01 23:30:00,-0.2
|
||||
2017-01-01 23:35:00,-0.3
|
||||
2017-01-01 23:40:00,-0.5
|
||||
2017-01-01 23:45:00,-0.7
|
||||
2017-01-01 23:50:00,-1.1
|
||||
2017-01-01 23:55:00,-1.3
|
||||
2017-01-02 00:00:00,-1.4
|
||||
2017-01-02 00:05:00,-1.7
|
||||
2017-01-02 00:10:00,-2.1
|
||||
2017-01-02 00:15:00,-2.4
|
||||
2017-01-02 00:20:00,-2.6
|
||||
2017-01-02 00:25:00,-2.9
|
||||
2017-01-02 00:30:00,-3.2
|
||||
2017-01-02 00:35:00,-3.5
|
||||
2017-01-02 00:40:00,-3.9
|
||||
2017-01-02 00:45:00,-4.1
|
||||
2017-01-02 00:50:00,-4.2
|
||||
2017-01-02 00:55:00,-4.4
|
||||
2017-01-02 01:00:00,-4.6
|
||||
2017-01-02 01:05:00,-4.7
|
||||
2017-01-02 01:10:00,-5.0
|
||||
2017-01-02 01:15:00,-5.1
|
||||
2017-01-02 01:20:00,-4.8
|
||||
2017-01-02 01:25:00,-4.7
|
||||
2017-01-02 01:30:00,-4.5
|
||||
2017-01-02 01:35:00,-4.0
|
||||
2017-01-02 01:40:00,-3.6
|
||||
2017-01-02 01:45:00,-3.1
|
||||
2017-01-02 01:50:00,-3.0
|
||||
2017-01-02 01:55:00,-3.0
|
||||
2017-01-02 02:00:00,-3.0
|
||||
2017-01-02 02:05:00,-2.9
|
||||
2017-01-02 02:10:00,-3.0
|
||||
2017-01-02 02:15:00,-2.9
|
||||
2017-01-02 02:20:00,-3.0
|
||||
2017-01-02 02:25:00,-3.0
|
||||
2017-01-02 02:30:00,-3.0
|
||||
2017-01-02 02:35:00,-3.0
|
||||
2017-01-02 02:40:00,-3.2
|
||||
2017-01-02 02:45:00,-3.5
|
||||
2017-01-02 02:50:00,-3.7
|
||||
2017-01-02 02:55:00,-3.5
|
||||
2017-01-02 03:00:00,-3.5
|
||||
2017-01-02 03:05:00,-3.4
|
||||
2017-01-02 03:10:00,-3.3
|
||||
2017-01-02 03:15:00,-3.2
|
||||
2017-01-02 03:20:00,-3.2
|
||||
2017-01-02 03:25:00,-3.3
|
||||
2017-01-02 03:30:00,-3.3
|
||||
2017-01-02 03:35:00,-3.3
|
||||
2017-01-02 03:40:00,-3.4
|
||||
2017-01-02 03:45:00,-3.4
|
||||
2017-01-02 03:50:00,-3.4
|
||||
2017-01-02 03:55:00,-3.5
|
||||
2017-01-02 04:00:00,-3.5
|
||||
2017-01-02 04:05:00,-3.5
|
||||
2017-01-02 04:10:00,-3.5
|
||||
2017-01-02 04:15:00,-3.6
|
||||
2017-01-02 04:20:00,-3.6
|
||||
2017-01-02 04:25:00,-3.8
|
||||
2017-01-02 04:30:00,-3.8
|
||||
2017-01-02 04:35:00,-3.8
|
||||
2017-01-02 04:40:00,-3.9
|
||||
2017-01-02 04:45:00,-3.9
|
||||
2017-01-02 04:50:00,-3.9
|
||||
2017-01-02 04:55:00,-3.9
|
||||
2017-01-02 05:00:00,-3.9
|
||||
2017-01-02 05:05:00,-3.9
|
||||
2017-01-02 05:10:00,-3.9
|
||||
2017-01-02 05:15:00,-4.0
|
||||
2017-01-02 05:20:00,-3.9
|
||||
2017-01-02 05:25:00,-4.0
|
||||
2017-01-02 05:30:00,-4.2
|
||||
2017-01-02 05:35:00,-4.2
|
||||
2017-01-02 05:40:00,-4.4
|
||||
2017-01-02 05:45:00,-4.4
|
||||
2017-01-02 05:50:00,-4.4
|
||||
2017-01-02 05:55:00,-4.4
|
||||
2017-01-02 06:00:00,-4.4
|
||||
2017-01-02 06:05:00,-5.3
|
||||
2017-01-02 06:10:00,-5.2
|
||||
2017-01-02 06:15:00,-5.3
|
||||
2017-01-02 06:20:00,-5.2
|
||||
2017-01-02 06:25:00,-5.0
|
||||
2017-01-02 06:30:00,-4.9
|
||||
2017-01-02 06:35:00,-4.8
|
||||
2017-01-02 06:40:00,-4.8
|
||||
2017-01-02 06:45:00,-4.7
|
||||
2017-01-02 06:50:00,-4.7
|
||||
2017-01-02 06:55:00,-4.8
|
||||
2017-01-02 07:00:00,-4.7
|
||||
2017-01-02 07:05:00,-4.7
|
||||
2017-01-02 07:10:00,-4.7
|
||||
2017-01-02 07:15:00,-5.0
|
||||
2017-01-02 07:20:00,-5.0
|
||||
2017-01-02 07:25:00,-4.9
|
||||
2017-01-02 07:30:00,-4.8
|
||||
2017-01-02 07:35:00,-4.8
|
||||
2017-01-02 07:40:00,-4.7
|
||||
2017-01-02 07:45:00,-4.6
|
||||
2017-01-02 07:50:00,-4.6
|
||||
2017-01-02 07:55:00,-4.7
|
||||
2017-01-02 08:00:00,-4.6
|
||||
2017-01-02 08:05:00,-4.6
|
||||
2017-01-02 08:10:00,-4.5
|
||||
2017-01-02 08:15:00,-4.5
|
||||
2017-01-02 08:20:00,-4.5
|
||||
2017-01-02 08:25:00,-4.5
|
||||
2017-01-02 08:30:00,-4.5
|
||||
2017-01-02 08:35:00,-4.5
|
||||
2017-01-02 08:40:00,-4.6
|
||||
2017-01-02 08:45:00,-4.6
|
||||
2017-01-02 08:50:00,-4.6
|
||||
2017-01-02 08:55:00,-4.6
|
||||
2017-01-02 09:00:00,-4.6
|
||||
2017-01-02 09:05:00,-4.6
|
||||
2017-01-02 09:10:00,-4.5
|
||||
2017-01-02 09:15:00,-4.5
|
||||
2017-01-02 09:20:00,-4.5
|
||||
2017-01-02 09:25:00,-4.5
|
||||
2017-01-02 09:30:00,-4.5
|
||||
2017-01-02 09:35:00,-4.5
|
||||
2017-01-02 09:40:00,-4.5
|
||||
2017-01-02 09:45:00,-4.5
|
||||
2017-01-02 09:50:00,-4.4
|
||||
2017-01-02 09:55:00,-4.4
|
||||
2017-01-02 10:00:00,-4.4
|
||||
2017-01-02 10:05:00,-4.5
|
||||
2017-01-02 10:10:00,-4.5
|
||||
2017-01-02 10:15:00,-4.4
|
||||
2017-01-02 10:20:00,-4.5
|
||||
2017-01-02 10:25:00,-4.5
|
||||
2017-01-02 10:30:00,-4.5
|
||||
2017-01-02 10:35:00,-4.5
|
||||
2017-01-02 10:40:00,-4.5
|
||||
2017-01-02 10:45:00,-4.5
|
||||
2017-01-02 10:50:00,-4.5
|
||||
2017-01-02 10:55:00,-4.4
|
||||
2017-01-02 11:00:00,-4.4
|
||||
2017-01-02 11:05:00,-4.5
|
||||
2017-01-02 11:10:00,-4.5
|
||||
2017-01-02 11:15:00,-4.5
|
||||
2017-01-02 11:20:00,-4.5
|
||||
2017-01-02 11:25:00,-4.5
|
||||
2017-01-02 11:30:00,-4.5
|
||||
2017-01-02 11:35:00,-4.5
|
||||
2017-01-02 11:40:00,-4.5
|
||||
2017-01-02 11:45:00,-4.6
|
||||
2017-01-02 11:50:00,-4.6
|
||||
2017-01-02 11:55:00,-4.6
|
||||
2017-01-02 12:00:00,-4.6
|
||||
2017-01-02 12:05:00,-4.7
|
||||
2017-01-02 12:10:00,-4.8
|
||||
2017-01-02 12:15:00,-4.8
|
||||
2017-01-02 12:20:00,-4.9
|
||||
2017-01-02 12:25:00,-5.0
|
||||
2017-01-02 12:30:00,-5.3
|
||||
2017-01-02 12:35:00,-5.5
|
||||
2017-01-02 12:40:00,-5.5
|
||||
2017-01-02 12:45:00,-5.6
|
||||
2017-01-02 12:50:00,-5.9
|
||||
2017-01-02 12:55:00,-6.1
|
||||
2017-01-02 13:00:00,-6.0
|
||||
2017-01-02 13:05:00,-6.1
|
||||
2017-01-02 13:10:00,-6.1
|
||||
2017-01-02 13:15:00,-6.0
|
||||
2017-01-02 13:20:00,-5.7
|
||||
2017-01-02 13:25:00,-5.5
|
||||
2017-01-02 13:30:00,-5.3
|
||||
2017-01-02 13:35:00,-5.2
|
||||
2017-01-02 13:40:00,-5.1
|
||||
2017-01-02 13:45:00,-5.0
|
||||
2017-01-02 13:50:00,-5.0
|
||||
2017-01-02 13:55:00,-5.0
|
||||
2017-01-02 14:00:00,-4.9
|
||||
2017-01-02 14:05:00,-4.9
|
||||
2017-01-02 14:10:00,-5.0
|
||||
2017-01-02 14:15:00,-4.9
|
||||
2017-01-02 14:20:00,-4.9
|
||||
2017-01-02 14:25:00,-4.9
|
||||
2017-01-02 14:30:00,-4.9
|
||||
2017-01-02 14:35:00,-4.9
|
||||
2017-01-02 14:40:00,-5.0
|
||||
2017-01-02 14:45:00,-4.9
|
||||
2017-01-02 14:50:00,-4.9
|
||||
2017-01-02 14:55:00,-5.0
|
||||
2017-01-02 15:00:00,-4.9
|
||||
2017-01-02 15:05:00,-4.9
|
||||
2017-01-02 15:10:00,-4.9
|
||||
2017-01-02 15:15:00,-4.9
|
||||
2017-01-02 15:20:00,-4.9
|
||||
2017-01-02 15:25:00,-4.9
|
||||
2017-01-02 15:30:00,-4.9
|
||||
2017-01-02 15:35:00,-4.9
|
||||
2017-01-02 15:40:00,-4.9
|
||||
2017-01-02 15:45:00,-4.9
|
||||
2017-01-02 15:50:00,-4.9
|
||||
2017-01-02 15:55:00,-4.9
|
||||
2017-01-02 16:00:00,-4.9
|
||||
2017-01-02 16:05:00,-4.9
|
||||
2017-01-02 16:10:00,-4.9
|
||||
2017-01-02 16:15:00,-4.9
|
||||
2017-01-02 16:20:00,-4.9
|
||||
2017-01-02 16:25:00,-4.8
|
||||
2017-01-02 16:30:00,-4.8
|
||||
2017-01-02 16:35:00,-4.7
|
||||
2017-01-02 16:40:00,-4.8
|
||||
2017-01-02 16:45:00,-4.8
|
||||
2017-01-02 16:50:00,-4.8
|
||||
2017-01-02 16:55:00,-4.9
|
||||
2017-01-02 17:00:00,-4.8
|
||||
2017-01-02 17:05:00,-4.8
|
||||
2017-01-02 17:10:00,-4.8
|
||||
2017-01-02 17:15:00,-4.8
|
||||
2017-01-02 17:20:00,-4.7
|
||||
2017-01-02 17:25:00,-4.7
|
||||
2017-01-02 17:30:00,-4.7
|
||||
2017-01-02 17:35:00,-4.7
|
||||
2017-01-02 17:40:00,-4.7
|
||||
2017-01-02 17:45:00,-4.6
|
||||
2017-01-02 17:50:00,-4.7
|
||||
2017-01-02 17:55:00,-4.7
|
||||
2017-01-02 18:00:00,-4.5
|
||||
2017-01-02 18:05:00,-4.6
|
||||
2017-01-02 18:10:00,-4.5
|
||||
2017-01-02 18:15:00,-4.4
|
||||
2017-01-02 18:20:00,-4.6
|
||||
2017-01-02 18:25:00,-4.6
|
||||
2017-01-02 18:30:00,-4.5
|
||||
2017-01-02 18:35:00,-4.4
|
||||
2017-01-02 18:40:00,-4.4
|
||||
2017-01-02 18:45:00,-4.4
|
||||
2017-01-02 18:50:00,-4.3
|
||||
2017-01-02 18:55:00,-4.2
|
||||
2017-01-02 19:00:00,-4.2
|
||||
2017-01-02 19:05:00,-4.2
|
||||
2017-01-02 19:10:00,-4.2
|
||||
2017-01-02 19:15:00,-4.1
|
||||
2017-01-02 19:20:00,-4.2
|
||||
2017-01-02 19:25:00,-4.2
|
||||
2017-01-02 19:30:00,-4.1
|
||||
2017-01-02 19:35:00,-3.9
|
||||
2017-01-02 19:40:00,-3.9
|
||||
2017-01-02 19:45:00,-4.1
|
||||
2017-01-02 19:50:00,-4.2
|
||||
2017-01-02 19:55:00,-4.0
|
||||
2017-01-02 20:00:00,-4.0
|
||||
2017-01-02 20:05:00,-4.1
|
||||
2017-01-02 20:10:00,-4.0
|
||||
2017-01-02 20:15:00,-4.1
|
||||
2017-01-02 20:20:00,-4.1
|
||||
2017-01-02 20:25:00,-4.0
|
||||
2017-01-02 20:30:00,-4.2
|
||||
2017-01-02 20:35:00,-4.1
|
||||
2017-01-02 20:40:00,-4.1
|
||||
2017-01-02 20:45:00,-4.2
|
||||
2017-01-02 20:50:00,-4.1
|
||||
2017-01-02 20:55:00,-4.3
|
||||
2017-01-02 21:00:00,-4.3
|
||||
2017-01-02 21:05:00,-4.4
|
||||
2017-01-02 21:10:00,-4.5
|
||||
2017-01-02 21:15:00,-4.4
|
||||
2017-01-02 21:20:00,-4.2
|
||||
2017-01-02 21:25:00,-4.5
|
||||
2017-01-02 21:30:00,-4.4
|
||||
2017-01-02 21:35:00,-4.2
|
||||
2017-01-02 21:40:00,-4.3
|
||||
2017-01-02 21:45:00,-4.3
|
||||
2017-01-02 21:50:00,-4.2
|
||||
2017-01-02 21:55:00,-4.2
|
||||
2017-01-02 22:00:00,-4.3
|
||||
2017-01-02 22:05:00,-4.2
|
||||
2017-01-02 22:10:00,-4.3
|
||||
2017-01-02 22:15:00,-4.4
|
||||
2017-01-02 22:20:00,-4.3
|
||||
2017-01-02 22:25:00,-4.3
|
||||
2017-01-02 22:30:00,-4.0
|
||||
2017-01-02 22:35:00,-4.3
|
||||
2017-01-02 22:40:00,-4.1
|
||||
2017-01-02 22:45:00,-4.2
|
||||
2017-01-02 22:50:00,-4.0
|
||||
2017-01-02 22:55:00,-3.9
|
||||
2017-01-02 23:00:00,-4.0
|
||||
2017-01-02 23:05:00,-4.1
|
||||
2017-01-02 23:10:00,-4.1
|
||||
2017-01-02 23:15:00,-4.0
|
||||
2017-01-02 23:20:00,-4.1
|
||||
2017-01-02 23:25:00,-4.2
|
||||
2017-01-02 23:30:00,-4.3
|
||||
2017-01-02 23:35:00,-4.2
|
||||
2017-01-02 23:40:00,-4.3
|
||||
2017-01-02 23:45:00,-4.3
|
||||
2017-01-02 23:50:00,-4.3
|
||||
2017-01-02 23:55:00,-4.4
|
||||
2017-01-03 00:00:00,-4.5
|
||||
2017-01-03 00:05:00,-4.5
|
||||
2017-01-03 00:10:00,-4.5
|
||||
2017-01-03 00:15:00,-4.5
|
||||
2017-01-03 00:20:00,-4.6
|
||||
2017-01-03 00:25:00,-4.6
|
||||
2017-01-03 00:30:00,-4.5
|
||||
2017-01-03 00:35:00,-4.6
|
||||
2017-01-03 00:40:00,-4.6
|
||||
2017-01-03 00:45:00,-4.5
|
||||
2017-01-03 00:50:00,-4.5
|
||||
2017-01-03 00:55:00,-4.6
|
||||
2017-01-03 01:00:00,-4.5
|
||||
2017-01-03 01:05:00,-4.6
|
||||
2017-01-03 01:10:00,-4.7
|
||||
2017-01-03 01:15:00,-4.7
|
||||
2017-01-03 01:20:00,-4.7
|
||||
2017-01-03 01:25:00,-4.9
|
||||
2017-01-03 01:30:00,-4.9
|
||||
2017-01-03 01:35:00,-4.9
|
||||
2017-01-03 01:40:00,-5.0
|
||||
2017-01-03 01:45:00,-5.0
|
||||
2017-01-03 01:50:00,-5.2
|
||||
2017-01-03 01:55:00,-5.2
|
||||
2017-01-03 02:00:00,-5.5
|
||||
2017-01-03 02:05:00,-5.3
|
||||
2017-01-03 02:10:00,-5.2
|
||||
2017-01-03 02:15:00,-5.2
|
||||
2017-01-03 02:20:00,-5.9
|
||||
2017-01-03 02:25:00,-6.4
|
||||
2017-01-03 02:30:00,-6.5
|
||||
2017-01-03 02:35:00,-6.0
|
||||
2017-01-03 02:40:00,-5.8
|
||||
2017-01-03 02:45:00,-5.5
|
||||
2017-01-03 02:50:00,-5.4
|
||||
2017-01-03 02:55:00,-5.5
|
||||
2017-01-03 03:00:00,-6.3
|
||||
2017-01-03 03:05:00,-6.3
|
||||
2017-01-03 03:10:00,-6.8
|
||||
2017-01-03 03:15:00,-6.3
|
||||
2017-01-03 03:20:00,-5.8
|
||||
2017-01-03 03:25:00,-6.8
|
||||
2017-01-03 03:30:00,-6.2
|
||||
2017-01-03 03:35:00,-5.7
|
||||
2017-01-03 03:40:00,-5.4
|
||||
2017-01-03 03:45:00,-5.3
|
||||
2017-01-03 03:50:00,-5.3
|
||||
2017-01-03 03:55:00,-5.2
|
||||
2017-01-03 04:00:00,-5.3
|
||||
2017-01-03 04:05:00,-5.3
|
||||
2017-01-03 04:10:00,-5.2
|
||||
2017-01-03 04:15:00,-5.2
|
||||
2017-01-03 04:20:00,-5.6
|
||||
2017-01-03 04:25:00,-6.1
|
||||
2017-01-03 04:30:00,-6.1
|
||||
2017-01-03 04:35:00,-6.1
|
||||
2017-01-03 04:40:00,-6.0
|
||||
2017-01-03 04:45:00,-5.8
|
||||
2017-01-03 04:50:00,-5.6
|
||||
2017-01-03 04:55:00,-5.7
|
||||
2017-01-03 05:00:00,-5.6
|
||||
2017-01-03 05:05:00,-6.1
|
||||
2017-01-03 05:10:00,-5.8
|
||||
2017-01-03 05:15:00,-5.9
|
||||
2017-01-03 05:20:00,-5.8
|
||||
2017-01-03 05:25:00,-6.3
|
||||
2017-01-03 05:30:00,-6.4
|
||||
2017-01-03 05:35:00,-6.5
|
||||
2017-01-03 05:40:00,-6.5
|
||||
2017-01-03 05:45:00,-5.9
|
||||
2017-01-03 05:50:00,-5.7
|
||||
2017-01-03 05:55:00,-5.8
|
||||
2017-01-03 06:00:00,-6.0
|
||||
2017-01-03 06:05:00,-6.3
|
||||
2017-01-03 06:10:00,-6.7
|
||||
2017-01-03 06:15:00,-6.6
|
||||
2017-01-03 06:20:00,-6.5
|
||||
2017-01-03 06:25:00,-6.4
|
||||
2017-01-03 06:30:00,-6.1
|
||||
2017-01-03 06:35:00,-6.3
|
||||
2017-01-03 06:40:00,-6.2
|
||||
2017-01-03 06:45:00,-6.1
|
||||
2017-01-03 06:50:00,-6.1
|
||||
2017-01-03 06:55:00,-6.0
|
||||
2017-01-03 07:00:00,-6.0
|
||||
2017-01-03 07:05:00,-6.2
|
||||
2017-01-03 07:10:00,-6.4
|
||||
2017-01-03 07:15:00,-6.2
|
||||
2017-01-03 07:20:00,-6.1
|
||||
2017-01-03 07:25:00,-5.9
|
||||
2017-01-03 07:30:00,-5.9
|
||||
2017-01-03 07:35:00,-5.9
|
||||
2017-01-03 07:40:00,-6.2
|
||||
2017-01-03 07:45:00,-6.4
|
||||
2017-01-03 07:50:00,-6.2
|
||||
2017-01-03 07:55:00,-6.0
|
||||
2017-01-03 08:00:00,-5.9
|
||||
2017-01-03 08:05:00,-5.9
|
||||
2017-01-03 08:10:00,-5.8
|
||||
2017-01-03 08:15:00,-5.8
|
||||
2017-01-03 08:20:00,-5.8
|
||||
2017-01-03 08:25:00,-5.8
|
||||
2017-01-03 08:30:00,-6.0
|
||||
2017-01-03 08:35:00,-5.9
|
||||
2017-01-03 08:40:00,-5.9
|
||||
2017-01-03 08:45:00,-5.8
|
||||
2017-01-03 08:50:00,-5.8
|
||||
2017-01-03 08:55:00,-5.7
|
||||
2017-01-03 09:00:00,-5.8
|
||||
2017-01-03 09:05:00,-5.8
|
||||
2017-01-03 09:10:00,-6.0
|
||||
2017-01-03 09:15:00,-6.1
|
||||
2017-01-03 09:20:00,-6.0
|
||||
2017-01-03 09:25:00,-5.9
|
||||
2017-01-03 09:30:00,-6.0
|
||||
2017-01-03 09:35:00,-6.0
|
||||
2017-01-03 09:40:00,-6.1
|
||||
2017-01-03 09:45:00,-6.2
|
||||
2017-01-03 09:50:00,-6.1
|
||||
2017-01-03 09:55:00,-6.3
|
||||
2017-01-03 10:00:00,-6.3
|
||||
2017-01-03 10:05:00,-6.1
|
||||
2017-01-03 10:10:00,-6.0
|
||||
2017-01-03 10:15:00,-5.9
|
||||
2017-01-03 10:20:00,-5.8
|
||||
2017-01-03 10:25:00,-5.7
|
||||
2017-01-03 10:30:00,-5.7
|
||||
2017-01-03 10:35:00,-5.8
|
||||
2017-01-03 10:40:00,-5.6
|
||||
2017-01-03 10:45:00,-5.6
|
||||
2017-01-03 10:50:00,-5.6
|
||||
2017-01-03 10:55:00,-5.6
|
||||
2017-01-03 11:00:00,-5.5
|
||||
2017-01-03 11:05:00,-5.6
|
||||
2017-01-03 11:10:00,-5.7
|
||||
2017-01-03 11:15:00,-5.7
|
||||
2017-01-03 11:20:00,-5.8
|
||||
2017-01-03 11:25:00,-5.7
|
||||
2017-01-03 11:30:00,-5.6
|
||||
2017-01-03 11:35:00,-5.5
|
||||
2017-01-03 11:40:00,-5.3
|
||||
2017-01-03 11:45:00,-5.2
|
||||
2017-01-03 11:50:00,-5.1
|
||||
2017-01-03 11:55:00,-5.0
|
||||
2017-01-03 12:00:00,-5.1
|
||||
2017-01-03 12:05:00,-5.0
|
||||
2017-01-03 12:10:00,-5.0
|
||||
2017-01-03 12:15:00,-5.0
|
||||
2017-01-03 12:20:00,-4.8
|
||||
2017-01-03 12:25:00,-4.8
|
||||
2017-01-03 12:30:00,-4.7
|
||||
2017-01-03 12:35:00,-4.6
|
||||
2017-01-03 12:40:00,-4.5
|
||||
2017-01-03 12:45:00,-4.4
|
||||
2017-01-03 12:50:00,-4.5
|
||||
2017-01-03 12:55:00,-4.6
|
||||
2017-01-03 13:00:00,-4.6
|
||||
2017-01-03 13:05:00,-4.6
|
||||
2017-01-03 13:10:00,-4.5
|
||||
2017-01-03 13:15:00,-4.5
|
||||
2017-01-03 13:20:00,-4.5
|
||||
2017-01-03 13:25:00,-4.3
|
||||
2017-01-03 13:30:00,-4.3
|
||||
2017-01-03 13:35:00,-4.3
|
||||
2017-01-03 13:40:00,-4.2
|
||||
2017-01-03 13:45:00,-4.2
|
||||
2017-01-03 13:50:00,-4.2
|
||||
2017-01-03 13:55:00,-4.2
|
||||
2017-01-03 14:00:00,-4.3
|
||||
2017-01-03 14:05:00,-4.3
|
||||
2017-01-03 14:10:00,-4.3
|
||||
2017-01-03 14:15:00,-4.3
|
||||
2017-01-03 14:20:00,-4.3
|
||||
2017-01-03 14:25:00,-4.3
|
||||
2017-01-03 14:30:00,-4.4
|
||||
2017-01-03 14:35:00,-4.4
|
||||
2017-01-03 14:40:00,-4.4
|
||||
2017-01-03 14:45:00,-4.5
|
||||
2017-01-03 14:50:00,-4.6
|
||||
2017-01-03 14:55:00,-4.5
|
||||
2017-01-03 15:00:00,-4.5
|
||||
2017-01-03 15:05:00,-4.5
|
||||
2017-01-03 15:10:00,-4.5
|
||||
2017-01-03 15:15:00,-4.5
|
||||
2017-01-03 15:20:00,-4.5
|
||||
2017-01-03 15:25:00,-4.5
|
||||
2017-01-03 15:30:00,-4.5
|
||||
2017-01-03 15:35:00,-4.5
|
||||
2017-01-03 15:40:00,-4.5
|
||||
2017-01-03 15:45:00,-4.6
|
||||
2017-01-03 15:50:00,-4.6
|
||||
2017-01-03 15:55:00,-4.5
|
||||
2017-01-03 16:00:00,-4.6
|
||||
2017-01-03 16:05:00,-4.5
|
||||
2017-01-03 16:10:00,-4.3
|
||||
2017-01-03 16:15:00,-4.2
|
||||
2017-01-03 16:20:00,-4.3
|
||||
2017-01-03 16:25:00,-4.2
|
||||
2017-01-03 16:30:00,-4.1
|
||||
2017-01-03 16:35:00,-4.0
|
||||
2017-01-03 16:40:00,-3.9
|
||||
2017-01-03 16:45:00,-3.8
|
||||
2017-01-03 16:50:00,-3.7
|
||||
2017-01-03 16:55:00,-3.7
|
||||
2017-01-03 17:00:00,-3.4
|
||||
2017-01-03 17:05:00,-3.3
|
||||
2017-01-03 17:10:00,-3.5
|
||||
2017-01-03 17:15:00,-3.4
|
||||
2017-01-03 17:20:00,-3.3
|
||||
2017-01-03 17:25:00,-3.2
|
||||
2017-01-03 17:30:00,-3.1
|
||||
2017-01-03 17:35:00,-3.0
|
||||
2017-01-03 17:40:00,-2.7
|
||||
2017-01-03 17:45:00,-2.6
|
||||
2017-01-03 17:50:00,-2.2
|
||||
2017-01-03 17:55:00,-2.4
|
||||
2017-01-03 18:00:00,-2.4
|
||||
2017-01-03 18:05:00,-2.7
|
||||
2017-01-03 18:10:00,-2.7
|
||||
2017-01-03 18:15:00,-2.6
|
||||
2017-01-03 18:20:00,-2.7
|
||||
2017-01-03 18:25:00,-2.5
|
||||
2017-01-03 18:30:00,-2.5
|
||||
2017-01-03 18:35:00,-2.6
|
||||
2017-01-03 18:40:00,-2.6
|
||||
2017-01-03 18:45:00,-2.6
|
||||
2017-01-03 18:50:00,-2.9
|
||||
2017-01-03 18:55:00,-2.7
|
||||
2017-01-03 19:00:00,-2.5
|
||||
2017-01-03 19:05:00,-2.3
|
||||
2017-01-03 19:10:00,-2.3
|
||||
2017-01-03 19:15:00,-2.3
|
||||
2017-01-03 19:20:00,-2.3
|
||||
2017-01-03 19:25:00,-2.2
|
||||
2017-01-03 19:30:00,-2.1
|
||||
2017-01-03 19:35:00,-2.3
|
||||
2017-01-03 19:40:00,-2.2
|
||||
2017-01-03 19:45:00,-2.0
|
||||
2017-01-03 19:50:00,-1.9
|
||||
2017-01-03 19:55:00,-1.8
|
||||
2017-01-03 20:00:00,-1.8
|
||||
2017-01-03 20:05:00,-1.9
|
||||
2017-01-03 20:10:00,-1.8
|
||||
2017-01-03 20:15:00,-1.6
|
||||
2017-01-03 20:20:00,-1.5
|
||||
2017-01-03 20:25:00,-1.1
|
||||
2017-01-03 20:30:00,-1.6
|
||||
2017-01-03 20:35:00,-2.2
|
||||
2017-01-03 20:40:00,-2.2
|
||||
2017-01-03 20:45:00,-2.3
|
||||
2017-01-03 20:50:00,-2.4
|
||||
2017-01-03 20:55:00,-2.4
|
||||
2017-01-03 21:00:00,-2.4
|
||||
2017-01-03 21:05:00,-2.3
|
||||
2017-01-03 21:10:00,-2.4
|
||||
2017-01-03 21:15:00,-2.5
|
||||
2017-01-03 21:20:00,-2.3
|
||||
2017-01-03 21:25:00,-2.1
|
||||
2017-01-03 21:30:00,-2.2
|
||||
2017-01-03 21:35:00,-2.2
|
||||
2017-01-03 21:40:00,-2.3
|
||||
2017-01-03 21:45:00,-2.3
|
||||
2017-01-03 21:50:00,-2.3
|
||||
2017-01-03 21:55:00,-2.3
|
||||
2017-01-03 22:00:00,-2.4
|
||||
2017-01-03 22:05:00,-2.3
|
||||
2017-01-03 22:10:00,-2.3
|
||||
2017-01-03 22:15:00,-2.4
|
||||
2017-01-03 22:20:00,-2.4
|
||||
2017-01-03 22:25:00,-2.5
|
||||
2017-01-03 22:30:00,-2.5
|
||||
2017-01-03 22:35:00,-2.7
|
||||
2017-01-03 22:40:00,-2.7
|
||||
2017-01-03 22:45:00,-2.8
|
||||
2017-01-03 22:50:00,-2.8
|
||||
2017-01-03 22:55:00,-2.8
|
||||
2017-01-03 23:00:00,-2.8
|
||||
2017-01-03 23:05:00,-2.8
|
||||
2017-01-03 23:10:00,-2.8
|
||||
2017-01-03 23:15:00,-2.7
|
||||
2017-01-03 23:20:00,-2.7
|
||||
2017-01-03 23:25:00,-2.6
|
||||
2017-01-03 23:30:00,-2.6
|
||||
2017-01-03 23:35:00,-2.5
|
||||
2017-01-03 23:40:00,-2.5
|
||||
2017-01-03 23:45:00,-2.4
|
||||
2017-01-03 23:50:00,-2.4
|
||||
2017-01-03 23:55:00,-2.4
|
||||
|
86
R/tests/testthat/test_diagnostics.R
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
library(prophet)
|
||||
context("Prophet diagnostics tests")
|
||||
|
||||
## Makes R CMD CHECK happy due to dplyr syntax below
|
||||
globalVariables(c("y", "yhat"))
|
||||
|
||||
DATA <- head(read.csv('data.csv'), 100)
|
||||
DATA$ds <- as.Date(DATA$ds)
|
||||
|
||||
test_that("simulated_historical_forecasts", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(DATA)
|
||||
k <- 2
|
||||
for (p in c(1, 10)) {
|
||||
for (h in c(1, 3)) {
|
||||
df.shf <- simulated_historical_forecasts(
|
||||
m, horizon = h, units = 'days', k = k, period = p)
|
||||
# All cutoff dates should be less than ds dates
|
||||
expect_true(all(df.shf$cutoff < df.shf$ds))
|
||||
# The unique size of output cutoff should be equal to 'k'
|
||||
expect_equal(length(unique(df.shf$cutoff)), k)
|
||||
expect_equal(max(df.shf$ds - df.shf$cutoff),
|
||||
as.difftime(h, units = 'days'))
|
||||
dc <- diff(df.shf$cutoff)
|
||||
dc <- min(dc[dc > 0])
|
||||
expect_true(dc >= as.difftime(p, units = 'days'))
|
||||
# Each y in df_shf and DATA with same ds should be equal
|
||||
df.merged <- dplyr::left_join(df.shf, m$history, by="ds")
|
||||
expect_equal(sum((df.merged$y.x - df.merged$y.y) ** 2), 0)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test_that("simulated_historical_forecasts_logistic", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
df <- DATA
|
||||
df$cap <- 40
|
||||
m <- prophet(df, growth='logistic')
|
||||
df.shf <- simulated_historical_forecasts(
|
||||
m, horizon = 3, units = 'days', k = 2, period = 3)
|
||||
# All cutoff dates should be less than ds dates
|
||||
expect_true(all(df.shf$cutoff < df.shf$ds))
|
||||
# The unique size of output cutoff should be equal to 'k'
|
||||
expect_equal(length(unique(df.shf$cutoff)), 2)
|
||||
# Each y in df_shf and DATA with same ds should be equal
|
||||
df.merged <- dplyr::left_join(df.shf, m$history, by="ds")
|
||||
expect_equal(sum((df.merged$y.x - df.merged$y.y) ** 2), 0)
|
||||
})
|
||||
|
||||
test_that("simulated_historical_forecasts_default_value_check", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(DATA)
|
||||
df.shf1 <- simulated_historical_forecasts(
|
||||
m, horizon = 10, units = 'days', k = 1)
|
||||
df.shf2 <- simulated_historical_forecasts(
|
||||
m, horizon = 10, units = 'days', k = 1, period = 5)
|
||||
expect_equal(sum(dplyr::select(df.shf1 - df.shf2, y, yhat)), 0)
|
||||
})
|
||||
|
||||
test_that("cross_validation", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(DATA)
|
||||
# Calculate the number of cutoff points
|
||||
te <- max(DATA$ds)
|
||||
ts <- min(DATA$ds)
|
||||
horizon <- as.difftime(4, units = "days")
|
||||
period <- as.difftime(10, units = "days")
|
||||
k <- 5
|
||||
df.cv <- cross_validation(
|
||||
m, horizon = 4, units = "days", period = 10, initial = 90)
|
||||
expect_equal(length(unique(df.cv$cutoff)), k)
|
||||
expect_equal(max(df.cv$ds - df.cv$cutoff), horizon)
|
||||
dc <- diff(df.cv$cutoff)
|
||||
dc <- min(dc[dc > 0])
|
||||
expect_true(dc >= period)
|
||||
})
|
||||
|
||||
test_that("cross_validation_default_value_check", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(DATA)
|
||||
df.cv1 <- cross_validation(
|
||||
m, horizon = 32, units = "days", period = 10)
|
||||
df.cv2 <- cross_validation(
|
||||
m, horizon = 32, units = 'days', period = 10, initial = 96)
|
||||
expect_equal(sum(dplyr::select(df.cv1 - df.cv2, y, yhat)), 0)
|
||||
})
|
||||
|
|
@ -2,11 +2,15 @@ library(prophet)
|
|||
context("Prophet tests")
|
||||
|
||||
DATA <- read.csv('data.csv')
|
||||
DATA$ds <- as.Date(DATA$ds)
|
||||
N <- nrow(DATA)
|
||||
train <- DATA[1:floor(N / 2), ]
|
||||
future <- DATA[(ceiling(N/2) + 1):N, ]
|
||||
|
||||
DATA2 <- read.csv('data2.csv')
|
||||
|
||||
DATA$ds <- prophet:::set_date(DATA$ds)
|
||||
DATA2$ds <- prophet:::set_date(DATA2$ds)
|
||||
|
||||
test_that("fit_predict", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(train)
|
||||
|
|
@ -27,9 +31,10 @@ test_that("fit_predict_no_changepoints", {
|
|||
|
||||
test_that("fit_predict_changepoint_not_in_history", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
train_t <- dplyr::mutate(DATA, ds=zoo::as.Date(ds))
|
||||
train_t <- dplyr::filter(train_t, (ds < zoo::as.Date('2013-01-01')) |
|
||||
(ds > zoo::as.Date('2014-01-01')))
|
||||
train_t <- dplyr::mutate(DATA, ds=prophet:::set_date(ds))
|
||||
train_t <- dplyr::filter(train_t,
|
||||
(ds < prophet:::set_date('2013-01-01')) |
|
||||
(ds > prophet:::set_date('2014-01-01')))
|
||||
future <- data.frame(ds=DATA$ds)
|
||||
m <- prophet(train_t, changepoints=c('2013-06-06'))
|
||||
expect_error(predict(m, future), NA)
|
||||
|
|
@ -44,6 +49,19 @@ test_that("fit_predict_duplicates", {
|
|||
expect_error(predict(m, future), NA)
|
||||
})
|
||||
|
||||
test_that("fit_predict_constant_history", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
train2 <- train
|
||||
train2$y <- 20
|
||||
m <- prophet(train2)
|
||||
fcst <- predict(m, future)
|
||||
expect_equal(tail(fcst$yhat, 1), 20)
|
||||
train2$y <- 0
|
||||
m <- prophet(train2)
|
||||
fcst <- predict(m, future)
|
||||
expect_equal(tail(fcst$yhat, 1), 0)
|
||||
})
|
||||
|
||||
test_that("setup_dataframe", {
|
||||
history <- train
|
||||
m <- prophet(history, fit = FALSE)
|
||||
|
|
@ -59,6 +77,36 @@ test_that("setup_dataframe", {
|
|||
expect_equal(max(history$y_scaled), 1)
|
||||
})
|
||||
|
||||
test_that("logistic_floor", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet(growth = 'logistic')
|
||||
history <- train
|
||||
history$floor <- 10.
|
||||
history$cap <- 80.
|
||||
future1 <- future
|
||||
future1$cap <- 80.
|
||||
future1$floor <- 10.
|
||||
m <- fit.prophet(m, history, algorithm = 'Newton')
|
||||
expect_true(m$logistic.floor)
|
||||
expect_true('floor' %in% colnames(m$history))
|
||||
expect_equal(m$history$y_scaled[1], 1., tolerance = 1e-6)
|
||||
fcst1 <- predict(m, future1)
|
||||
|
||||
m2 <- prophet(growth = 'logistic')
|
||||
history2 <- history
|
||||
history2$y <- history2$y + 10.
|
||||
history2$floor <- history2$floor + 10.
|
||||
history2$cap <- history2$cap + 10.
|
||||
future1$cap <- future1$cap + 10.
|
||||
future1$floor <- future1$floor + 10.
|
||||
m2 <- fit.prophet(m2, history2, algorithm = 'Newton')
|
||||
expect_equal(m2$history$y_scaled[1], 1., tolerance = 1e-6)
|
||||
fcst2 <- predict(m, future1)
|
||||
fcst2$yhat <- fcst2$yhat - 10.
|
||||
# Check for approximate shift invariance
|
||||
expect_true(all(abs(fcst1$yhat - fcst2$yhat) < 1))
|
||||
})
|
||||
|
||||
test_that("get_changepoints", {
|
||||
history <- train
|
||||
m <- prophet(history, fit = FALSE)
|
||||
|
|
@ -99,18 +147,33 @@ test_that("get_zero_changepoints", {
|
|||
expect_equal(ncol(mat), 1)
|
||||
})
|
||||
|
||||
test_that("override_n_changepoints", {
|
||||
history <- train[1:20,]
|
||||
m <- prophet(history, fit = FALSE)
|
||||
|
||||
out <- prophet:::setup_dataframe(m, history, initialize_scales = TRUE)
|
||||
m <- out$m
|
||||
history <- out$df
|
||||
m$history <- history
|
||||
|
||||
m <- prophet:::set_changepoints(m)
|
||||
expect_equal(m$n.changepoints, 15)
|
||||
cp <- m$changepoints.t
|
||||
expect_equal(length(cp), 15)
|
||||
})
|
||||
|
||||
test_that("fourier_series_weekly", {
|
||||
mat <- prophet:::fourier_series(DATA$ds, 7, 3)
|
||||
true.values <- c(0.7818315, 0.6234898, 0.9749279, -0.2225209, 0.4338837,
|
||||
-0.9009689)
|
||||
expect_equal(true.values, mat[1, ], tolerance = 1e-6)
|
||||
mat <- prophet:::fourier_series(DATA$ds, 7, 3)
|
||||
expect_equal(true.values, mat[1, ], tolerance = 1e-6)
|
||||
})
|
||||
|
||||
test_that("fourier_series_yearly", {
|
||||
mat <- prophet:::fourier_series(DATA$ds, 365.25, 3)
|
||||
true.values <- c(0.7006152, -0.7135393, -0.9998330, 0.01827656, 0.7262249,
|
||||
0.6874572)
|
||||
expect_equal(true.values, mat[1, ], tolerance = 1e-6)
|
||||
mat <- prophet:::fourier_series(DATA$ds, 365.25, 3)
|
||||
expect_equal(true.values, mat[1, ], tolerance = 1e-6)
|
||||
})
|
||||
|
||||
test_that("growth_init", {
|
||||
|
|
@ -170,31 +233,84 @@ test_that("piecewise_logistic", {
|
|||
})
|
||||
|
||||
test_that("holidays", {
|
||||
holidays = data.frame(ds = zoo::as.Date(c('2016-12-25')),
|
||||
holidays = data.frame(ds = c('2016-12-25'),
|
||||
holiday = c('xmas'),
|
||||
lower_window = c(-1),
|
||||
upper_window = c(0))
|
||||
df <- data.frame(
|
||||
ds = seq(zoo::as.Date('2016-12-20'), zoo::as.Date('2016-12-31'), by='d'))
|
||||
ds = seq(prophet:::set_date('2016-12-20'),
|
||||
prophet:::set_date('2016-12-31'), by='d'))
|
||||
m <- prophet(train, holidays = holidays, fit = FALSE)
|
||||
feats <- prophet:::make_holiday_features(m, df$ds)
|
||||
out <- prophet:::make_holiday_features(m, df$ds)
|
||||
feats <- out$holiday.features
|
||||
priors <- out$prior.scales
|
||||
expect_equal(nrow(feats), nrow(df))
|
||||
expect_equal(ncol(feats), 2)
|
||||
expect_equal(sum(colSums(feats) - c(1, 1)), 0)
|
||||
expect_true(all(priors == c(10., 10.)))
|
||||
|
||||
holidays = data.frame(ds = zoo::as.Date(c('2016-12-25')),
|
||||
holidays = data.frame(ds = c('2016-12-25'),
|
||||
holiday = c('xmas'),
|
||||
lower_window = c(-1),
|
||||
upper_window = c(10))
|
||||
m <- prophet(train, holidays = holidays, fit = FALSE)
|
||||
feats <- prophet:::make_holiday_features(m, df$ds)
|
||||
out <- prophet:::make_holiday_features(m, df$ds)
|
||||
feats <- out$holiday.features
|
||||
priors <- out$prior.scales
|
||||
expect_equal(nrow(feats), nrow(df))
|
||||
expect_equal(ncol(feats), 12)
|
||||
expect_true(all(priors == rep(10, 12)))
|
||||
# Check prior specifications
|
||||
holidays <- data.frame(
|
||||
ds = prophet:::set_date(c('2016-12-25', '2017-12-25')),
|
||||
holiday = c('xmas', 'xmas'),
|
||||
lower_window = c(-1, -1),
|
||||
upper_window = c(0, 0),
|
||||
prior_scale = c(5., 5.)
|
||||
)
|
||||
m <- prophet(holidays = holidays, fit = FALSE)
|
||||
out <- prophet:::make_holiday_features(m, df$ds)
|
||||
priors <- out$prior.scales
|
||||
expect_true(all(priors == c(5., 5.)))
|
||||
# 2 different priors
|
||||
holidays2 <- data.frame(
|
||||
ds = prophet:::set_date(c('2012-06-06', '2013-06-06')),
|
||||
holiday = c('seans-bday', 'seans-bday'),
|
||||
lower_window = c(0, 0),
|
||||
upper_window = c(1, 1),
|
||||
prior_scale = c(8, 8)
|
||||
)
|
||||
holidays2 <- rbind(holidays, holidays2)
|
||||
m <- prophet(holidays = holidays2, fit = FALSE)
|
||||
out <- prophet:::make_holiday_features(m, df$ds)
|
||||
priors <- out$prior.scales
|
||||
expect_true(all(priors == c(8, 8, 5, 5)))
|
||||
holidays2 <- data.frame(
|
||||
ds = prophet:::set_date(c('2012-06-06', '2013-06-06')),
|
||||
holiday = c('seans-bday', 'seans-bday'),
|
||||
lower_window = c(0, 0),
|
||||
upper_window = c(1, 1)
|
||||
)
|
||||
holidays2 <- dplyr::bind_rows(holidays, holidays2)
|
||||
m <- prophet(holidays = holidays2, fit = FALSE, holidays.prior.scale = 4)
|
||||
out <- prophet:::make_holiday_features(m, df$ds)
|
||||
priors <- out$prior.scales
|
||||
expect_true(all(priors == c(4, 4, 5, 5)))
|
||||
# Check incompatible priors
|
||||
holidays <- data.frame(
|
||||
ds = prophet:::set_date(c('2016-12-25', '2016-12-27')),
|
||||
holiday = c('xmasish', 'xmasish'),
|
||||
lower_window = c(-1, -1),
|
||||
upper_window = c(0, 0),
|
||||
prior_scale = c(5., 6.)
|
||||
)
|
||||
m <- prophet(holidays = holidays, fit = FALSE)
|
||||
expect_error(prophet:::make_holiday_features(m, df$ds))
|
||||
})
|
||||
|
||||
test_that("fit_with_holidays", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
holidays <- data.frame(ds = zoo::as.Date(c('2012-06-06', '2013-06-06')),
|
||||
holidays <- data.frame(ds = c('2012-06-06', '2013-06-06'),
|
||||
holiday = c('seans-bday', 'seans-bday'),
|
||||
lower_window = c(0, 0),
|
||||
upper_window = c(1, 1))
|
||||
|
|
@ -206,51 +322,248 @@ test_that("make_future_dataframe", {
|
|||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
train.t <- DATA[1:234, ]
|
||||
m <- prophet(train.t)
|
||||
future <- make_future_dataframe(m, periods = 3, freq = 'd',
|
||||
future <- make_future_dataframe(m, periods = 3, freq = 'day',
|
||||
include_history = FALSE)
|
||||
correct <- as.Date(c('2013-04-26', '2013-04-27', '2013-04-28'))
|
||||
correct <- prophet:::set_date(c('2013-04-26', '2013-04-27', '2013-04-28'))
|
||||
expect_equal(future$ds, correct)
|
||||
|
||||
future <- make_future_dataframe(m, periods = 3, freq = 'm',
|
||||
future <- make_future_dataframe(m, periods = 3, freq = 'month',
|
||||
include_history = FALSE)
|
||||
correct <- as.Date(c('2013-05-25', '2013-06-25', '2013-07-25'))
|
||||
correct <- prophet:::set_date(c('2013-05-25', '2013-06-25', '2013-07-25'))
|
||||
expect_equal(future$ds, correct)
|
||||
})
|
||||
|
||||
test_that("auto_weekly_seasonality", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
# Should be True
|
||||
# Should be enabled
|
||||
N.w <- 15
|
||||
train.w <- DATA[1:N.w, ]
|
||||
m <- prophet(train.w, fit = FALSE)
|
||||
expect_equal(m$weekly.seasonality, 'auto')
|
||||
m <- prophet:::fit.prophet(m, train.w)
|
||||
expect_equal(m$weekly.seasonality, TRUE)
|
||||
# Should be False due to too short history
|
||||
m <- fit.prophet(m, train.w)
|
||||
expect_true('weekly' %in% names(m$seasonalities))
|
||||
true <- list(period = 7, fourier.order = 3, prior.scale = 10)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$weekly[[name]], true[[name]])
|
||||
}
|
||||
# Should be disabled due to too short history
|
||||
N.w <- 9
|
||||
train.w <- DATA[1:N.w, ]
|
||||
m <- prophet(train.w)
|
||||
expect_equal(m$weekly.seasonality, FALSE)
|
||||
expect_false('weekly' %in% names(m$seasonalities))
|
||||
m <- prophet(train.w, weekly.seasonality = TRUE)
|
||||
expect_equal(m$weekly.seasonality, TRUE)
|
||||
expect_true('weekly' %in% names(m$seasonalities))
|
||||
# Should be False due to weekly spacing
|
||||
train.w <- DATA[seq(1, nrow(DATA), 7), ]
|
||||
m <- prophet(train.w)
|
||||
expect_equal(m$weekly.seasonality, FALSE)
|
||||
expect_false('weekly' %in% names(m$seasonalities))
|
||||
m <- prophet(DATA, weekly.seasonality = 2, seasonality.prior.scale = 3)
|
||||
true <- list(period = 7, fourier.order = 2, prior.scale = 3)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$weekly[[name]], true[[name]])
|
||||
}
|
||||
})
|
||||
|
||||
test_that("auto_yearly_seasonality", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
# Should be True
|
||||
# Should be enabled
|
||||
m <- prophet(DATA, fit = FALSE)
|
||||
expect_equal(m$yearly.seasonality, 'auto')
|
||||
m <- prophet:::fit.prophet(m, DATA)
|
||||
expect_equal(m$yearly.seasonality, TRUE)
|
||||
# Should be False due to too short history
|
||||
m <- fit.prophet(m, DATA)
|
||||
expect_true('yearly' %in% names(m$seasonalities))
|
||||
true <- list(period = 365.25, fourier.order = 10, prior.scale = 10)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$yearly[[name]], true[[name]])
|
||||
}
|
||||
# Should be disabled due to too short history
|
||||
N.w <- 240
|
||||
train.y <- DATA[1:N.w, ]
|
||||
m <- prophet(train.y)
|
||||
expect_equal(m$yearly.seasonality, FALSE)
|
||||
expect_false('yearly' %in% names(m$seasonalities))
|
||||
m <- prophet(train.y, yearly.seasonality = TRUE)
|
||||
expect_equal(m$yearly.seasonality, TRUE)
|
||||
expect_true('yearly' %in% names(m$seasonalities))
|
||||
m <- prophet(DATA, yearly.seasonality = 7, seasonality.prior.scale = 3)
|
||||
true <- list(period = 365.25, fourier.order = 7, prior.scale = 3)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$yearly[[name]], true[[name]])
|
||||
}
|
||||
})
|
||||
|
||||
test_that("auto_daily_seasonality", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
# Should be enabled
|
||||
m <- prophet(DATA2, fit = FALSE)
|
||||
expect_equal(m$daily.seasonality, 'auto')
|
||||
m <- fit.prophet(m, DATA2)
|
||||
expect_true('daily' %in% names(m$seasonalities))
|
||||
true <- list(period = 1, fourier.order = 4, prior.scale = 10)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$daily[[name]], true[[name]])
|
||||
}
|
||||
# Should be disabled due to too short history
|
||||
N.d <- 430
|
||||
train.y <- DATA2[1:N.d, ]
|
||||
m <- prophet(train.y)
|
||||
expect_false('daily' %in% names(m$seasonalities))
|
||||
m <- prophet(train.y, daily.seasonality = TRUE)
|
||||
expect_true('daily' %in% names(m$seasonalities))
|
||||
m <- prophet(DATA2, daily.seasonality = 7, seasonality.prior.scale = 3)
|
||||
true <- list(period = 1, fourier.order = 7, prior.scale = 3)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$daily[[name]], true[[name]])
|
||||
}
|
||||
m <- prophet(DATA)
|
||||
expect_false('daily' %in% names(m$seasonalities))
|
||||
})
|
||||
|
||||
test_that("test_subdaily_holidays", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
holidays <- data.frame(ds = c('2017-01-02'),
|
||||
holiday = c('special_day'))
|
||||
m <- prophet(DATA2, holidays=holidays)
|
||||
fcst <- predict(m)
|
||||
expect_equal(sum(fcst$special_day == 0), 575)
|
||||
})
|
||||
|
||||
test_that("custom_seasonality", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
holidays <- data.frame(ds = c('2017-01-02'),
|
||||
holiday = c('special_day'),
|
||||
prior_scale = c(4))
|
||||
m <- prophet(holidays=holidays)
|
||||
m <- add_seasonality(m, name='monthly', period=30, fourier.order=5)
|
||||
true <- list(period = 30, fourier.order = 5, prior.scale = 10)
|
||||
for (name in names(true)) {
|
||||
expect_equal(m$seasonalities$monthly[[name]], true[[name]])
|
||||
}
|
||||
expect_error(
|
||||
add_seasonality(m, name='special_day', period=30, fourier_order=5)
|
||||
)
|
||||
expect_error(
|
||||
add_seasonality(m, name='trend', period=30, fourier_order=5)
|
||||
)
|
||||
m <- add_seasonality(m, name='weekly', period=30, fourier.order=5)
|
||||
# Test priors
|
||||
m <- prophet(holidays = holidays, yearly.seasonality = FALSE)
|
||||
m <- add_seasonality(
|
||||
m, name='monthly', period=30, fourier.order=5, prior.scale = 2)
|
||||
m <- fit.prophet(m, DATA)
|
||||
prior.scales <- prophet:::make_all_seasonality_features(
|
||||
m, m$history)$prior.scales
|
||||
expect_true(all(prior.scales == c(rep(2, 10), rep(10, 6), 4)))
|
||||
})
|
||||
|
||||
test_that("added_regressors", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
m <- prophet()
|
||||
m <- add_regressor(m, 'binary_feature', prior.scale=0.2)
|
||||
m <- add_regressor(m, 'numeric_feature', prior.scale=0.5)
|
||||
m <- add_regressor(m, 'binary_feature2', standardize=TRUE)
|
||||
df <- DATA
|
||||
df$binary_feature <- c(rep(0, 255), rep(1, 255))
|
||||
df$numeric_feature <- 0:509
|
||||
# Require all regressors in df
|
||||
expect_error(
|
||||
fit.prophet(m, df)
|
||||
)
|
||||
df$binary_feature2 <- c(rep(1, 100), rep(0, 410))
|
||||
m <- fit.prophet(m, df)
|
||||
# Check that standardizations are correctly set
|
||||
true <- list(prior.scale = 0.2, mu = 0, std = 1, standardize = 'auto')
|
||||
for (name in names(true)) {
|
||||
expect_equal(true[[name]], m$extra_regressors$binary_feature[[name]])
|
||||
}
|
||||
true <- list(prior.scale = 0.5, mu = 254.5, std = 147.368585)
|
||||
for (name in names(true)) {
|
||||
expect_equal(true[[name]], m$extra_regressors$numeric_feature[[name]],
|
||||
tolerance = 1e-5)
|
||||
}
|
||||
true <- list(prior.scale = 10., mu = 0.1960784, std = 0.3974183)
|
||||
for (name in names(true)) {
|
||||
expect_equal(true[[name]], m$extra_regressors$binary_feature2[[name]],
|
||||
tolerance = 1e-5)
|
||||
}
|
||||
# Check that standardization is done correctly
|
||||
df2 <- prophet:::setup_dataframe(m, df)$df
|
||||
expect_equal(df2$binary_feature[1], 0)
|
||||
expect_equal(df2$numeric_feature[1], -1.726962, tolerance = 1e-4)
|
||||
expect_equal(df2$binary_feature2[1], 2.022859, tolerance = 1e-4)
|
||||
# Check that feature matrix and prior scales are correctly constructed
|
||||
out <- prophet:::make_all_seasonality_features(m, df2)
|
||||
seasonal.features <- out$seasonal.features
|
||||
prior.scales <- out$prior.scales
|
||||
expect_true('binary_feature' %in% colnames(seasonal.features))
|
||||
expect_true('numeric_feature' %in% colnames(seasonal.features))
|
||||
expect_true('binary_feature2' %in% colnames(seasonal.features))
|
||||
expect_equal(ncol(seasonal.features), 29)
|
||||
expect_true(all(sort(prior.scales[27:29]) == c(0.2, 0.5, 10.)))
|
||||
# Check that forecast components are reasonable
|
||||
future <- data.frame(
|
||||
ds = c('2014-06-01'), binary_feature = c(0), numeric_feature = c(10))
|
||||
expect_error(predict(m, future))
|
||||
future$binary_feature2 <- 0.
|
||||
fcst <- predict(m, future)
|
||||
expect_equal(ncol(fcst), 31)
|
||||
expect_equal(fcst$binary_feature[1], 0)
|
||||
expect_equal(fcst$extra_regressors[1],
|
||||
fcst$numeric_feature[1] + fcst$binary_feature2[1])
|
||||
expect_equal(fcst$seasonalities[1], fcst$yearly[1] + fcst$weekly[1])
|
||||
expect_equal(fcst$seasonal[1],
|
||||
fcst$seasonalities[1] + fcst$extra_regressors[1])
|
||||
expect_equal(fcst$yhat[1], fcst$trend[1] + fcst$seasonal[1])
|
||||
})
|
||||
|
||||
test_that("copy", {
|
||||
skip_if_not(Sys.getenv('R_ARCH') != '/i386')
|
||||
inputs <- list(
|
||||
growth = c('linear', 'logistic'),
|
||||
changepoints = c(NULL, c('2016-12-25')),
|
||||
n.changepoints = c(3),
|
||||
yearly.seasonality = c(TRUE, FALSE),
|
||||
weekly.seasonality = c(TRUE, FALSE),
|
||||
daily.seasonality = c(TRUE, FALSE),
|
||||
holidays = c(NULL, 'insert_dataframe'),
|
||||
seasonality.prior.scale = c(1.1),
|
||||
holidays.prior.scale = c(1.1),
|
||||
changepoints.prior.scale = c(0.1),
|
||||
mcmc.samples = c(100),
|
||||
interval.width = c(0.9),
|
||||
uncertainty.samples = c(200)
|
||||
)
|
||||
products <- expand.grid(inputs)
|
||||
for (i in 1:length(products)) {
|
||||
if (products$holidays[i] == 'insert_dataframe') {
|
||||
holidays <- data.frame(ds=c('2016-12-25'), holiday=c('x'))
|
||||
} else {
|
||||
holidays <- NULL
|
||||
}
|
||||
m1 <- prophet(
|
||||
growth = products$growth[i],
|
||||
changepoints = products$changepoints[i],
|
||||
n.changepoints = products$n.changepoints[i],
|
||||
yearly.seasonality = products$yearly.seasonality[i],
|
||||
weekly.seasonality = products$weekly.seasonality[i],
|
||||
daily.seasonality = products$daily.seasonality[i],
|
||||
holidays = holidays,
|
||||
seasonality.prior.scale = products$seasonality.prior.scale[i],
|
||||
holidays.prior.scale = products$holidays.prior.scale[i],
|
||||
changepoints.prior.scale = products$changepoints.prior.scale[i],
|
||||
mcmc.samples = products$mcmc.samples[i],
|
||||
interval.width = products$interval.width[i],
|
||||
uncertainty.samples = products$uncertainty.samples[i],
|
||||
fit = FALSE
|
||||
)
|
||||
m2 <- prophet:::prophet_copy(m1)
|
||||
# Values should be copied correctly
|
||||
for (arg in names(inputs)) {
|
||||
expect_equal(m1[[arg]], m2[[arg]])
|
||||
}
|
||||
}
|
||||
# Check for cutoff
|
||||
changepoints <- seq.Date(as.Date('2012-06-15'), as.Date('2012-09-15'), by='d')
|
||||
cutoff <- as.Date('2012-07-25')
|
||||
m1 <- prophet(DATA, changepoints = changepoints)
|
||||
m2 <- prophet:::prophet_copy(m1, cutoff)
|
||||
changepoints <- changepoints[changepoints <= cutoff]
|
||||
expect_equal(prophet:::set_date(changepoints), m2$changepoints)
|
||||
})
|
||||
|
|
|
|||
21
README.md
|
|
@ -14,6 +14,7 @@ Prophet is [open source software](https://code.facebook.com/projects/) released
|
|||
- Prophet R package: https://cran.r-project.org/package=prophet
|
||||
- Prophet Python package: https://pypi.python.org/pypi/fbprophet/
|
||||
- Release blogpost: https://research.fb.com/prophet-forecasting-at-scale/
|
||||
- Prophet paper, "Forecasting at Scale": https://peerj.com/preprints/3190.pdf
|
||||
|
||||
## Installation in R
|
||||
|
||||
|
|
@ -30,6 +31,8 @@ After installation, you can [get started!](https://facebookincubator.github.io/p
|
|||
|
||||
On Windows, R requires a compiler so you'll need to [follow the instructions](https://github.com/stan-dev/rstan/wiki/Installing-RStan-on-Windows) provided by `rstan`. The key step is installing [Rtools](http://cran.r-project.org/bin/windows/Rtools/) before attempting to install the package.
|
||||
|
||||
If you have custom Stan compiler settings, install from source rather than the CRAN binary.
|
||||
|
||||
## Installation in Python
|
||||
|
||||
Prophet is on PyPI, so you can use pip to install it:
|
||||
|
|
@ -47,8 +50,26 @@ After installation, you can [get started!](https://facebookincubator.github.io/p
|
|||
|
||||
On Windows, PyStan requires a compiler so you'll need to [follow the instructions](http://pystan.readthedocs.io/en/latest/windows.html). The key step is installing a recent [C++ compiler](http://landinghub.visualstudio.com/visual-cpp-build-tools).
|
||||
|
||||
### Linux
|
||||
|
||||
Make sure compilers (gcc, g++) and Python development tools (python-dev) are installed. If you are using a VM, be aware that you will need at least 2GB of memory to run PyStan.
|
||||
|
||||
### Anaconda
|
||||
|
||||
Use `conda install gcc` to set up gcc. The easiest way to install Prophet is through conda-forge: `conda install -c conda-forge fbprophet`.
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 0.2 (2017.09.02)
|
||||
|
||||
- Forecasting with sub-daily data
|
||||
- Daily seasonality, and custom seasonalities
|
||||
- Extra regressors
|
||||
- Access to posterior predictive samples
|
||||
- Cross-validation function
|
||||
- Saturating minimums
|
||||
- Bugfixes
|
||||
|
||||
### Version 0.1.1 (2017.04.17)
|
||||
|
||||
- Bugfixes
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
items:
|
||||
- id: installation
|
||||
- id: quick_start
|
||||
- id: forecasting_growth
|
||||
- id: saturating_forecasts
|
||||
- id: trend_changepoints
|
||||
- id: holiday_effects
|
||||
- id: seasonality_and_holiday_effects
|
||||
- id: uncertainty_intervals
|
||||
- id: outliers
|
||||
- id: non-daily_data
|
||||
- id: diagnostics
|
||||
- id: contributing
|
||||
|
||||
# n title:, 1 items: per title:, n id: per items:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ title: "How to Contribute"
|
|||
permalink: /docs/contributing.html
|
||||
---
|
||||
|
||||
Prophet has an non-fixed release cycle but we will be making bugfixes in response to user feedback and adding features. Its current state is Beta (v0.1), we expect no obvious bugs. Please let us know if you encounter a bug by [filing an issue](https://github.com/facebookincubator/prophet/issues).
|
||||
Prophet has an non-fixed release cycle but we will be making bugfixes in response to user feedback and adding features. Its current state is Beta (v0.2), we expect no obvious bugs. Please let us know if you encounter a bug by [filing an issue](https://github.com/facebookincubator/prophet/issues).
|
||||
|
||||
We appreciate all contributions. If you are planning to contribute back bug-fixes, please do so without any further discussion.
|
||||
|
||||
|
|
|
|||
96
docs/_docs/diagnostics.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "diagnostics"
|
||||
title: "Diagnostics"
|
||||
permalink: /docs/diagnostics.html
|
||||
---
|
||||
Prophet includes functionality for time series cross validation to measure forecast error using historical data. This is done by selecting cutoff points in the history, and for each of them fitting the model using data only up to that cutoff point. We can then compare the forecasted values to the actual values. This figure illustrates a simulated historical forecast on the Peyton Manning dataset, where the model was fit to a initial history of 5 years, and a forecast was made on a one year horizon.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
[The Prophet paper](https://peerj.com/preprints/3190.pdf) gives further description of simulated historical forecasts.
|
||||
|
||||
This cross validation procedure can be done automatically for a range of historical cutoffs using the `cross_validation` function. We specify the forecast horizon (`horizon`), and then optionally the size of the initial training period (`initial`) and the spacing between cutoff dates (`period`). By default, the initial training period is set to three times the horizon, and cutoffs are made every half a horizon.
|
||||
|
||||
The output of `cross_validation` is a dataframe with the true values `y` and the out-of-sample forecast values `yhat`, at each simulated forecast date and for each cutoff date. This dataframe can then be used to compute error measures of `yhat` vs. `y`.
|
||||
|
||||
```R
|
||||
# R
|
||||
df.cv <- cross_validation(m, horizon = 730, units = 'days')
|
||||
head(df.cv)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
from fbprophet.diagnostics import cross_validation
|
||||
df_cv = cross_validation(m, horizon = '730 days')
|
||||
df_cv.head()
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>yhat</th>
|
||||
<th>yhat_lower</th>
|
||||
<th>yhat_upper</th>
|
||||
<th>y</th>
|
||||
<th>cutoff</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>0</th>
|
||||
<td>2014-01-21</td>
|
||||
<td>9.439510</td>
|
||||
<td>8.799215</td>
|
||||
<td>10.080240</td>
|
||||
<td>10.542574</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>1</th>
|
||||
<td>2014-01-22</td>
|
||||
<td>9.267086</td>
|
||||
<td>8.645900</td>
|
||||
<td>9.882225</td>
|
||||
<td>10.004283</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2</th>
|
||||
<td>2014-01-23</td>
|
||||
<td>9.263447</td>
|
||||
<td>8.628803</td>
|
||||
<td>9.852847</td>
|
||||
<td>9.732818</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3</th>
|
||||
<td>2014-01-24</td>
|
||||
<td>9.277452</td>
|
||||
<td>8.693226</td>
|
||||
<td>9.897891</td>
|
||||
<td>9.866460</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>4</th>
|
||||
<td>2014-01-25</td>
|
||||
<td>9.087565</td>
|
||||
<td>8.447306</td>
|
||||
<td>9.728898</td>
|
||||
<td>9.370927</td>
|
||||
<td>2014-01-20</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -22,6 +22,8 @@ After installation, you can [get started!](quick_start.html#r-api)
|
|||
|
||||
On Windows, R requires a compiler so you'll need to [follow the instructions](https://github.com/stan-dev/rstan/wiki/Installing-RStan-on-Windows) provided by `rstan`. The key step is installing [Rtools](http://cran.r-project.org/bin/windows/Rtools/) before attempting to install the package.
|
||||
|
||||
If you have custom Stan compiler settings, install from source rather than the CRAN binary.
|
||||
|
||||
## Installation in Python
|
||||
|
||||
Prophet is on PyPI, so you can use pip to install it:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,47 @@ docid: "non-daily_data"
|
|||
title: "Non-Daily Data"
|
||||
permalink: /docs/non-daily_data.html
|
||||
---
|
||||
Prophet doesn't strictly require daily data, but you can get strange results if you ask for daily forecasts from non-daily data and fit seasonalities. Here we forecast US retail sales volume for the next 10 years:
|
||||
## Sub-daily data
|
||||
|
||||
Prophet can make forecasts for time series with sub-daily observations by passing in a dataframe with timestamps in the `ds` column. When sub-daily data are used, daily seasonality will automatically be fit. Here we fit Prophet to data with 5-minute resolution (daily temperatures at Yosemite):
|
||||
|
||||
```R
|
||||
# R
|
||||
df <- read.csv('../examples/example_yosemite_temps.csv')
|
||||
m <- prophet(df, changepoint.prior.scale=0.01)
|
||||
future <- make_future_dataframe(m, periods = 300, freq = 60 * 60)
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst);
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
df = pd.read_csv('../examples/example_yosemite_temps.csv')
|
||||
m = Prophet(changepoint_prior_scale=0.01).fit(df)
|
||||
future = m.make_future_dataframe(periods=300, freq='H')
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
The daily seasonality will show up in the components plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
prophet_plot_components(m, fcst)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
m.plot_components(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
## Monthly data
|
||||
|
||||
You can use Prophet to fit monthly data. However, the underlying model is continuous-time, which means that you can get strange results if you fit the model to monthly data and then ask for daily forecasts. Here we forecast US retail sales volume for the next 10 years:
|
||||
|
||||
```R
|
||||
# R
|
||||
|
|
@ -23,14 +63,14 @@ fcst = m.predict(future)
|
|||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
The forecast here seems very noisy. What's happening is that this particular data set only provides monthly data. When we fit the yearly seasonality, it only has data for the first of each month and the seasonality components for the remaining days are unidentifiable and overfit. When you are fitting Prophet to monthly data, only make monthly forecasts, which can be done by passing the frequency into make_future_dataframe:
|
||||
|
||||
```R
|
||||
# R
|
||||
future <- make_future_dataframe(m, periods = 120, freq = 'm')
|
||||
future <- make_future_dataframe(m, periods = 120, freq = 'month')
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst)
|
||||
```
|
||||
|
|
@ -41,5 +81,5 @@ fcst = m.predict(future)
|
|||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -147,37 +147,37 @@ forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
|
|||
<tr>
|
||||
<th>3265</th>
|
||||
<td>2017-01-15</td>
|
||||
<td>8.205065</td>
|
||||
<td>7.488507</td>
|
||||
<td>8.887731</td>
|
||||
<td>8.206753</td>
|
||||
<td>7.485107</td>
|
||||
<td>8.920149</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3266</th>
|
||||
<td>2017-01-16</td>
|
||||
<td>8.530088</td>
|
||||
<td>7.862778</td>
|
||||
<td>9.223688</td>
|
||||
<td>8.531766</td>
|
||||
<td>7.779331</td>
|
||||
<td>9.284859</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3267</th>
|
||||
<td>2017-01-17</td>
|
||||
<td>8.317468</td>
|
||||
<td>7.644606</td>
|
||||
<td>9.021893</td>
|
||||
<td>8.319156</td>
|
||||
<td>7.610545</td>
|
||||
<td>8.986889</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3268</th>
|
||||
<td>2017-01-18</td>
|
||||
<td>8.150081</td>
|
||||
<td>7.462394</td>
|
||||
<td>8.889095</td>
|
||||
<td>8.151772</td>
|
||||
<td>7.415802</td>
|
||||
<td>8.875191</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>3269</th>
|
||||
<td>2017-01-19</td>
|
||||
<td>8.162015</td>
|
||||
<td>7.438503</td>
|
||||
<td>8.877361</td>
|
||||
<td>8.163690</td>
|
||||
<td>7.427153</td>
|
||||
<td>8.884826</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -205,6 +205,8 @@ m.plot_components(forecast);
|
|||

|
||||
|
||||
|
||||
More details about the options available for each method are available in the docstrings, for example, via `help(Prophet)` or `help(Prophet.fit)`.
|
||||
|
||||
## R API
|
||||
|
||||
In R, we use the normal model fitting API. We provide a `prophet` function that performs fitting and returns a model object. You can then call `predict` and `plot` on this model object.
|
||||
|
|
@ -254,12 +256,12 @@ tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')])
|
|||
```
|
||||
|
||||
ds yhat yhat_lower yhat_upper
|
||||
3265 2017-01-14 7.832396 7.140713 8.533132
|
||||
3266 2017-01-15 8.214232 7.460897 8.918678
|
||||
3267 2017-01-16 8.539239 7.788240 9.262142
|
||||
3268 2017-01-17 8.326654 7.615613 9.003147
|
||||
3269 2017-01-18 8.159337 7.382162 8.889958
|
||||
3270 2017-01-19 8.171276 7.354854 8.922918
|
||||
3265 2017-01-14 7.825609 7.183818 8.488012
|
||||
3266 2017-01-15 8.207400 7.478778 8.951113
|
||||
3267 2017-01-16 8.532394 7.826360 9.240482
|
||||
3268 2017-01-17 8.319785 7.596815 9.042505
|
||||
3269 2017-01-18 8.152424 7.440858 8.874581
|
||||
3270 2017-01-19 8.164327 7.419148 8.882906
|
||||
|
||||
|
||||
|
||||
|
|
@ -270,7 +272,7 @@ You can use the generic `plot` function to plot the forecast, by passing in the
|
|||
plot(m, forecast)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
You can use the `prophet_plot_components` function to see the forecast broken down into trend, weekly seasonality, and yearly seasonality.
|
||||
|
|
@ -280,5 +282,7 @@ You can use the `prophet_plot_components` function to see the forecast broken do
|
|||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
More details about the options available for each method are available in the docstrings, for example, via `?prophet` or `?fit.prophet`. This documentation is also available in the [reference manual](https://cran.r-project.org/web/packages/prophet/prophet.pdf) on CRAN.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "forecasting_growth"
|
||||
title: "Forecasting Growth"
|
||||
permalink: /docs/forecasting_growth.html
|
||||
docid: "saturating_forecasts"
|
||||
title: "Saturating Forecasts"
|
||||
permalink: /docs/saturating_forecasts.html
|
||||
---
|
||||
### Forecasting Growth
|
||||
|
||||
By default, Prophet uses a linear model for its forecast. When forecasting growth, there is usually some maximum achievable point: total market size, total population size, etc. This is called the carrying capacity, and the forecast should saturate at this point.
|
||||
|
||||
Prophet allows you to make forecasts using a [logistic growth](https://en.wikipedia.org/wiki/Logistic_function) trend model, with a specified carrying capacity. We illustrate this with the log number of page visits to the [R (programming language)](https://en.wikipedia.org/wiki/R_%28programming_language%29) page on Wikipedia:
|
||||
|
|
@ -44,13 +46,6 @@ m <- prophet(df, growth = 'logistic')
|
|||
```
|
||||
We make a dataframe for future predictions as before, except we must also specify the capacity in the future. Here we keep capacity constant at the same value as in the history, and forecast 3 years into the future:
|
||||
|
||||
```python
|
||||
# Python
|
||||
future = m.make_future_dataframe(periods=1826)
|
||||
future['cap'] = 8.5
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
future <- make_future_dataframe(m, periods = 1826)
|
||||
|
|
@ -58,6 +53,44 @@ future$cap <- 8.5
|
|||
fcst <- predict(m, future)
|
||||
plot(m, fcst);
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
future = m.make_future_dataframe(periods=1826)
|
||||
future['cap'] = 8.5
|
||||
fcst = m.predict(future)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### Saturating Minimum
|
||||
|
||||
The logistic growth model can also handle a saturating minimum, which is specified with a column `floor` in the same way as the `cap` column specifies the maximum:
|
||||
|
||||
```R
|
||||
# R
|
||||
df$y <- 10 - df$y
|
||||
df$cap <- 6
|
||||
df$floor <- 1.5
|
||||
future$cap <- 6
|
||||
future$floor <- 1.5
|
||||
m <- prophet(df, growth = 'logistic')
|
||||
fcst <- predict(m, future)
|
||||
plot(m, fcst)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
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)
|
||||
m.plot(fcst);
|
||||
```
|
||||
|
||||

|
||||
|
||||
367
docs/_docs/seasonality_and_holiday_effects.md
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
---
|
||||
layout: docs
|
||||
docid: "seasonality_and_holiday_effects"
|
||||
title: "Seasonality And Holiday Effects"
|
||||
permalink: /docs/seasonality_and_holiday_effects.html
|
||||
---
|
||||
### Specifying Seasonalities
|
||||
|
||||
Prophet will by default fit weekly and yearly seasonalities, if the time series is more than two cycles long. It will also fit daily seasonality for a sub-daily time series. You can add other seasonalities (monthly, quarterly, hourly) using the `add_seasonality` method (Python) or function (R).
|
||||
|
||||
The inputs to this function are a name, the period of the seasonality in days, and the number of Fourier terms for the seasonality. Increasing the number of Fourier terms allows the seasonality to fit faster changing cycles, but can also lead to overfitting: $N$ Fourier terms corresponds to $2N$ variables used for modeling the cycle. For reference, by default Prophet uses 3 terms for weekly seasonality and 10 for yearly seasonality. An optional input to `add_seasonality` is the prior scale for that seasonal component - this is discussed below.
|
||||
|
||||
As an example, here we fit the Peyton Manning data from the Quickstart, but replace the weekly seasonality with monthly seasonality. The monthly seasonality then will appear in the components plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(weekly.seasonality=FALSE)
|
||||
m <- add_seasonality(m, name='monthly', period=30.5, fourier.order=5)
|
||||
m <- fit.prophet(m, df)
|
||||
forecast <- predict(m, future)
|
||||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(weekly_seasonality=False)
|
||||
m.add_seasonality(name='monthly', period=30.5, fourier_order=5)
|
||||
forecast = m.fit(df).predict(future)
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
### Modeling Holidays and Special Events
|
||||
If you have holidays or other recurring events that you'd like to model, you must create a dataframe for them. It has two columns (`holiday` and `ds`) and a row for each occurrence of the holiday. It must include all occurrences of the holiday, both in the past (back as far as the historical data go) and in the future (out as far as the forecast is being made). If they won't repeat in the future, Prophet will model them and then not include them in the forecast.
|
||||
|
||||
You can also include columns `lower_window` and `upper_window` which extend the holiday out to `[lower_window, upper_window]` days around the date. For instance, if you wanted to included Christmas Eve in addition to Christmas you'd include `lower_window=-1,upper_window=0`. If you wanted to use Black Friday in addition to Thanksgiving, you'd include `lower_window=0,upper_window=1`. You can also include a column `prior_scale` to set the prior scale separately for each holiday, as described below.
|
||||
|
||||
Here we create a dataframe that includes the dates of all of Peyton Manning's playoff appearances:
|
||||
|
||||
```python
|
||||
# Python
|
||||
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))
|
||||
```
|
||||
```R
|
||||
# R
|
||||
library(dplyr)
|
||||
playoffs <- data_frame(
|
||||
holiday = 'playoff',
|
||||
ds = as.Date(c('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 <- data_frame(
|
||||
holiday = 'superbowl',
|
||||
ds = as.Date(c('2010-02-07', '2014-02-02', '2016-02-07')),
|
||||
lower_window = 0,
|
||||
upper_window = 1
|
||||
)
|
||||
holidays <- bind_rows(playoffs, superbowls)
|
||||
```
|
||||
Above we have include the superbowl days as both playoff games and superbowl games. This means that the superbowl effect will be an additional additive bonus on top of the playoff effect.
|
||||
|
||||
Once the table is created, holiday effects are included in the forecast by passing them in with the `holidays` argument. Here we do it with the Peyton Manning data from the Quickstart:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(holidays=holidays)
|
||||
forecast = m.fit(df).predict(future)
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, holidays = holidays)
|
||||
forecast <- predict(m, future)
|
||||
```
|
||||
The holiday effect can be seen in the `forecast` dataframe:
|
||||
|
||||
```R
|
||||
# R
|
||||
forecast %>%
|
||||
select(ds, playoff, superbowl) %>%
|
||||
filter(abs(playoff + superbowl) > 0) %>%
|
||||
tail(10)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
forecast[(forecast['playoff'] + forecast['superbowl']).abs() > 0][
|
||||
['ds', 'playoff', 'superbowl']][-10:]
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>playoff</th>
|
||||
<th>superbowl</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>2190</th>
|
||||
<td>2014-02-02</td>
|
||||
<td>1.226679</td>
|
||||
<td>1.192500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2191</th>
|
||||
<td>2014-02-03</td>
|
||||
<td>1.911294</td>
|
||||
<td>1.373781</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2532</th>
|
||||
<td>2015-01-11</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2533</th>
|
||||
<td>2015-01-12</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2901</th>
|
||||
<td>2016-01-17</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2902</th>
|
||||
<td>2016-01-18</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2908</th>
|
||||
<td>2016-01-24</td>
|
||||
<td>1.226679</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2909</th>
|
||||
<td>2016-01-25</td>
|
||||
<td>1.911294</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2922</th>
|
||||
<td>2016-02-07</td>
|
||||
<td>1.226679</td>
|
||||
<td>1.192500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2923</th>
|
||||
<td>2016-02-08</td>
|
||||
<td>1.911294</td>
|
||||
<td>1.373781</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
The holiday effects will also show up in the components plot, where we see that there is a spike on the days around playoff appearances, with an especially large spike for the superbowl:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
prophet_plot_components(m, forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
Individual holidays can be plotted using the `plot_forecast_component` method (Python) or function (R). For example, `m.plot_forecast_component(forecast, 'superbowl')` in Python and `plot_forecast_component(forecast, 'superbowl')` in R to plot just the superbowl holiday component.
|
||||
|
||||
### Prior scale for holidays and seasonality
|
||||
If you find that the holidays are overfitting, you can adjust their prior scale to smooth them using the parameter `holidays_prior_scale`. By default this parameter is 10, which provides very little regularization. Reducing this parameter dampens holiday effects:
|
||||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, holidays = holidays, holidays.prior.scale = 0.05)
|
||||
forecast <- predict(m, future)
|
||||
forecast %>%
|
||||
select(ds, playoff, superbowl) %>%
|
||||
filter(abs(playoff + superbowl) > 0) %>%
|
||||
tail(10)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
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:]
|
||||
```
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<table border="1" class="dataframe">
|
||||
<thead>
|
||||
<tr style="text-align: right;">
|
||||
<th></th>
|
||||
<th>ds</th>
|
||||
<th>playoff</th>
|
||||
<th>superbowl</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>2190</th>
|
||||
<td>2014-02-02</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.957093</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2191</th>
|
||||
<td>2014-02-03</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.979777</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2532</th>
|
||||
<td>2015-01-11</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2533</th>
|
||||
<td>2015-01-12</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2901</th>
|
||||
<td>2016-01-17</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2902</th>
|
||||
<td>2016-01-18</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2908</th>
|
||||
<td>2016-01-24</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2909</th>
|
||||
<td>2016-01-25</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.000000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2922</th>
|
||||
<td>2016-02-07</td>
|
||||
<td>1.200631</td>
|
||||
<td>0.957093</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>2923</th>
|
||||
<td>2016-02-08</td>
|
||||
<td>1.841906</td>
|
||||
<td>0.979777</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
The magnitude of the holiday effect has been reduced compared to before, especially for superbowls, which had the fewest observations. There is a parameter `seasonality_prior_scale` which similarly adjusts the extent to which the seasonality model will fit the data.
|
||||
|
||||
Prior scales can be set separately for individual holidays by including a column `prior_scale` in the holidays dataframe. Prior scales for individual seasonalities can be passed as an argument to `add_seasonality`. For instance, the prior scale for just weekly seasonality can be set using:
|
||||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet()
|
||||
m.add_seasonality(
|
||||
name='weekly', period=7, fourier_order=3, prior_scale=0.1);
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet()
|
||||
m <- add_seasonality(
|
||||
m, name='weekly', period=7, fourier.order=3, prior.scale=0.1)
|
||||
```
|
||||
### Additional regressors
|
||||
Additional regressors can be added to the linear part of the model using the `add_regressor` method or function. A column with the regressor value will need to be present in both the fitting and prediction dataframes. For example, we can add an additional effect on Sundays during the NFL season. On the components plot, this effect will show up in the 'extra_regressors' plot:
|
||||
|
||||
```R
|
||||
# R
|
||||
nfl_sunday <- function(ds) {
|
||||
dates <- as.Date(ds)
|
||||
month <- as.numeric(format(dates, '%m'))
|
||||
as.numeric((weekdays(dates) == "Sunday") & (month > 8 | month < 2))
|
||||
}
|
||||
df$nfl_sunday <- nfl_sunday(df$ds)
|
||||
|
||||
m <- prophet()
|
||||
m <- add_regressor(m, 'nfl_sunday')
|
||||
m <- fit.prophet(m, df)
|
||||
|
||||
future$nfl_sunday <- nfl_sunday(future$ds)
|
||||
|
||||
forecast <- predict(m, future)
|
||||
prophet_plot_components(m, forecast)
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
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)
|
||||
m.plot_components(forecast);
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
NFL Sundays could also have been handled using the "holidays" interface described above, by creating a list of past and future NFL Sundays. The `add_regressor` function provides a more general interface for defining extra linear regressors, and in particular does not require that the regressor be a binary indicator. Another time series could be used as a regressor, although its future values would have to be known.
|
||||
|
||||
The `add_regressor` function has optional arguments for specifying the prior scale (holiday prior scale is used by default) and whether or not the regressor is standardized - see the docstring with `help(Prophet.add_regressor)` in Python and `?add_regressor` in R.
|
||||
|
|
@ -64,7 +64,7 @@ If you wish, rather than using automatic changepoint detection you can manually
|
|||
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, changepoints = c(as.Date('2014-01-01')))
|
||||
m <- prophet(df, changepoints = c('2014-01-01'))
|
||||
forecast <- predict(m, future)
|
||||
plot(m, forecast);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ By default Prophet will only return uncertainty in the trend and observation noi
|
|||
|
||||
```python
|
||||
# Python
|
||||
m = Prophet(mcmc_samples=500)
|
||||
m = Prophet(mcmc_samples=300)
|
||||
forecast = m.fit(df).predict(future)
|
||||
```
|
||||
```R
|
||||
# R
|
||||
m <- prophet(df, mcmc.samples = 500)
|
||||
m <- prophet(df, mcmc.samples = 300)
|
||||
forecast <- predict(m, future)
|
||||
```
|
||||
This replaces the typical MAP estimation with MCMC sampling, and takes much longer - think 10 minutes instead of 10 seconds. If you do full sampling, then you will see the uncertainty in seasonal components when you plot them:
|
||||
|
|
@ -53,4 +53,6 @@ prophet_plot_components(m, forecast);
|
|||

|
||||
|
||||
|
||||
You can access the raw posterior predictive samples in Python using the method `m.predictive_samples(future)`, or in R using the function `predictive_samples(m, future)`.
|
||||
|
||||
There are upstream issues in PyStan for Windows which make MCMC sampling extremely slow. The best choice for MCMC sampling in Windows is to use R, or Python in a Linux VM.
|
||||
|
|
|
|||
BIN
docs/static/diagnostics_files/diagnostics_3_0.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 52 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_10_0.png
vendored
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_12_0.png
vendored
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_13_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 48 KiB |
BIN
docs/static/non-daily_data_files/non-daily_data_9_1.png
vendored
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/static/outliers_files/outliers_10_0.png
vendored
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
BIN
docs/static/outliers_files/outliers_12_1.png
vendored
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
BIN
docs/static/outliers_files/outliers_13_0.png
vendored
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 70 KiB |
BIN
docs/static/outliers_files/outliers_3_1.png
vendored
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
BIN
docs/static/outliers_files/outliers_4_0.png
vendored
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 38 KiB |
BIN
docs/static/outliers_files/outliers_6_1.png
vendored
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
BIN
docs/static/outliers_files/outliers_7_0.png
vendored
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 73 KiB |
BIN
docs/static/outliers_files/outliers_9_1.png
vendored
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
docs/static/quick_start_files/quick_start_12_0.png
vendored
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 101 KiB |
BIN
docs/static/quick_start_files/quick_start_14_0.png
vendored
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
docs/static/quick_start_files/quick_start_26_0.png
vendored
|
Before Width: | Height: | Size: 86 KiB |
BIN
docs/static/quick_start_files/quick_start_27_0.png
vendored
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/static/quick_start_files/quick_start_28_0.png
vendored
|
Before Width: | Height: | Size: 42 KiB |
BIN
docs/static/quick_start_files/quick_start_29_0.png
vendored
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_12_1.png
vendored
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_13_0.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_15_1.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/static/saturating_forecasts_files/saturating_forecasts_16_0.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_15_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_16_0.png
vendored
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_25_1.png
vendored
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_26_0.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_3_1.png
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/static/seasonality_and_holiday_effects_files/seasonality_and_holiday_effects_4_0.png
vendored
Normal file
|
After Width: | Height: | Size: 53 KiB |