Reputation: 31
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:
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()
Current Format:
fig, ax = plt.subplots(1, 1, figsize=[8,6])
ax.plot(df, lw=1)
fig.autofmt_xdate()
plt.show()
Upvotes: 3
Views: 3463
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:
Upvotes: 5