Search code examples
pythonmatplotlibplotaxissubplot

Plot a curve on top of 2 subplots simultaneously


EDIT: My question was closed because someone thought another question was responding to it (but it doesn't: Matplotlib different size subplots). To clarify what I want: I would like to replicate something like what is done on this photo: having a 3rd dataset plotted on top of 2 subplots, with its y-axis displayed on the right.

enter image description here

I have 3 datasets spanning the same time interval (speed, position, precipitation). I would like to plot the speed and position in 2 horizontal subplots, and the precipitation spanning the 2 subplots. For example in the code below, instead of having the twinx() only on the first subplot, I would like to have it overlap the two subplots (ie. on the right side have a y-axis with 0 at the bottom right of the 2nd subplot, and 20 at the top right of the 1st subplot). I could I achieve that ?

import matplotlib.pyplot as plt
import numpy as np



fig, ax = plt.subplots(2,1,figsize=(20,15), dpi = 600)
#plot 1:
x = np.array([0, 1, 2, 3])
y = np.array([3, 8, 1, 10])

ax[0].plot(x,y, label = 'speed')
plt.legend()

#plot 2:
x = np.array([0, 1, 2, 3])
y = np.array([3, 8, 1, 10])

ax[1].plot(x,y, label = 'position')
plt.legend()


#plot 3:

x = np.array([0, 1, 2, 3])
y = np.array([10, 0, 4, 20])
ax2=ax[0].twinx()
ax2.plot(x,y, label = 'precipitation')

plt.legend(loc='upper right')
plt.show()

Solution

  • Best way I found is not very elegant but it works:

    # Prepare 2 subplots
    fig, ax = plt.subplots(2,1,figsize=(20,15), dpi = 600)
    #plot 1:
    
    # Dummy values for plotting
    x = np.array([0, 1, 2, 3])
    y = np.array([3, 8, 1, 10])
    
    ax[0].plot(x,y, label = 'speed')
    
    # Prints the legend
    plt.legend()
    
    #plot 2:
    x = np.array([0, 1, 2, 3])
    y = np.array([3, 8, 1, 10])
    
    ax[1].plot(x,y, label = 'position')
    plt.legend()
    
    
    #plot 3:
    
    x = np.array([0, 1, 2, 3])
    y = np.array([10, 0, 4, 20])
    
    # Add manually a 3rd subplot that stands on top of the 2 others
    ax2 = fig.add_subplot(111, label="new subplot", facecolor="none")
    
    # Move the y-axis to the right otherwise it will overlap with the ones on the left 
    ax2.yaxis.set_label_position("right")
    
    # "Erase" every tick and label of this 3rd plot
    ax2.tick_params(left=False, right=True, labelleft=False, labelright=True,
                    bottom=False, labelbottom=False)
    
    # This line merges the x axes of the 1st and 3rd plot, and indicates
    # that the y-axis of the 3rd plot will be drawn on the entirety of the 
    # figure instead of just 1 subplot (because fig.add_subplot(111) makes it spread on the entirety of the figure) 
    ax[0].get_shared_x_axes().join(ax[0],ax2)
    ax2.plot(x,y, label = 'precipitation')
    
    # Prints the legend in the upper right corner
    plt.legend(loc='upper right')
    plt.show()