matplotlib: share x axis from one subplot with y axis from another

Viewed 391

I want to project 3D data onto XY, XZ, YZ subplots with interactive shared axes.

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(3, 1, constrained_layout=True)

n = 10000
pts = {
   'X': np.random.normal(0, 1, n),
   'Y': np.random.normal(0, 2, n),
   'Z': np.random.normal(0, 4, n)
}

for ax, (k1, k2) in zip(axes, [('X', 'Y'), ('X', 'Z'), ('Y', 'Z')]):
   ax.plot(pts[k1], pts[k2], ',')
   ax.set_xlabel(k1)
   ax.set_ylabel(k2)

axes[0].sharex(axes[1])
axes[1].sharey(axes[2])

plt.show()

enter image description here

The XY and XZ plots share the X axis limits, and the YZ and XZ plots share the Z axis limits, but how can I make it such that the XY and YZ share the Y axis limits? Maybe some syntax like axes[2].sharexy(axes[0]) exists in some fashion?

1 Answers

A quick (and possibly very stupid) fix I found is to sort of do the axis sharing manually. In other words, if both x and y axes you want to share have the same size in figure (i.e. both of them span e.g. 10 cm), you can manually set them to have equal limits, ticks and tick labels. In your case it would be something like:

axes[0].set_ylim(axes[2].get_xlim()) #set the y lim of first subplot the same 
                                     #as x lim of last subplot      
axes[0].set_yticks(axes[2].get_xticks()) #set y ticks of first subplot the same as
                                         #x ticks of last subplot
#You can also do further stuff like turning off y ticks labels of axes[0] 
#with something like plt.setp(axes[0].get_yticklabels(), visible=False).

In my case, doing this after all the figure adjustments (subplots_adjust() etc.) yielded in a result very similar to sharing both of these axes, also with correct tick labels. Adjusting the y tick labels of axes[0] after "sharing" manually seems to be trickier, since axes[2].get_xticklabels() returns an array of Text objects, which have also x and y positions. Another (dirty) workaround for this to manually adjust y tick labels for axes[0] is:

#list comprehension to get strings of each x ticks of last subplot
ax2xticklabels = [i.get_text() for i in axes[2].get_xticklabels()] 
axes[0].set_yticklabels(ax2xticklabels) #set y tick labels of first subplot
                                        #the same as x tick labels of last subplot

I actually came here also to search for a much more elegant way to solve this problem, but noticing there seems to be nothing to independently share 2 axes objects in the internet, I wanted to share my dirty quick fix :D. Hope this might help!

Related