Search code examples
pythonmatplotlibplotfigure

How can I offset the x-axis ticks so every other is slightly lower/higher?


The minor x-axis labels on my plot are very dense. Instead of making them smaller, I want to move every other one slightly down so they fit within the axis. Something like this. I tried label padding but no success.

enter image description here

Code:

fig, ax1 = plt.subplots(figsize=(18, 6))

ax1.plot(data['date_time'], data.Casual, color='g')
ax1.plot(data['date_time'], data.Registered, color='b')

ax1.set(xlabel='', ylabel='Total # of trips started')
ax1.yaxis.label.set_size(13)
ax1.xaxis.set(
    major_locator=mdates.DayLocator(),
    major_formatter=mdates.DateFormatter('\n\n%A'),
    minor_locator=mdates.HourLocator(byhour=range(0,24,1)),
    minor_formatter=mdates.DateFormatter('%-H'),
)
ax1.tick_params(axis='x', which='minor', bottom=True)
ax1.set_xbound(data['date_time'][0],data['date_time'][166])
ax1.yaxis.set_ticks(np.arange(0, 550, 50))
ax1.set_ybound(0,550)
ax1.yaxis.grid(True, which='major')
ax1.xaxis.grid(True, which='major', color='green')

#borders
ax1.spines['left'].set_color('0.0')
ax1.spines['right'].set_color('0.0')
ax1.spines['bottom'].set_color('0.0')

# Create offset transform by 74 points in x direction
dx = 74/72.; dy = 0/72. 
offset = mpl.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)

# apply offset transform to all x ticklabels.
for label in ax1.xaxis.get_majorticklabels():
    label.set_transform(label.get_transform() + offset)

### Trying to move them up and down here ###
labels_formatted = [label if i%2==0 else label+'\n' for i, label in enumerate(ax1.xaxis.get_majorticklabels())]
ax1.set_xticklabels(labels_formatted)


plt.show()

Solution

  • You are doing one fundamental mistake I think. You should append the new line character before the string because only then you will see the label text one line below. Otherwise, you are just sending the cursor to the next line without printing anything.

    Moreover, you need label.get_text() to get the string of the tick-labels. I am showing a sample answer below. Adapt the same logic to your example. I cannot do that because you haven't provided a MCVE

    import matplotlib.pyplot as plt
    import numpy as np
    
    fig, ax = plt.subplots()
    
    x = np.linspace(0, 10, 20)
    
    plt.plot(x, x**2)
    fig.canvas.draw()
    labels_formatted = [label.get_text() if i%2==0 else '\n'+label.get_text() for i, label in enumerate(ax.xaxis.get_majorticklabels())]
    ax.set_xticklabels(labels_formatted)
    plt.show()
    

    enter image description here