facebook / prophet

Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth.
https://facebook.github.io/prophet
MIT License
18.32k stars 4.52k forks source link

Plot multiple trends/components on one plot? #993

Closed chrisjvargo closed 5 years ago

chrisjvargo commented 5 years ago

Hi @bletham and Facebook Core DS!

First, thank you for this wonderful tool. I taught my students how to do time series analysis through Prophet's lens and they really found value in the method.

I'm using it for some academic work right now, and I have several models, all for different 'y' variables. They're related however, and instead of dedicating a figure, in an article, to every 'y' trend and/or component, I was wondering if it was possible to plot multiple on the same figure.

For instance, imagine combining these two figures together, with some type of color key/legend to differentiate: image image

Is there an easy way to do this, or a way to easily export the data going into the plots to a dataframe to do some manual plotting?

Again, I am truly thankful to you all for this wonderful tool.

Chris

bletham commented 5 years ago

Hey @chrisjvargo!

I think what you're trying to do can be can be done without a terrible amount of effort. The plot_components method creates a matplotlib figure, and then fills in the panels by calling out to other functions that actually do the plotting for each component. You can just call those functions directly to have more control over their placing. The two you'd want for your example here are:

plot_forecast_component(m, fcst, name='trend') for the trend: https://github.com/facebook/prophet/blob/b77f85ffd8e811c401afb1e638d93c0c244c4ab7/python/fbprophet/plot.py#L187

and

plot_yearly(m) for yearly seasonality: https://github.com/facebook/prophet/blob/b77f85ffd8e811c401afb1e638d93c0c244c4ab7/python/fbprophet/plot.py#L303

Each of these will by default generate a new figure and make the plot on that figure, but you can also give it an existing matplotlib axis object and it will put the plot there. Here is an example to get a 2x2 plot with components from two models:

from matplotlib import pyplot as plt
from fbprophet.plot import plot_forecast_component, plot_yearly

fig = plt.figure(figsize=(12, 8))

ax1 = fig.add_subplot(2, 2, 1)
plot_forecast_component(m=m1, fcst=fcst1, name='trend', ax=ax1)
ax1.set_title('Model 1, trend')

ax2 = fig.add_subplot(2, 2, 2)
plot_yearly(m=m1, ax=ax2)
ax2.set_title('Model 1, yearly seasonality')

ax3 = fig.add_subplot(2, 2, 3)
plot_forecast_component(m=m2, fcst=fcst2, name='trend', ax=ax3)
ax3.set_title('Model 2, trend')

ax4 = fig.add_subplot(2, 2, 4)
plot_yearly(m=m2, ax=ax4)
ax4.set_title('Model 2, yearly seasonality')

fig.subplots_adjust(wspace=0.3, hspace=0.3)

If you want to also change colors / add legends, you can do that by just working with the matplotlib ax objects. For instance colors can be changed with

ax1.get_lines()[0].set_color("black")

Making more complex modifications to matplotlib plots can be a real pain, so if you want to really customize things for the purposes of a publication you might want to just copy out the plotting code and make direct modifications. It's actually a rather small amount of code: plot_yearly and plot_forecast_component are 24 lines each (code links above). You could then directly modify colors / labels when generating them.

chrisjvargo commented 5 years ago

This is incredible and a completely robust solution. Thanks @bletham!

Roopana commented 4 years ago

Hi, Is there a way to achieve the same (plotting multiple time series in the same graph) in spark?