I'm coming from this question Matplotlib: two x axis and two y axis where I learned how to plot two x
and y
axis on the same plot.
Here's a MWE
:
import matplotlib.pyplot as plt
import numpy as np
# Generate random data.
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)
# Plot both curves.
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_xlabel('x_1')
ax1.set_ylabel('y_1')
plt.plot(x1, y1, c='r')
ax2 = ax1.twinx().twiny()
ax2.set_xlabel('x_2')
ax2.set_ylabel('y_2')
plt.ylim(min(y2), max(y2))
ax2.plot(x2, y2, c='b')
plt.show()
and this is the output:
The right y
axis and the top x
axis correspond to the blue curve.
As you can see, the second y
label is missing even though it is defined. I've tried a number of different approaches but I can't get it to show. Am I doing something wrong?
Add:
apparently there's an issue with the line:
ax2 = ax1.twinx().twiny()
if I invert it like so:
ax2 = ax1.twiny().twinx()
then it's the second x
label that will not show.
Basically, what's happening is that there's a third axes object created that you're not currently retaining a reference to. ax2
's visible y-axis actually belongs to this third axes object.
You have a couple of options.
twinx
and twiny
and instead create an axes in the same position as the first.The second option is a touch more verbose, but has the advantage that the y-axis limits on the second plot will autoscale as you'd expect. You won't need to manually set them as you're currently doing.
At any rate, here's an example of the first option:
import matplotlib.pyplot as plt
import numpy as np
# Generate random data.
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)
# Plot both curves.
fig, ax1 = plt.subplots()
ax1.set(xlabel='x_1', ylabel='y_1')
ax1.plot(x1, y1, c='r')
tempax = ax1.twinx()
ax2 = tempax.twiny()
ax2.plot(x2, y2, c='b')
ax2.set(xlabel='x_2', ylim=[min(y2), max(y2)])
tempax.set_ylabel('y_2', rotation=-90)
plt.show()
...And here's an example of the second option:
import matplotlib.pyplot as plt
import numpy as np
def twinboth(ax):
# Alternately, we could do `newax = ax._make_twin_axes(frameon=False)`
newax = ax.figure.add_subplot(ax.get_subplotspec(), frameon=False)
newax.xaxis.set(label_position='top')
newax.yaxis.set(label_position='right', offset_position='right')
newax.yaxis.get_label().set_rotation(-90) # Optional...
newax.yaxis.tick_right()
newax.xaxis.tick_top()
return newax
# Generate random data.
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)
# Plot both curves.
fig, ax1 = plt.subplots()
ax1.set(xlabel='x_1', ylabel='y_1')
ax1.plot(x1, y1, c='r')
ax2 = twinboth(ax1)
ax2.set(xlabel='x_2', ylabel='y_2')
ax2.plot(x2, y2, c='b')
plt.show()
Both produce identical output:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With