ソースを参照

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

Ben Letham 7 年 前
コミット
3da46503ed

+ 2 - 2
R/NAMESPACE

@@ -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)

+ 34 - 0
R/R/plot.R

@@ -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.

+ 0 - 33
R/R/utils.R

@@ -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)
-}

+ 5 - 5
R/man/layer_changepoints.Rd

@@ -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)
 }
 
 }

+ 1 - 1
R/man/compile_stan_model.Rd

@@ -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

+ 20 - 18
R/man/create_metric_data.Rd

@@ -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}

+ 0 - 18
R/man/get_changepoint_matrix.Rd

@@ -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}

+ 1 - 1
R/man/get_prophet_stan_model.Rd

@@ -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

+ 18 - 0
R/man/make_metrics_function.Rd

@@ -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}

+ 91 - 83
R/man/metrics.Rd

@@ -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))
+}
+}

+ 34 - 0
python/fbprophet/plot.py

@@ -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