Browse Source

Allow not showing capacity on plots

Ben Letham 8 years ago
parent
commit
8155143af0
5 changed files with 64 additions and 34 deletions
  1. 18 11
      R/R/prophet.R
  2. 5 2
      R/man/plot.prophet.Rd
  3. 4 1
      R/man/plot_trend.Rd
  4. 4 1
      R/man/prophet_plot_components.Rd
  5. 33 19
      python/fbprophet/forecaster.py

+ 18 - 11
R/R/prophet.R

@@ -900,6 +900,8 @@ df_for_plotting <- function(m, fcst) {
 #' @param fcst Data frame returned by predict(m, df).
 #' @param uncertainty Boolean indicating if the uncertainty interval for yhat
 #'  should be plotted. Must be present in fcst as yhat_lower and yhat_upper.
+#' @param plot_cap Boolean indicating if the capacity should be shown in the
+#'  figure, if available.
 #' @param xlabel Optional label for x-axis
 #' @param ylabel Optional label for y-axis
 #' @param ... additional arguments
@@ -917,12 +919,12 @@ df_for_plotting <- function(m, fcst) {
 #' }
 #'
 #' @export
-plot.prophet <- function(x, fcst, uncertainty = TRUE, xlabel = 'ds',
-                         ylabel = 'y', ...) {
+plot.prophet <- function(x, fcst, uncertainty = TRUE, plot_cap = TRUE,
+                         xlabel = 'ds', ylabel = 'y', ...) {
   df <- df_for_plotting(x, fcst)
   gg <- ggplot2::ggplot(df, ggplot2::aes(x = ds, y = y)) +
     ggplot2::labs(x = xlabel, y = ylabel)
-  if (exists('cap', where = df)) {
+  if (exists('cap', where = df) && plot_cap) {
     gg <- gg + ggplot2::geom_line(
       ggplot2::aes(y = cap), linetype = 'dashed', na.rm = TRUE)
   }
@@ -949,15 +951,18 @@ plot.prophet <- function(x, fcst, uncertainty = TRUE, xlabel = 'ds',
 #' @param fcst Data frame returned by predict(m, df).
 #' @param uncertainty Boolean indicating if the uncertainty interval should be
 #'  plotted for the trend, from fcst columns trend_lower and trend_upper.
+#' @param plot_cap Boolean indicating if the capacity should be shown in the
+#'  figure, if available.
 #'
 #' @return Invisibly return a list containing the plotted ggplot objects
 #'
 #' @export
 #' @importFrom dplyr "%>%"
-prophet_plot_components <- function(m, fcst, uncertainty = TRUE) {
+prophet_plot_components <- function(m, fcst, uncertainty = TRUE,
+                                    plot_cap = TRUE) {
   df <- df_for_plotting(m, fcst)
   # Plot the trend
-  panels <- list(plot_trend(df, uncertainty))
+  panels <- list(plot_trend(df, uncertainty, plot_cap))
   # Plot holiday components, if present.
   if (!is.null(m$holidays)) {
     panels[[length(panels) + 1]] <- plot_holidays(m, df, uncertainty)
@@ -985,13 +990,15 @@ prophet_plot_components <- function(m, fcst, uncertainty = TRUE) {
 #'
 #' @param df Forecast dataframe for plotting.
 #' @param uncertainty Boolean to plot uncertainty intervals.
+#' @param plot_cap Boolean indicating if the capacity should be shown in the
+#'  figure, if available.
 #'
 #' @return A ggplot2 plot.
-plot_trend <- function(df, uncertainty = TRUE) {
+plot_trend <- function(df, uncertainty = TRUE, plot_cap = TRUE) {
   df.t <- df[!is.na(df$trend),]
   gg.trend <- ggplot2::ggplot(df.t, ggplot2::aes(x = ds, y = trend)) +
     ggplot2::geom_line(color = "#0072B2", na.rm = TRUE)
-  if (exists('cap', where = df.t)) {
+  if (exists('cap', where = df.t) && plot_cap) {
     gg.trend <- gg.trend + ggplot2::geom_line(ggplot2::aes(y = cap),
                                               linetype = 'dashed',
                                               na.rm = TRUE)
@@ -1046,8 +1053,8 @@ plot_holidays <- function(m, df, uncertainty = TRUE) {
 #' @return A ggplot2 plot.
 plot_weekly <- function(m, uncertainty = TRUE) {
   # Compute weekly seasonality for a Sun-Sat sequence of dates.
-  df.w <- data.frame(ds=seq.Date(zoo::as.Date('2017-01-01'), by='d',
-                                 length.out=7))
+  df.w <- data.frame(
+    ds=seq.Date(zoo::as.Date('2017-01-01'), by='d', length.out=7), cap=1.)
   df.w <- setup_dataframe(m, df.w)$df
   seas <- predict_seasonal_components(m, df.w)
   seas$dow <- factor(weekdays(df.w$ds), levels=weekdays(df.w$ds))
@@ -1075,8 +1082,8 @@ plot_weekly <- function(m, uncertainty = TRUE) {
 #' @return A ggplot2 plot.
 plot_yearly <- function(m, uncertainty = TRUE) {
   # Compute yearly seasonality for a Jan 1 - Dec 31 sequence of dates.
-  df.y <- data.frame(ds=seq.Date(zoo::as.Date('2017-01-01'), by='d',
-                                 length.out=365))
+  df.y <- data.frame(
+    ds=seq.Date(zoo::as.Date('2017-01-01'), by='d', length.out=365), cap=1.)
   df.y <- setup_dataframe(m, df.y)$df
   seas <- predict_seasonal_components(m, df.y)
   seas$ds <- df.y$ds

+ 5 - 2
R/man/plot.prophet.Rd

@@ -4,8 +4,8 @@
 \alias{plot.prophet}
 \title{Plot the prophet forecast.}
 \usage{
-\method{plot}{prophet}(x, fcst, uncertainty = TRUE, xlabel = "ds",
-  ylabel = "y", ...)
+\method{plot}{prophet}(x, fcst, uncertainty = TRUE, plot_cap = TRUE,
+  xlabel = "ds", ylabel = "y", ...)
 }
 \arguments{
 \item{x}{Prophet object.}
@@ -15,6 +15,9 @@
 \item{uncertainty}{Boolean indicating if the uncertainty interval for yhat
 should be plotted. Must be present in fcst as yhat_lower and yhat_upper.}
 
+\item{plot_cap}{Boolean indicating if the capacity should be shown in the
+figure, if available.}
+
 \item{xlabel}{Optional label for x-axis}
 
 \item{ylabel}{Optional label for y-axis}

+ 4 - 1
R/man/plot_trend.Rd

@@ -4,12 +4,15 @@
 \alias{plot_trend}
 \title{Plot the prophet trend.}
 \usage{
-plot_trend(df, uncertainty = TRUE)
+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.

+ 4 - 1
R/man/prophet_plot_components.Rd

@@ -6,7 +6,7 @@
 Prints a ggplot2 with panels for trend, weekly and yearly seasonalities if
 present, and holidays if present.}
 \usage{
-prophet_plot_components(m, fcst, uncertainty = TRUE)
+prophet_plot_components(m, fcst, uncertainty = TRUE, plot_cap = TRUE)
 }
 \arguments{
 \item{m}{Prophet object.}
@@ -15,6 +15,9 @@ prophet_plot_components(m, fcst, uncertainty = TRUE)
 
 \item{uncertainty}{Boolean indicating if the uncertainty interval should be
 plotted for the trend, from fcst columns trend_lower and trend_upper.}
+
+\item{plot_cap}{Boolean indicating if the capacity should be shown in the
+figure, if available.}
 }
 \value{
 Invisibly return a list containing the plotted ggplot objects

+ 33 - 19
python/fbprophet/forecaster.py

@@ -857,13 +857,16 @@ class Prophet(object):
 
         return pd.DataFrame({'ds': dates})
 
-    def plot(self, fcst, uncertainty=True, xlabel='ds', ylabel='y'):
+    def plot(self, fcst, uncertainty=True, plot_cap=True, xlabel='ds',
+             ylabel='y'):
         """Plot the Prophet forecast.
 
         Parameters
         ----------
         fcst: pd.DataFrame output of self.predict.
         uncertainty: Optional boolean to plot uncertainty intervals.
+        plot_cap: Optional boolean indicating if the capacity should be shown
+            in the figure, if available.
         xlabel: Optional label name on X-axis
         ylabel: Optional label name on Y-axis
 
@@ -875,7 +878,7 @@ class Prophet(object):
         ax = fig.add_subplot(111)
         ax.plot(self.history['ds'].values, self.history['y'], 'k.')
         ax.plot(fcst['ds'].values, fcst['yhat'], ls='-', c='#0072B2')
-        if 'cap' in fcst:
+        if 'cap' in fcst and plot_cap:
             ax.plot(fcst['ds'].values, fcst['cap'], ls='--', c='k')
         if uncertainty:
             ax.fill_between(fcst['ds'].values, fcst['yhat_lower'],
@@ -887,7 +890,7 @@ class Prophet(object):
         fig.tight_layout()
         return fig
 
-    def plot_components(self, fcst, uncertainty=True):
+    def plot_components(self, fcst, uncertainty=True, plot_cap=True):
         """Plot the Prophet forecast components.
 
         Will plot whichever are available of: trend, holidays, weekly
@@ -897,31 +900,41 @@ class Prophet(object):
         ----------
         fcst: pd.DataFrame output of self.predict.
         uncertainty: Optional boolean to plot uncertainty intervals.
+        plot_cap: Optional boolean indicating if the capacity should be shown
+            in the figure, if available.
 
         Returns
         -------
         a matplotlib figure.
         """
         # Identify components to be plotted
-        components = [('plot_trend', True),
-                      ('plot_holidays', self.holidays is not None),
-                      ('plot_weekly', 'weekly' in fcst),
-                      ('plot_yearly', 'yearly' in fcst)]
-        components = [(plot, cond) for plot, cond in components if cond]
+        components = [('trend', True),
+                      ('holidays', self.holidays is not None),
+                      ('weekly', 'weekly' in fcst),
+                      ('yearly', 'yearly' in fcst)]
+        components = [plot for plot, cond in components if cond]
         npanel = len(components)
 
         fig, axes = plt.subplots(npanel, 1, facecolor='w',
                                  figsize=(9, 3 * npanel))
 
         artists = []
-        for ax, plot in zip(axes,
-                            [getattr(self, plot) for plot, _ in components]):
-            artists += plot(fcst, ax=ax, uncertainty=uncertainty)
+        for ax, plot in zip(axes, components):
+            if plot == 'trend':
+                artists += self.plot_trend(
+                    fcst, ax=ax, uncertainty=uncertainty, plot_cap=plot_cap)
+            elif plot == 'holidays':
+                artists += self.plot_holidays(fcst, ax=ax,
+                                              uncertainty=uncertainty)
+            elif plot == 'weekly':
+                artists += self.plot_weekly(ax=ax, uncertainty=uncertainty)
+            elif plot == 'yearly':
+                artists += self.plot_yearly(ax=ax, uncertainty=uncertainty)
 
         fig.tight_layout()
         return artists
 
-    def plot_trend(self, fcst, ax=None, uncertainty=True):
+    def plot_trend(self, fcst, ax=None, uncertainty=True, plot_cap=True):
         """Plot the trend component of the forecast.
 
         Parameters
@@ -929,6 +942,8 @@ class Prophet(object):
         fcst: pd.DataFrame output of self.predict.
         ax: Optional matplotlib Axes to plot on.
         uncertainty: Optional boolean to plot uncertainty intervals.
+        plot_cap: Optional boolean indicating if the capacity should be shown
+            in the figure, if available.
 
         Returns
         -------
@@ -941,7 +956,7 @@ class Prophet(object):
             ax = fig.add_subplot(111)
         artists += ax.plot(fcst['ds'].values, fcst['trend'], ls='-',
                            c='#0072B2')
-        if 'cap' in fcst:
+        if 'cap' in fcst and plot_cap:
             artists += ax.plot(fcst['ds'].values, fcst['cap'], ls='--', c='k')
         if uncertainty:
             artists += [ax.fill_between(
@@ -988,12 +1003,11 @@ class Prophet(object):
         ax.set_ylabel('holidays')
         return artists
 
-    def plot_weekly(self, fcst, ax=None, uncertainty=True):
+    def plot_weekly(self, ax=None, uncertainty=True):
         """Plot the weekly component of the forecast.
 
         Parameters
         ----------
-        fcst: pd.DataFrame output of self.predict.
         ax: Optional matplotlib Axes to plot on. One will be created if this
             is not provided.
         uncertainty: Optional boolean to plot uncertainty intervals.
@@ -1008,7 +1022,7 @@ class Prophet(object):
             ax = fig.add_subplot(111)
         # Compute weekly seasonality for a Sun-Sat sequence of dates.
         days = pd.date_range(start='2017-01-01', periods=7)
-        df_w = pd.DataFrame({'ds': days})
+        df_w = pd.DataFrame({'ds': days, 'cap': 1.})
         df_w = self.setup_dataframe(df_w)
         seas = self.predict_seasonal_components(df_w)
         days = days.weekday_name
@@ -1025,12 +1039,11 @@ class Prophet(object):
         ax.set_ylabel('weekly')
         return artists
 
-    def plot_yearly(self, fcst, ax=None, uncertainty=True):
+    def plot_yearly(self, ax=None, uncertainty=True):
         """Plot the yearly component of the forecast.
 
         Parameters
         ----------
-        fcst: pd.DataFrame output of self.predict.
         ax: Optional matplotlib Axes to plot on. One will be created if
             this is not provided.
         uncertainty: Optional boolean to plot uncertainty intervals.
@@ -1044,7 +1057,8 @@ class Prophet(object):
             fig = plt.figure(facecolor='w', figsize=(10, 6))
             ax = fig.add_subplot(111)
         # Compute yearly seasonality for a Jan 1 - Dec 31 sequence of dates.
-        df_y = pd.DataFrame({'ds': pd.date_range(start='2017-01-01', periods=365)})
+        df_y = pd.DataFrame(
+            {'ds': pd.date_range(start='2017-01-01', periods=365), 'cap': 1.})
         df_y = self.setup_dataframe(df_y)
         seas = self.predict_seasonal_components(df_y)
         artists += ax.plot(df_y['ds'], seas['yearly'], ls='-',