Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: Aligning two y-axis around zero

I have a plot with two y-axis on a shared x-axis, and I want to make them align at y=0 so that I can draw a horizontal line to highlight the zero tick. currently the two axis are not aligned and I have to draw two line which is terrible. How can I achieve this?

enter image description here

like image 603
dingx Avatar asked Apr 12 '19 07:04

dingx


2 Answers

Assuming that you created the plots with a shared axis, you just have to modify the range of y to be centered at zero or have a similar offset multiplier in both plots (i.e set ax.set_ylim(-6,6) for both plots). The following code is an example.

from matplotlib import pyplot as plt
import numpy as np

#Create some Fake Data
x =np.arange(-10,10)
y = x+np.random.rand(20)
y2 = 0.5*x-3.*np.random.rand(20)


#Figure
fig = plt.figure(figsize=(12,6))

#First subplot with zero line not even
ax1 = plt.subplot(121)
ax2 = ax1.twinx()

ax1.plot(x,y,c='r')
ax2.plot(x,y2,c='b')

ax1.axhline(0)

#Second Subplot with zero line the same on both axes
ax3 = plt.subplot(122)
ax4 = ax3.twinx()

ax3.plot(x,y,c='r')
ax4.plot(x,y2,c='b')

ax3.axhline(0)

#If you set your limits on both sides to have the same interval you will get the same zero line
ax3.set_ylim(-10,10)
ax4.set_ylim(-6,6)

plt.show()

enter image description here

like image 102
BenT Avatar answered Oct 05 '22 23:10

BenT


I had the same issue, and what I did was to change the extents of the y-axis, depending on the ratio of the min to max limits. If you set the ratio of the y-axes to be the same, the zero point should be the same.

fig, ax1 = plt.subplots()

ax1.plot(...)     # Plot first data set
ax2 = ax1.twinx()
ax2.plot(...)     # Plot second data set

ax1_ylims = ax1.axes.get_ylim()           # Find y-axis limits set by the plotter
ax1_yratio = ax1_ylims[0] / ax1_ylims[1]  # Calculate ratio of lowest limit to highest limit

ax2_ylims = ax2.axes.get_ylim()           # Find y-axis limits set by the plotter
ax2_yratio = ax2_ylims[0] / ax2_ylims[1]  # Calculate ratio of lowest limit to highest limit


# If the plot limits ratio of plot 1 is smaller than plot 2, the first data set has
# a wider range range than the second data set. Calculate a new low limit for the
# second data set to obtain a similar ratio to the first data set.
# Else, do it the other way around

if ax1_yratio < ax2_yratio: 
    ax2.set_ylim(bottom = ax2_ylims[1]*ax1_yratio)
else:
    ax1.set_ylim(bottom = ax1_ylims[1]*ax2_yratio)

plt.tight_layout()
plt.show()

This is my first answer, so I hope it is sufficient and okay.

like image 34
KobusNell Avatar answered Oct 05 '22 23:10

KobusNell