Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plot single data with two Y axes (two units) in matplotlib

I'm trying to plot a single time series, but want to represent it in two units on left and right axes. Here's what I have done so far.

fig, ax1 = plt.subplots()
t = np.arange(1,50,1)
s1 = np.sin(t)*20000+40000 #synthetic ts, but closer to my data 
ax1.plot(t, s1, 'b-')

ax1.set_xlabel('time')
ax1.set_ylim(20000,70000)
ax1.set_ylabel('km3/year')

km3yearToSv=31.6887646*(1/1e6)

ax2 = ax1.twinx()
s2 = s1*km3yearToSv
ax2.plot(t, s2, 'b-')
ax2.set_ylim(20000*km3yearToSv,70000*km3yearToSv)
ax2.set_ylabel('Sv')

enter image description here

By adjusting the ylim(), I can get it to seem as a single line, but some aliasing can be seen. I would prefer if I don't have to plot the data twice.

Any suggestions?

UPDATE: Thanks, askewchan, for the perfect solution!

like image 733
hrishi Avatar asked Sep 18 '15 23:09

hrishi


People also ask

How do I plot multiple Y-axis in MatPlotLib?

Create multiple y axes with a shared x axis. This is done by creating a twinx axes, turning all spines but the right one invisible and offset its position using set_position . Note that this approach uses matplotlib.

What is dual axis plot MatPlotLib?

MatPlotLib with Python Moreso, when plotting curves with different units together. Matplotlib supports this with the twinxand twiny functions. In the following example, the plot has dual y axes, one showing exp(x) and the other showing log(x) − import matplotlib. pyplot as plt import numpy as np fig = plt.

How do you add two Y-axis in Python?

The way to make a plot with two different y-axis is to use two different axes objects with the help of twinx() function. We first create figure and axis objects and make a first plot. In this example, we plot year vs lifeExp. And we also set the x and y-axis labels by updating the axis object.


1 Answers

There is no need to plot it twice, this much should give you the result you want:

ax2 = ax1.twinx()
ax2.set_ylim(20000*km3yearToSv, 70000*km3yearToSv)
ax2.set_ylabel('Sv')

A more robust way to do it is to first extract the limits of the plot (in case you change them, and they're no longer 20000 and 70000, or you want the plot to be able to automatically adjust the limits:

ax2 = ax1.twinx()
mn, mx = ax1.get_ylim()
ax2.set_ylim(mn*km3yearToSv, mx*km3yearToSv)
ax2.set_ylabel('Sv')

one plot

Altogether, with some other small tweaks:

import numpy as np
import matplotlib.pyplot as plt

mean, amp = 40000, 20000
t = np.arange(50)
s1 = np.sin(t)*amp + mean #synthetic ts, but closer to my data 

fig, ax1 = plt.subplots()
ax1.plot(t, s1, 'b-')

ax1.set_xlabel('time')
mn, mx = ax1.set_ylim(mean-amp, mean+amp)
ax1.set_ylabel('km$^3$/year')

km3yearToSv = 31.6887646e-6

ax2 = ax1.twinx()
ax2.set_ylim(mn*km3yearToSv, mx*km3yearToSv)
ax2.set_ylabel('Sv')
like image 65
askewchan Avatar answered Oct 02 '22 01:10

askewchan