pythonmatplotlibsquare

How to use twinx and still get square plot


How do I show a plot with twin axes such that the aspect of the top and right axes are 'equal'. For example, the following code will produce a square plot

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.plot([0,1],[0,1])

But this changes as soon as you use the twinx function.

ax2 = ax.twinx()
ax2.set_ylim([0,2])
ax3 = ax.twiny()
ax3.set_xlim([0,2])

Using set_aspect('equal') on ax2 and ax3 seems to force it the the aspect of ax, but set_aspect(0.5) doesn't seem to change anything either.

Put simply, I would like the plot to be square, the bottom and left axes to run from 0 to 1 and the top and right axes to run from 0 to 2.

Can you set the aspect between two twined axes? I've tried stacking the axes:

ax3 = ax2.twiny()
ax3.set_aspect('equal')

I've also tried using the adjustable keyword in set_aspect:

ax.set_aspect('equal', adjustable:'box-forced')

The closest I can get is:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_aspect('equal', adjustable='box-forced')
ax.plot([0,1],[0,1])
ax2=ax.twinx()
ax3 = ax2.twiny()
ax3.set_aspect(1, adjustable='box-forced')
ax2.set_ylim([0,2])
ax3.set_xlim([0,2])
ax.set_xlim([0,1])
ax.set_ylim([0,1])

Which produces:

enter image description here

I would like to remove the extra space to the right and left of the plot


Solution

  • It seems overly complicated to use two different twin axes to get two independent set of axes. If the aim is to create one square plot with one axis on each side of the plot, you may use two axes, both at the same position but with different scales. Both can then be set to have equal aspect ratios.

    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    ax.set_aspect('equal')
    ax.plot([0,1],[0,1])
    
    ax2 = fig.add_axes(ax.get_position())
    ax2.set_facecolor("None")
    ax2.set_aspect('equal')
    ax2.plot([2,0],[0,2], color="red")
    ax2.tick_params(bottom=0, top=1, left=0, right=1, 
                    labelbottom=0, labeltop=1, labelleft=0, labelright=1)
    
    plt.show()
    

    enter image description here