Some years ago, I have posted the question Synchronising dual x axes in a dual (sub)plot in interactive Matplotlib? , which ended up having a working solution, which was behaved like this:
Thankfully, the library authors changed the API, so I can spend even more hours debugging the same old issues, and rewriting the same old tired code – providing me with a job for life :)
First, for the line:
ax.get_shared_x_axes().join(ax, ax2, ax22)
… I got the error:
AttributeError: ‘GrouperView’ object has no attribute ‘join’. Did you mean: ‘joined’?
… however, I managed to find AttributeError: ‘GrouperView’ object has no attribute ‘join’ where the accepted error suggests:
ax1.sharey(ax2) ax2.sharey(ax3)
… but when I try the equivalent with .sharex()
in my code, where Matplotlib reports version 3.8.3, I get:
ValueError: x-axis is already shared
Is there a fix to get this working again? Here is my modified code:
#!/usr/bin/env python3
import matplotlib
print("matplotlib.__version__ {}".format(matplotlib.__version__))
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import packaging
#
# Some toy data
x_seq = [x / 100.0 for x in range(1, 100)]
y_seq = [x**2 for x in x_seq]
y2_seq = [0.3*x**2 for x in x_seq]
#
# Scatter plot
fig, (ax, ax2) = plt.subplots(2, 1, sharex=True, figsize=(9, 6), dpi=100, gridspec_kw={'height_ratios': [2, 1]}) # two rows, one column
# Remove horizontal space between axes
fig.subplots_adjust(hspace=0)
ax22 = ax2.twiny() # instantiate a second axes that shares the same y-axis ; /q/31803817
#ax.get_shared_x_axes().join(ax, ax22) # for two axes, from /q/42718823
if packaging.version.Version(matplotlib.__version__) < packaging.version.Version("3.7"):
ax.get_shared_x_axes().join(ax, ax2, ax22) # in matplotlib 3.8: AttributeError: 'GrouperView' object has no attribute 'join'. Did you mean: 'joined'?
else:
# from /q/77418896 :
ax.sharex(ax2)
ax2.sharex(ax22) # ValueError: x-axis is already shared
# Move twinned axis ticks and label from top to bottom
ax22.xaxis.set_ticks_position("bottom")
ax22.xaxis.set_label_position("bottom")
# Offset the twin axis below the host
ax22.spines["bottom"].set_position(("axes", -0.1))
ax.plot(x_seq, y_seq)
ax2.plot(x_seq, y2_seq)
factor = 655
# FuncFormatter can be used as a decorator
@ticker.FuncFormatter
def major_formatter(x, pos):
#return "[%.2f]" % x
return int(factor*x)
ax22.xaxis.set_major_formatter(major_formatter)
#
# Show
plt.show()
Well, sometimes it seems one must post a question, to get to the answer – it seems, all one needs to do is to inverts the “order of sharing” in the second statement:
...
else:
# from /q/77418896 :
ax.sharex(ax2)
ax22.sharex(ax2) # works!
...
… and things seem to work as before; nice!