pythonmatplotlibplot

matplotlib multiple axes mixups


I have a problem with a multi axis matplotlib plot. The code is close to what I want but somehow axes are getting mixed up. The ticks are missing on ax4 aka the green y-axis but only show up on ax2 (the red one) and the labels are duplicated and appear on both axes, ax2 and ax4.

import numpy as np
import matplotlib.pyplot as plt

# Generate fake data
distance = np.logspace(2, 4, num=50)
a_detector = 10**4 / distance**1.5
b_detector = 10**5 / distance**1.6
c_detector = 10**3 / distance**1.4
d_detector = 10**2 / distance**1.2

# Create figure and axes
fig, ax1 = plt.subplots(figsize=(20, 10))

ax1.plot(distance, a_detector, 'bo-', label='A')
ax1.set_xlabel('Shower Plane Distance [meter]')
ax1.set_ylabel('signal type I', color='blue')
ax1.set_xscale('log')
ax1.set_yscale('log')
ax1.tick_params(axis='y', labelcolor='blue')

ax2 = ax1.twinx()
ax2.plot(distance, b_detector, 'ro-', label='B')
ax2.set_ylabel('signal type II', color='red')
ax2.set_yscale('log')
ax2.tick_params(axis='y', labelcolor='red')

ax3 = ax1.twinx()
ax3.spines['right'].set_position(('outward', 90))
ax3.plot(distance, c_detector, 'ks-', label='C')
ax3.set_ylabel('signal type III', color='black')
ax3.set_yscale('log')
ax3.tick_params(axis='y', labelcolor='black')

ax4 = ax1.twinx()
ax4.spines['left'].set_position(('outward', 90))
ax4.plot(distance, d_detector, 'g^-', label='D')
ax4.set_ylabel('signal type IV', color='green')
ax4.set_yscale('log')
ax4.tick_params(axis='y', labelcolor='green')
ax4.yaxis.set_label_position('left')
ax4.yaxis.set_tick_params(labelleft=True)

fig.legend(loc='upper right', bbox_to_anchor=(0.89, 0.86))
plt.show()

Solution

  • You just need to replace:

    ax4.yaxis.set_tick_params(labelleft=True)
    

    by:

    ax4.yaxis.set_tick_params(which='major', left=True, right=False, labelleft=True, labelright=False)  
    ax4.yaxis.set_tick_params(which='minor', left=True, right=False, labelleft=True, labelright=False)
    

    You put the yaxis major tick labels to the left but you also need to remove them from their original location with labelright=False. This has to be done also for the tick labels (previously it was the tick marks) and also for the minor ticks (default is major ticks).

    plot