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.

retail_sales.csv
df = pd.read_csv(
retail_sales.csv
, index_col='ds', parse_dates=True) df = df.reset_index() df.head()
dsy
02009-10-01338630
12009-11-01339386
22009-12-01400264
32010-01-01314640
42010-02-01311022
5 items

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
"TypeError: float() argument must be a string or a number, not 'Period'"

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