Plotting Pandas Time Series Data in Prophet
The Error
When plotting Pandas data in the context of Facebook's Prophet library, the following error occurs: TypeError: float() argument must be a string or a number, not Period.
The Solution
The Pandas ↔ Matplotlib converters must be manually registered with plotting.register_matplotlib_converters()
. Credit to Darek Tidwell and Ben Letham for publishing this solution.
The Explanation
The issue is created by Prophet's deregistration of Pandas' automatic Matplotlib converters. The error occurs when using fbprophet 0.4
and above with pandas ~0.24
. To demonstrate, start by loading the libraries:
import fbprophet as prophet import pandas as pd print("Prophet version: " + prophet.__version__ + "\nPandas version: " + pd.__version__)
Then prepare the dataset by loading it into a standard Pandas dataframe.
df = pd.read_csv(retail_sales.csv, index_col='ds', parse_dates=True) df = df.reset_index() df.head()
ds | y | |
---|---|---|
0 | 2009-10-01 | 338630 |
1 | 2009-11-01 | 339386 |
2 | 2009-12-01 | 400264 |
3 | 2010-01-01 | 314640 |
4 | 2010-02-01 | 311022 |
Now try to plot the dataframe to generate the error. Note that Prophet is never directly invoked outside of the initial call to import fbprophet as prophet
. In other words, the plot would work if fbprophet
was never loaded.
try: df.set_index('ds').y.plot().get_figure() except TypeError as e: figure_or_exception = str("TypeError: " + str(e)) else: figure_or_exception = df.set_index('ds').y.plot().get_figure() figure_or_exception
What's happening? Even though pandas.DataFrame.plot
uses Matplotlib as a backend default, Pandas uses its own internal types. The library registers several functions to help Matplotlib plot these types. This includes types datetime plotting - a type critical to Prophet.
The Pandas → Matplotlib converters work transparently without Prophet. However, as Ben Letham from the Core Data Science group at Facebook explains, the Prophet team decided not to use Pandas types for plotting and automatically converts the data before passing it to Matplotlib.
A conflict arises when calling Pandas' plot
on a Prophet model; this warning is generated: Using an
implicitly
registered datetime converter for a matplotlib plotting method
(emphasis mine). In the future, Pandas will require users to explicitly register the converters that enable the plotting of Pandas types in Matplotlib. To comply with future versions of Pandas, Prophet deregisters the Pandas converters via pandas.plotting
→ deregister_matplotlib_converters()
.
Deregistering Matplotlib converters in Pandas makes it impossible to plot Pandas data using the default Matplotlib backend.
If the user wishes to plot Matplotlib data, they must explicitly register the converters using pd.plotting.register_matplotlib_converters()
. Like so:
pd.plotting.register_matplotlib_converters() try: df.set_index('ds').y.plot().get_figure() except TypeError as e: figure_or_exception = str("TypeError: " + str(e)) else: figure_or_exception = df.set_index('ds').y.plot().get_figure() figure_or_exception