Одна из возможностей состоит в том, чтобы использовать основные отметки для обозначения меток месяца и второстепенные отметки для разделения. Всякий раз, когда меняется метка контрольной точки, необходимо нарисовать более длинный тик. Положение метки контрольной точки будет находиться между двумя длинными галочками.
Кажется, есть один месяц с двумя разными метками (месяц 34). Не ясно, что должно произойти потом. В приведенном ниже коде нарисована длинная крупная галочка.
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
data1 = {'Month': list(range(11, 35)) + list(range(34, 42)),
'Checkpoint': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
'C', 'C', 'C', 'C', 'D', 'C', 'D', 'D', 'D', 'D', 'D', 'D', 'D'],
'Litres': [216545.67, 18034.45, 25807.83, 46136.23, 68099.21, 55436.35, 56412.33, 9347.52, 3177.29, 103.89,
333.29, 2355.41, 49063.72, 113622.80, 243639.97, 303992.32, 255471.55, 267022.75, 274952.92,
619665.39, 798969.54, 1127476.60, 1563344.98, 1051827.75, 603167.32, 1880605.49, 1931002.19,
2970500.68, 2362336.66, 5311058.83, 5071784.10, 5325575.47]}
df = pd.DataFrame(data1)
fig, ax = plt.subplots(figsize=(10, 5))
ax.scatter(df['Month'], df['Litres'], s=30, color='crimson')
ax.xaxis.set_major_locator(ticker.FixedLocator(0.5))
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.5))
ax.set_xlim(df['Month'].iloc[0] - 0.5, df['Month'].iloc[-1] + 0.5)
checkpoints = list(df['Checkpoint'])
long_minor_ticks = [df['Month'].iloc[0] - 1] # these minor ticks need to be longer
long_major_ticks = [] # these major ticks need to be longer
for m1, m, c1, c in zip(df['Month'][1:], df['Month'], df['Checkpoint'][1:], df['Checkpoint']):
if m == m1:
long_major_ticks.append(m)
elif c != c1:
long_minor_ticks.append(m)
long_minor_ticks.append(df['Month'].iloc[-1])
ax.tick_params(which='minor', axis='x', pad=20) # put the minor tick labels at some distance
checkpoint_labels = []
for tick, month in zip(ax.xaxis.get_minor_ticks(), range(df['Month'].iloc[0]-1, 100)):
l = 35 if month in long_minor_ticks and not month in long_major_ticks and not month+1 in long_major_ticks else 18
tick.tick1line.set_markersize(l)
checkpoint_labels.append('')
for tick, month in zip(ax.xaxis.get_major_ticks(), range(df['Month'].iloc[0]-1, 100)):
l = 35 if month in long_major_ticks else 0
tick.tick1line.set_markersize(l)
# set the checkpoint letters at the positions between the long minor ticks
for t0, t1 in zip(long_minor_ticks[:-1],long_minor_ticks[1:]):
if t1 != t0 + 1:
ind = (t1+t0) // 2 - long_minor_ticks[0]
checkpoint_labels[ind] = df['Checkpoint'].iloc[ind]
ax.set_xticklabels(checkpoint_labels, minor=True)
fig.subplots_adjust(bottom=0.15) # we need space to show the large ticks
plt.show()