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 <
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: