Add utility for plotting changepoints (Py), and put in plotting file (R and Py)

This commit is contained in:
Ben Letham 2018-05-03 11:10:11 -07:00
parent 7c95c62cf0
commit 3da46503ed
11 changed files with 206 additions and 161 deletions

View file

@ -1,20 +1,20 @@
# Generated by roxygen2: do not edit by hand
S3method(plot,prophet)
S3method(predict,prophet)
export(add_changepoints_to_plot)
export(add_regressor)
export(add_seasonality)
export(all_metrics)
export(cross_validation)
export(dyplot.prophet)
export(fit.prophet)
export(layer_changepoints)
export(mae)
export(make_future_dataframe)
export(mape)
export(me)
export(mpe)
export(mse)
export(plot.prophet)
export(plot_forecast_component)
export(predictive_samples)
export(prophet)

View file

@ -302,6 +302,40 @@ plot_seasonality <- function(m, name, uncertainty = TRUE) {
return(gg.s)
}
#' Get layers to overlay significant changepoints on prophet forecast plot.
#'
#' @param m Prophet model object.
#' @param threshold Numeric, changepoints where abs(delta) >= threshold are
#' significant. (Default 0.01)
#' @param cp_color Character, line color. (Default "red")
#' @param cp_linetype Character or integer, line type. (Default "dashed")
#' @param trend Logical, if FALSE, do not draw trend line. (Default TRUE)
#' @param ... Other arguments passed on to layers.
#'
#' @return A list of ggplot2 layers.
#'
#' @examples
#' \dontrun{
#' plot(m, fcst) + add_changepoints_to_plot(m)
#' }
#'
#' @export
add_changepoints_to_plot <- function(m, threshold = 0.01, cp_color = "red",
cp_linetype = "dashed", trend = TRUE, ...) {
layers <- list()
if (trend) {
trend_layer <- ggplot2::geom_line(
ggplot2::aes_string("ds", "trend"), color = cp_color, ...)
layers <- append(layers, trend_layer)
}
signif_changepoints <- m$changepoints[abs(m$params$delta) >= threshold]
cp_layer <- ggplot2::geom_vline(
xintercept = as.integer(signif_changepoints), color = cp_color,
linetype = cp_linetype, ...)
layers <- append(layers, cp_layer)
return(layers)
}
#' Plot the prophet forecast.
#'
#' @param x Prophet object.

View file

@ -1,33 +0,0 @@
#' Get layers to overlay significant changepoints on prophet forecast plot.
#'
#' @param m Prophet model object.
#' @param threshold Numeric, changepoints where abs(delta) >= threshold are
#' significant. (Default 0.01)
#' @param cp_color Character, line color. (Default "red")
#' @param cp_linetype Character or integer, line type. (Default "dashed")
#' @param trend Logical, if FALSE, do not draw trend line. (Default TRUE)
#' @param ... Other arguments passed on to layers.
#'
#' @return A list of ggplot2 layers.
#'
#' @examples
#' \dontrun{
#' plot(m, fcst) + layer_changepoints(m)
#' }
#'
#' @export
layer_changepoints <- function(m, threshold = 0.01, cp_color = "red",
cp_linetype = "dashed", trend = TRUE, ...) {
layers <- list()
if (trend) {
trend_layer <- ggplot2::geom_line(
ggplot2::aes_string("ds", "trend"), color = cp_color, ...)
layers <- append(layers, trend_layer)
}
signif_changepoints <- m$changepoints[abs(m$params$delta) >= threshold]
cp_layer <- ggplot2::geom_vline(
xintercept = as.integer(signif_changepoints), color = cp_color,
linetype = cp_linetype, ...)
layers <- append(layers, cp_layer)
return(layers)
}

View file

@ -1,10 +1,10 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{layer_changepoints}
\alias{layer_changepoints}
% Please edit documentation in R/plot.R
\name{add_changepoints_to_plot}
\alias{add_changepoints_to_plot}
\title{Get layers to overlay significant changepoints on prophet forecast plot.}
\usage{
layer_changepoints(m, threshold = 0.01, cp_color = "red",
add_changepoints_to_plot(m, threshold = 0.01, cp_color = "red",
cp_linetype = "dashed", trend = TRUE, ...)
}
\arguments{
@ -29,7 +29,7 @@ Get layers to overlay significant changepoints on prophet forecast plot.
}
\examples{
\dontrun{
plot(m, fcst) + layer_changepoints(m)
plot(m, fcst) + add_changepoints_to_plot(m)
}
}

View file

@ -4,7 +4,7 @@
\alias{compile_stan_model}
\title{Compile Stan model}
\usage{
compile_stan_model(model)
compile_stan_model()
}
\arguments{
\item{model}{String 'linear' or 'logistic' to specify a linear or logistic

View file

@ -1,18 +1,20 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/metrics.R
\name{create_metric_data}
\alias{create_metric_data}
\title{Prepare dataframe for metrics calculation.}
\usage{
create_metric_data(fcst)
}
\arguments{
\item{fcst}{Dataframe output of `predict`.}
}
\value{
A dataframe only with y and yhat as a column.
}
\description{
Prepare dataframe for metrics calculation.
}
\keyword{internal}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/metrics.R
\name{create_metric_data}
\alias{create_metric_data}
\title{Prepare dataframe for metrics calculation.}
\usage{
create_metric_data(m = NULL, df = NULL)
}
\arguments{
\item{m}{Prophet object. Default NULL}
\item{df}{A dataframe which is output of `simulated_historical_forecasts` or `cross_validation` Default NULL}
}
\value{
A dataframe only with y and yhat as a column.
}
\description{
Prepare dataframe for metrics calculation.
}
\keyword{internal}

View file

@ -1,18 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{get_changepoint_matrix}
\alias{get_changepoint_matrix}
\title{Gets changepoint matrix for history dataframe.}
\usage{
get_changepoint_matrix(m)
}
\arguments{
\item{m}{Prophet object.}
}
\value{
array of indexes.
}
\description{
Gets changepoint matrix for history dataframe.
}
\keyword{internal}

View file

@ -4,7 +4,7 @@
\alias{get_prophet_stan_model}
\title{Load compiled Stan model}
\usage{
get_prophet_stan_model(model)
get_prophet_stan_model()
}
\arguments{
\item{model}{String 'linear' or 'logistic' to specify a linear or logistic

View file

@ -0,0 +1,18 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/metrics.R
\name{make_metrics_function}
\alias{make_metrics_function}
\title{Meta function to make the function which evaluate metrics.}
\usage{
make_metrics_function(metrics)
}
\arguments{
\item{metrics}{metrics function}
}
\value{
A function using for metrics evaluation.
}
\description{
Meta function to make the function which evaluate metrics.
}
\keyword{internal}

View file

@ -1,83 +1,91 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/metrics.R
\name{metrics}
\alias{metrics}
\alias{me}
\alias{mse}
\alias{rmse}
\alias{mae}
\alias{mpe}
\alias{mape}
\alias{all_metrics}
\title{Metrics for Time Series Forecasts}
\usage{
me(fcst)
mse(fcst)
rmse(fcst)
mae(fcst)
mpe(fcst)
mape(fcst)
all_metrics(fcst)
}
\arguments{
\item{fcst}{Dataframe output of `predict`.}
}
\value{
metrics value (numeric)
}
\description{
A time-series forecast requires making a quantitative prediction of future values.
After forecast, we also have to provide accurracy of forecasts to check wether the forecast serves our need.
Metrics for time series forecasts are so useful in telling you how your model is good and helping you determine which particular forecasting models work best.
}
\details{
Here, as a notation, we assume that \eqn{y} is the actual value and \eqn{yhat} is the forecast value.
Mean Error (ME, \code{me})
The Mean Error (ME) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} y_{t}-yhat_{t} .}
Mean Squared Error (MSE, \code{mse})
The Mean Squared Error (MSE) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} (y_{t}-yhat_{t})^2 .}
Root Mean Square Error (RMSE, \code{rmse})
Root Mean Square Error (RMSE) is define by the formula:
\deqn{ \sqrt{\frac{1}{n} \sum_{t=1}^{n} (y_{t}-yhat_{t})^2} .}
Mean Absolute Error (MAE, \code{mae})
The Mean Absolute Error (MAE) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} | y_{t}-yhat_{t} | .}
Mean Percentage Error (MPE, \code{mpe})
The Mean Percentage Error (MPE) is usually expressed as a percentage
and is defined by the formula:
\deqn{ \frac{100}{n} \sum_{t=1}^{n} \frac {y_{t}-yhat_{t}}{y_{t}} .}
Mean Absolute Percentage Error (MAPE, \code{mape})
The Mean absolute Percentage Error (MAPE), also known as Mean Absolute Percentage Deviation (MAPD), is usually expressed as a percentage,
and is defined by the formula:
\deqn{ \frac{100}{n} \sum_{t=1}^{n} | \frac {y_{t}-yhat_{t}}{y_{t}}| .}
}
\examples{
\dontrun{
# Create example model
library(readr)
df <- read_csv('../tests/testthat/data.csv')
m <- prophet(df)
# You can check your models's accuracy using me, mse, rmse ...etc.
print(rmse(m))
}
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/metrics.R
\name{metrics}
\alias{metrics}
\alias{me}
\alias{mse}
\alias{rmse}
\alias{mae}
\alias{mpe}
\alias{mape}
\alias{all_metrics}
\title{Metrics for Time Series Forecasts}
\usage{
me(m = NULL, df = NULL)
mse(m = NULL, df = NULL)
rmse(m = NULL, df = NULL)
mae(m = NULL, df = NULL)
mpe(m = NULL, df = NULL)
mape(m = NULL, df = NULL)
all_metrics(m = NULL, df = NULL)
}
\arguments{
\item{m}{Prophet object. Default NULL}
\item{df}{A dataframe which is output of `simulated_historical_forecasts` or `cross_validation` Default NULL}
}
\value{
metrics value (numeric)
}
\description{
A time-series forecast requires making a quantitative prediction of future values.
After forecast, we also have to provide accurracy of forecasts to check wether the forecast serves our need.
Metrics for time series forecasts are so useful in telling you how your model is good and helping you determine which particular forecasting models work best.
}
\details{
Here, as a notation, we assume that \eqn{y} is the actual value and \eqn{yhat} is the forecast value.
Mean Error (ME, \code{me})
The Mean Error (ME) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} y_{t}-yhat_{t} .}
Mean Squared Error (MSE, \code{mse})
The Mean Squared Error (MSE) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} (y_{t}-yhat_{t})^2 .}
Root Mean Square Error (RMSE, \code{rmse})
Root Mean Square Error (RMSE) is define by the formula:
\deqn{ \sqrt{\frac{1}{n} \sum_{t=1}^{n} (y_{t}-yhat_{t})^2} .}
Mean Absolute Error (MAE, \code{mae})
The Mean Absolute Error (MAE) is defined by the formula:
\deqn{ \frac{1}{n} \sum_{t=1}^{n} | y_{t}-yhat_{t} | .}
Mean Percentage Error (MPE, \code{mpe})
The Mean Percentage Error (MPE) is usually expressed as a percentage
and is defined by the formula:
\deqn{ \frac{100}{n} \sum_{t=1}^{n} \frac {y_{t}-yhat_{t}}{y_{t}} .}
Mean Absolute Percentage Error (MAPE, \code{mape})
The Mean absolute Percentage Error (MAPE), also known as Mean Absolute Percentage Deviation (MAPD), is usually expressed as a percentage,
and is defined by the formula:
\deqn{ \frac{100}{n} \sum_{t=1}^{n} | \frac {y_{t}-yhat_{t}}{y_{t}}| .}
}
\examples{
\dontrun{
# Create example model
library(readr)
library(prophet)
df <- read_csv('../tests/testthat/data.csv')
m <- prophet(df)
future <- make_future_dataframe(m, periods = 365)
forecast <- predict(m, future)
all_metrics(forecast)
df.cv <- cross_validation(m, horizon = 100, units = 'days')
all_metrics(df.cv)
# You can check your models's accuracy using me, mse, rmse ...etc.
print(rmse(m))
}
}

View file

@ -333,3 +333,37 @@ def plot_seasonality(m, name, ax=None, uncertainty=True):
ax.set_xlabel('ds')
ax.set_ylabel(name)
return artists
def add_changepoints_to_plot(
ax, m, fcst, threshold=0.01, cp_color='r', cp_linestyle='--', trend=True,
):
"""Add markers for significant changepoints to prophet forecast plot.
Example:
fig = m.plot(forecast)
add_changepoints_to_plot(fig.gca(), m, forecast)
Parameters
----------
ax: axis on which to overlay changepoint markers.
m: Prophet model.
fcst: Forecast output from m.predict.
threshold: Threshold on trend change magnitude for significance.
cp_color: Color of changepoint markers.
cp_linestyle: Linestyle for changepoint markers.
trend: If True, will also overlay the trend.
Returns
-------
a list of matplotlib artists
"""
artists = []
if trend:
artists.append(ax.plot(fcst['ds'], fcst['trend'], c=cp_color))
signif_changepoints = m.changepoints[
np.abs(np.nanmean(m.params['delta'], axis=0)) >= threshold
]
for cp in signif_changepoints:
artists.append(ax.axvline(x=cp, c=cp_color, ls=cp_linestyle))
return artists