Secondary axes in Matplotlib show the same plotted values in a second unit or coordinate scale without drawing another data series. They fit figures that need the native measurement and a converted scale, such as temperatures in Celsius on the left and Fahrenheit on the right.
The secondary_yaxis() and secondary_xaxis() methods attach a converted axis to an existing Axes object. Each method needs a location and a forward/inverse function pair so Matplotlib can convert primary-axis tick values to the secondary scale and map secondary ticks back to the primary scale.
Plot the data on the original Axes and use the secondary axis for converted ticks and labels only. Matplotlib still marks the secondary-axis API as experimental, so keep the conversion functions small and check the exported figure after library upgrades.
Related: How to set axis labels in Matplotlib
Related: How to set axis limits in Matplotlib
Related: How to fix overlapping labels in Matplotlib
Steps to add a secondary axis in Matplotlib:
- Save the secondary-axis script as secondary_axis_temperature.py.
- secondary_axis_temperature.py
from pathlib import Path import matplotlib import matplotlib.pyplot as plt import numpy as np def celsius_to_fahrenheit(celsius): return celsius * 9 / 5 + 32 def fahrenheit_to_celsius(fahrenheit): return (fahrenheit - 32) * 5 / 9 months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] temperature_c = np.array([4, 7, 12, 17, 22, 26]) fig, ax = plt.subplots(figsize=(6, 4), layout="constrained") ax.plot(months, temperature_c, marker="o", linewidth=2) ax.set_title("Average monthly temperature") ax.set_xlabel("Month") ax.set_ylabel("Temperature (deg C)") ax.set_ylim(0, 30) ax.grid(True, axis="y", alpha=0.3) secondary = ax.secondary_yaxis( "right", functions=(celsius_to_fahrenheit, fahrenheit_to_celsius) ) secondary.set_ylabel("Temperature (deg F)") output = Path("temperature-secondary-axis.png") fig.savefig(output, dpi=160) fig.canvas.draw() check_c = np.array([0, 20, 30]) check_f = celsius_to_fahrenheit(check_c) round_trip_c = fahrenheit_to_celsius(check_f) print(f"matplotlib: {matplotlib.__version__} ({matplotlib.get_backend()} backend)") print(f"primary y label: {ax.get_ylabel()}") print(f"secondary y label: {secondary.get_ylabel()}") print(f"conversion check: {check_c.tolist()} deg C -> {check_f.tolist()} deg F") print(f"round trip: {round_trip_c.tolist()} deg C") print(f"saved: {output}") print(f"bytes: {output.stat().st_size}") plt.close(fig)
The forward function converts from the primary axis to the secondary axis. The inverse function converts back, and both functions should accept NumPy arrays because Matplotlib passes tick values as arrays.
- Run the script from the directory where the output image should be written.
$ python secondary_axis_temperature.py matplotlib: 3.11.0 (Agg backend) primary y label: Temperature (deg C) secondary y label: Temperature (deg F) conversion check: [0, 20, 30] deg C -> [32.0, 68.0, 86.0] deg F round trip: [0.0, 20.0, 30.0] deg C saved: temperature-secondary-axis.png bytes: 50407
The byte count can vary by backend, font, Matplotlib version, and DPI. Confirm the primary label, secondary label, reversible conversion, and saved filename.
- Open temperature-secondary-axis.png and check the converted scale.
The left axis should read Temperature (deg C) and the right axis should read Temperature (deg F). Use ax.secondary_xaxis(“top”, functions=(forward, inverse)) instead when the converted scale belongs on the x-axis.
- Remove the temporary files when they were created only to test the secondary axis.
$ rm secondary_axis_temperature.py temperature-secondary-axis.png
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.