8

I'd like to add a second y-axis to my plot plt.plot([1,2,4]) on the right side, which should be aligned with the left axis, but in different units which can be calculated.

For example a scaling to 1. So effectively the left y-axis will be [1,2,3,4] and the right should be [0.25, 0.5, 0.75, 1.0] and properly aligned.

How can I do that in matplotlib?

(the twin axis example seems to handle a different use-case where you have un-aligned axes on different data)

Gere
  • 12,075
  • 18
  • 62
  • 94
  • a quick workaround would be to use `twiny` and manually provide limits for that axis that are based on the limits of the left-hand side y-axis ... but I'm aware that this is not the solution you are looking for... – mommermi Oct 07 '16 at 18:29
  • Adapt the gallery's celsius-or-fahrenheit example: http://matplotlib.org/examples/subplots_axes_and_figures/fahrenheit_celsius_scales.html – cphlewis Oct 07 '16 at 22:34
  • @cphlewis: Thanks. That works. I just had to be careful not to use `plt.` thereafter, or it gets confused. – Gere Oct 10 '16 at 15:01
  • Yes, this crosses the boundary from the pyplot/matlab style to where OO style works better -- [nice summary](http://matplotlib.org/faq/usage_faq.html?highlight=plt%20style#coding-styles) – cphlewis Oct 13 '16 at 19:38
  • Does this answer your question? [How to add a second x-axis in matplotlib](https://stackoverflow.com/questions/10514315/how-to-add-a-second-x-axis-in-matplotlib) – G M Nov 28 '19 at 13:08
  • PSA: The example above will not work if the two axes being plotted do not have a linear relationship :( – pretzlstyle Sep 17 '21 at 19:09

1 Answers1

6

This was answered in a link in the comments, but I'd like to add the solution here in case that link breaks. Basically you make a twin axis, and use callbacks.connect to make sure the new axis updates whenever the original does. As such, the connection code needs to go before the plotting commands. Using the OP's example:

import matplotlib.pyplot as plt

x = [1,2,3,4]

fig, ax1 = plt.subplots()

# add second axis with different units, update it whenever ax1 changes
ax2 = ax1.twinx()

def convert_ax2(ax1):
    y1, y2 = ax1.get_ylim()
    ax2.set_ylim(y1/max(x), y2/max(x))
    ax2.figure.canvas.draw()    

ax1.callbacks.connect("ylim_changed", convert_ax2)   

ax1.plot(x)

plot with two axes

SpinUp __ A Davis
  • 5,016
  • 1
  • 30
  • 25