Search code examples
pythonmatplotlibgridaxis

Grid based on 1. y-axis with 2. x-axis is shown in matplotlib


For my students I need a blanked plot with 2 x-axis and 2 y-axis. For a better workflow there is a grid based on 1st x-axis and 1st y-axis so they can easily copy the data from the machine by hand. On the 2nd x- and y-axis they can check there calculations.

Here you can see the plot that I want (manipulate in paint.exe :p)

what I want

You can see, that the grid is perfectly orientated on the blue (1st) axis AND there is a line on the red (2nd) x-axis.

In the following code there is no line in the 2nd a-axis, because auf frame_on=False in line 25.

import matplotlib.pyplot as plt
import numpy as np

# put in some data outside the plot
x_values1=[-10,-10]
y_values1=[-10,-10]

x_values2=[-10,-10]
y_values2=[-10,-10]

fig=plt.figure()

# define 1st x- and y-axis
ax=fig.add_subplot(111, label="1")
ax.set_xlim(xmin=0, xmax=12)
ax.set_ylim(ymin=0, ymax=120)

# grid on after 1st x- and y-axis
ax.grid(which='major', color='#DDDDDD', linewidth=0.5)
ax.grid(which='minor', color='#EEEEEE', linestyle=':', linewidth=0.5)
ax.minorticks_on()
plt.grid(True, linestyle='--', color='gray', alpha=0.2, which='both')

# define 2nd x- and y-axis
ax2=fig.add_subplot(111, label="2", frame_on=False) # frame_on=True
ax2.set_xlim(xmin=0, xmax=24)
ax2.set_ylim(ymin=0, ymax=120000/78)

# label of 1st axis
ax.plot(x_values1, y_values1)
ax.set_xlabel("1st x-axis", color='blue')
ax.set_ylabel("1st y-axis", color='blue')

ax.tick_params(axis='x')
ax.tick_params(axis='y')

# label of 2nd axis and repositioning
ax2.scatter(x_values2, y_values2, color="red")
ax2.xaxis.tick_bottom()
ax2.yaxis.tick_right()
ax2.set_xlabel('2nd x-axis', color='red') 
ax2.set_ylabel('2nd y-axis' , color='black')       
ax2.xaxis.set_label_position('bottom')

# repositioning 2nd x-axis
ax2.spines['bottom'].set_position(('outward', 35))
ax2.yaxis.set_label_position('right') 
ax2.tick_params(axis='x')
ax2.tick_params(axis='y')
ax2.set_xticks(np.arange(0, 25, 2))

plt.subplots_adjust(bottom=0.2, right = 0.88)
plt.show()

what it looks like

If I turn frame_on=True in line 25, there is no grid.

no grid

And if I switch the postion of plt.grid(True, linestyle='--', color='gray', alpha=0.2, which='both') to the end of the script, the grid is based on the 2nd axis, after frame_on=True.

import matplotlib.pyplot as plt
import numpy as np

# put in some data outside the plot
x_values1=[-10,-10]
y_values1=[-10,-10]

x_values2=[-10,-10]
y_values2=[-10,-10]

fig=plt.figure()

# define 1st x- and y-axis
ax=fig.add_subplot(111, label="1")
ax.set_xlim(xmin=0, xmax=12)
ax.set_ylim(ymin=0, ymax=120)

# grid on after 1st x- and y-axis
ax.grid(which='major', color='#DDDDDD', linewidth=0.5)
ax.grid(which='minor', color='#EEEEEE', linestyle=':', linewidth=0.5)
ax.minorticks_on()
# plt.grid(True, linestyle='--', color='gray', alpha=0.2, which='both') # put it to the end

# define 2nd x- and y-axis
ax2=fig.add_subplot(111, label="2", frame_on=True) # frame_on=True
ax2.set_xlim(xmin=0, xmax=24)
ax2.set_ylim(ymin=0, ymax=120000/78)

# label of 1st axis
ax.plot(x_values1, y_values1)
ax.set_xlabel("1st x-axis", color='blue')
ax.set_ylabel("1st y-axis", color='blue')

ax.tick_params(axis='x')
ax.tick_params(axis='y')

# label of 2nd axis and repositioning
ax2.scatter(x_values2, y_values2, color="red")
ax2.xaxis.tick_bottom()
ax2.yaxis.tick_right()
ax2.set_xlabel('2nd x-axis', color='red') 
ax2.set_ylabel('2nd y-axis' , color='black')       
ax2.xaxis.set_label_position('bottom')

# repositioning 2nd x-axis
ax2.spines['bottom'].set_position(('outward', 35))
ax2.yaxis.set_label_position('right') 
ax2.tick_params(axis='x')
ax2.tick_params(axis='y')
ax2.set_xticks(np.arange(0, 25, 2))

plt.subplots_adjust(bottom=0.2, right = 0.88)

plt.grid(True, linestyle='--', color='gray', alpha=0.2, which='both')

plt.show()

what it looks like after reposit grid

Is there a way that I get a plot like the 1st picture without using paint?


Solution

  • Create ax2 first and then ax over top of it.

    enter image description here

    Source: comment on the question by Jody Klymak