j_becker
j_becker

Reputation: 31

Pandas auto datetime format in matplotlib

I frequently plot multiple timeseries data from different sources on a single plot, some of which require using matplotlib. When formatting the x-axis, I use matplotlib's autofmt_xdate(), but I much prefer the auto formatting of pandas. I'm aware I can manually set the format using set_major_formatter(), but the plots I create vary from years, to days in total range, so I would need to adjust the formatting based on each plot. Is there a way to set matplotlib to auto format the x-axis with dates similar to pandas?

I also use interactive plotting, and when using pandas df.plot() the x-axis updates when zooming to the respective ranges as shown below, which I would also like to achieve using matplotlib:

pandas format month pandas format day pandas format inter-day

Versions:

Python: 3.7.1
Pandas: 0.23.3
Matplotlib: 2.2.2

Desired Format:

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

ix = pd.date_range('1/1/2017', '11/1/2018', freq='D')
vals = np.random.randn(len(ix))
df = pd.DataFrame({'Values': vals}, index=ix)

fig, ax = plt.subplots(1, 1, figsize=[8,6])
df.plot(ax=ax, lw=1)
plt.show()

desired pandas format

Current Format:

fig, ax = plt.subplots(1, 1, figsize=[8,6])
ax.plot(df, lw=1)
fig.autofmt_xdate()
plt.show()

Current matplotlib format

Upvotes: 3

Views: 3463

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339775

An option to show the years in a second row is to use the major and minor ticklabels.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import MonthLocator, YearLocator, DateFormatter

ix = pd.date_range('1/1/2017', '11/1/2018', freq='D')
vals = np.random.randn(len(ix))
s = pd.DataFrame({'Values': vals}, index=ix)

fig, ax = plt.subplots(figsize=[8,6])
ax.plot(s, lw=1)

ax.xaxis.set_major_locator(YearLocator())
ax.xaxis.set_major_formatter(DateFormatter("\n%Y"))

ax.xaxis.set_minor_locator(MonthLocator((1,4,7,10)))
ax.xaxis.set_minor_formatter(DateFormatter("%b"))

plt.show()

If you need the minor ticks for something else, the following would format the major ticks alone - with the same result. Here you would use a FuncFormatter to determine the format depending on the month.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import MonthLocator, DateFormatter
from matplotlib.ticker import FuncFormatter

ix = pd.date_range('1/1/2017', '11/1/2018', freq='D')
vals = np.random.randn(len(ix))
s = pd.DataFrame({'Values': vals}, index=ix)

fig, ax = plt.subplots(figsize=[8,6])
ax.plot(s, lw=1)

monthfmt = DateFormatter("%b")
yearfmt = DateFormatter("%Y")

def combinedfmt(x,pos):
    string = monthfmt(x)
    if string == "Jan":
        string += "\n" + yearfmt(x)
    return string

ax.xaxis.set_major_locator(MonthLocator((1,4,7,10)))
ax.xaxis.set_major_formatter(FuncFormatter(combinedfmt))

plt.show()

The result is in both cases the same:

enter image description here

Upvotes: 5

Related Questions