Date axis¶
example¶
import numpy
import pandas
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
n = 25
numpy.random.seed(n)
ds = pandas.date_range('2020-01-01', periods=n, freq='m')
df = pandas.DataFrame({
't': ds,
'v': numpy.random.randn(n),
})
fig, ax = plt.subplots(figsize=(10, 6))
df.plot(ax=ax, x='t', y=['v'])
rotate¶
turn on grid¶
b\nY¶
#ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b\n%Y'))
time\ndate¶
ax.plot(df.t, df.v)
dy_fmt=mdates.DateFormatter('%H:%M\n%Y-%m-%d')
hr_fmt=mdates.DateFormatter('%H:%M')
ax.xaxis.set_major_formatter(dy_fmt)
ax.xaxis.set_major_locator(mdates.DayLocator())
ax.xaxis.set_minor_formatter(hr_fmt)
ax.xaxis.set_minor_locator(mdates.HourLocator(byhour=range(2,24,2)))
date minor tick labels too crowded¶
When using auto date locator, sometimes the minor tick labels are too crowded. In this case we need to check the number of visible non-empty minor tick labels and replace with custom locator.
We also adjust the major tick label heights as sometimes it's not aligned with the minor tick labels.
There are some custom postprocessing of the major tick labels as well to remove first empty line.
colours = [my_colours[col] for col in df.columns]
kwargs.setdefault('color', colours)
kwargs.setdefault('alpha', 0.6)
kwargs['stacked'] = False
kwargs['subplots'] = True
kwargs['sharey'] = True
kwargs['legend'] = False
# df index is datetime
axes = df.fillna(0).plot.area(
figsize=figsize,
layout=layout,
**kwargs
)
ymin, ymax = plt.ylim()
use_custom_locator = None
minor_locator = mdates.DayLocator(bymonthday=range(1, 32, 2))
for col, ax in zip(df.columns, axes.ravel()):
ax.set_title(col)
ax.set_ylim(ymin*1.1, ymax*1.1)
# switch to custom locator based on number of visible labels
if use_custom_locator is None:
n_ticks = sum(
1 for lbl in ax.get_xminorticklabels()
if lbl.get_visible() and lbl.get_text().strip()
)
use_custom_locator = n_ticks > 9
if use_custom_locator:
ax.xaxis.set_minor_locator(minor_locator)
# adjust height of major tick labels
for label in ax.get_xticklabels(which='major'):
label.set_y(0.005)
# remove first empty line in major tick labels
labels = [
lbl.get_text().replace('\n\n', '\n')
for lbl in ax.get_xticklabels(which='major')
]
ax.set_xticks(
ticks=ax.get_xticks(minor=False),
labels=labels,
minor=False,
)
axes[0, 0].set_ylabel('Shared Y Axis')
fig = axes[0, 0].figure
fig.suptitle('My Custom Chart', fontsize=14)
fig.show()
plt.close(fig) # close the figure to free memory