3

Let's say there's a time series that I want to plot in matplotlib:

dates = pd.date_range(start='2011-01-01', end='2012-01-01')
s = pd.Series(np.random.rand(1, len(dates))[0], index=dates)

The GUI backends in matplotlib have this nice feature that they show the cursor coordinates in the window. When I plot pandas series using its plot() method like this:

fig = plt.figure()
s.plot()
fig.show()

the cursor's x coords are shown in full yyyy-mm-dd at the bottom of the window as you can see on pic 1.

Series s plotted with s.plot()

However when I plot the same series s with pyplot:

fig = plt.figure()
plt.plot(s.index, s.values)
fig.show()

full dates are only shown when I zoom in and in the default view I can only see Mon-yyyy (see pic 2) and I would see just the year if the series were longer.

Series s plotted with plt.plot()

In my project there are functions for drawing complex, multi-series graphs from time series data using plt.plot(), so when I view the results in GUI I only see the full dates in the close-ups. I'm using ipython3 v. 4.0 and I'm mostly working with the MacOSX backend, but I tried TK, Qt and GTK backends on Linux with no difference in the behavior.

So far I've got 2 ideas on how to get the full dates displayed in GUI at any zoom level:

  1. rewrite plt.plot() to pd.Series.plot()
  2. use canvas event handler to get the x-coord from the cursor pos and print it somewhere

However before I attempt any of the above I need to know for sure if there is a better quicker way to get the full dates printed in the graph window. I guess there is, because pandas is using it, but I couldn't find it in pyplot docs or examples or elsewhere online and it's none of these 2 calls:

ax.xaxis_date()
fig.autofmt_xdate()

Somebody please advise.

mac13k
  • 2,423
  • 23
  • 34

1 Answers1

2

Hooks for formatting the info are Axes.format_coord or Axes.fmt_xdata. Standard formatters are defined in matplotlib.dates (plus some additions from pandas). A basic solution could be:

import matplotlib.dates
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

dates = pd.date_range(start='2011-01-01', end='2012-01-01')
series = pd.Series(np.random.rand(len(dates)), index=dates)

plt.plot(series.index, series.values)
plt.gca().fmt_xdata = matplotlib.dates.DateFormatter('%Y-%m-%d')
plt.show()
wrwrwr
  • 1,008
  • 2
  • 11
  • 19
  • Works nice, thanks. Third and second last can be actually written in a single line if nothing else is to be done with the axes, ie.: `plt.gca().axes.fmt_xdata = lambda x: num2date(x).strftime('%Y-%m-%d')` – mac13k Nov 29 '16 at 12:06
  • Thanks, combined the lines. – wrwrwr Nov 29 '16 at 12:14
  • 1
    On the side note it seems like with multiple subplots this has to be set for each subplot in the figure. If called once just before `plt.show()` it only affects the last subplot. – mac13k Nov 29 '16 at 13:10
  • 1
    Here's even nicer way of achieving the same result: `plt.gca().axes.fmt_xdata = matplotlib.dates.DateFormatter('%Y-%m-%d')` found at [Matplotlib recipes](http://matplotlib.org/users/recipes.html#fixing-common-date-annoyances) – mac13k Nov 29 '16 at 13:19