tanasr
tanasr

Reputation: 115

How to keep the pyplot axis scaled according to one plot only and not extending for other plots?

I want to plot several functions in one figure, but I want to prevent the axis to be extended if one function is plotted that has much higher/smaller values than others. In the code below, the parameter alpha is actually random (here I fixed it to alpha = 2), and could get very high values which messes up my plot. Basically what I would like to do is, I'd like to plot one function, then freeze the axis according to its xlim and ylim, then add the remaining plots without extending the axis anymore if alpha happens to be large. How can I do this? The solution here did unfortunately not work for me, i.e., using plt.autoscale(False) I would need to fix the limits manually, which is not what I want.

Here is a minimum working example:

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = 2
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)


axsLeft = subfigs[0].subplots(1, 1)
axsLeft.plot(x,data1)
# plt.autoscale(False)
axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
# axsLeft.set_ylim([-1.05,+1.05])
axsLeft.set_xlabel("x")


axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsRight[1].set_xlabel('x')

fig.show()

My plot This orange plot extends the axis such that the other plots are not interpretable anymore. I'd like the orange plot to to overshoot in the y-direction, like this: What I want but without setting ylim manually.

Upvotes: 3

Views: 826

Answers (2)

zorRo
zorRo

Reputation: 96

After plotting the reference, in your case data1, you can retrieve the defined y-axis limits with get_ylim() in seperate variables a and b and rescale your axis accordingly after plotting the remaining curves with set_ylim:

This makes sure the axis is always scaled according to the reference and it works even if the lower limit of the y-axis is very low or zero.

import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = 2
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)


axsLeft = subfigs[0].subplots(1, 1)
# reference axis
axsLeft.plot(x,data1)
a,b = axsLeft.get_ylim()

axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
axsLeft.set_xlabel("x")

# set limit according to reference
axsLeft.set_ylim((a,b))


axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsRight[1].set_xlabel('x')

fig.show()

Upvotes: 3

Desty
Desty

Reputation: 337

If you want to adjust the y-axis to the maximum and minimum values ​​of data1, use the code below. (0.05 is padding.)

axsLeft.set_ylim(np.min(data1) - 0.05, np.max(data1) + 0.05)

If you want the alpha value to also vary according to data1, you can get the value by subtracting the alpha value from np.max() and np.min(). Below is a modified version of the code you uploaded.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = np.max(data1) - np.min(data1) # change 1
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)

axsLeft = subfigs[0].subplots(1, 1)
axsLeft.plot(x,data1)
axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
axsLeft.set_xlabel("x")
axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsLeft.set_ylim(-alpha / 2 - 0.05, alpha / 2 + 0.05) # change 2
axsRight[1].set_xlabel('x')

plt.show()

Upvotes: 1

Related Questions