HOWTO · Matplotlib
How to Add a Y-Axis Label to the Secondary Y-Axis in Matplotlib
Learn how to add a y-axis label to the secondary y-axis in Matplotlib using the axes object and pandas DataFrame plot method. This guide provides step-by-step instructions, code examples, and tips for customizing your visualizations. Perfect for data analysts and anyone interested in enhancing their data visualization skills.
On this page
To label a secondary y-axis in Matplotlib, call set_ylabel() on the secondary axes returned by Axes.twinx(). The returned axes object shares the plot’s x-axis and provides an independent y-axis on the opposite side. Use descriptive labels, including units when they help distinguish the quantities.
Add a label to the secondary y-axis with twinx()
Create the second axes with ax.twinx(), plot the second series on it, and set its label directly. This complete example defines both colors and uses tight_layout() to leave room for the labels.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 5, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), color="tab:blue")
ax.set_xlabel("Time (s)")
ax.set_ylabel("sin(x)", color="tab:blue")
ax.tick_params(axis="y", labelcolor="tab:blue")
ax2 = ax.twinx()
ax2.plot(x, np.cos(x), color="tab:orange")
ax2.set_ylabel("cos(x)", color="tab:orange")
ax2.tick_params(axis="y", labelcolor="tab:orange")
fig.tight_layout()
plt.show()
ax2 is the secondary axes, so ax2.set_ylabel(...) places the label on the right-hand y-axis. Applying set_ylabel() to ax instead changes the primary, left-hand label. Matching label and tick colors to each line is optional, but can help readers tell the two scales apart.
When the first example is displayed, the horizontal axis is labeled Time (s). A blue sine curve uses the left y-axis, and an orange cosine curve uses the right y-axis. Both curves span the same time values, while each vertical scale is read against its own side of the figure. The feature image for this article shows Height and Weight axes; it is a separate illustration and does not depict these sine and cosine curves.
Customize the y-axis labels for clarity
Choose text that names the measured quantity and its unit, such as Temperature (°C) or Pressure (kPa). Styling is optional: pass arguments such as color, fontsize, or fontweight to set_ylabel() when they improve legibility. Keep the labels distinct and avoid relying on color alone to explain which data belongs to each scale.
This example applies those styling options to a chart whose left scale reports temperature in degrees Celsius and whose right scale reports pressure in kilopascals:
import matplotlib.pyplot as plt
import numpy as np
hours = np.arange(0, 24, 2)
temperature = 18 + 4 * np.sin((hours - 9) * np.pi / 12)
pressure = 101.3 + 0.8 * np.cos((hours - 6) * np.pi / 12)
fig, ax = plt.subplots()
ax.plot(hours, temperature, color="tab:red", marker="o")
ax.set_xlabel("Hour of day")
ax.set_ylabel(
"Temperature (°C)", color="tab:red", fontsize=12, fontweight="bold"
)
ax.tick_params(axis="y", labelcolor="tab:red")
ax2 = ax.twinx()
ax2.plot(hours, pressure, color="tab:green", marker="s")
ax2.set_ylabel(
"Pressure (kPa)", color="tab:green", fontsize=12, fontweight="bold"
)
ax2.tick_params(axis="y", labelcolor="tab:green")
fig.tight_layout()
plt.show()
Treat each label as a short description of the values read from that side of the chart, as in the example above. The text and units tell readers what the numbers mean; matching label color to a line is an additional visual cue. If labels feel crowded, tight_layout() can adjust the figure spacing, though a long label may still need a larger figure or a shorter wording.
Add a secondary y-axis label with DataFrame.plot
For pandas data, pass the first plot’s axes through ax when plotting the second series with secondary_y=True. DataFrame.plot returns an axes object for each call: the first call returns the primary axes, and the second returns the secondary axes. Set each label on the corresponding object.
import matplotlib.pyplot as plt
import pandas as pd
frame = pd.DataFrame({
"age": [10, 20, 30, 40],
"height": [120, 140, 160, 170],
"weight": [30, 45, 60, 70],
})
ax = frame.plot(x="age", y="height", color="tab:blue")
ax2 = frame.plot(
x="age", y="weight", secondary_y=True, ax=ax, color="tab:orange"
)
ax.set_ylabel("Height (cm)")
ax2.set_ylabel("Weight (kg)")
plt.tight_layout()
plt.show()
Here secondary_y selects the right-hand scale for weight, while ax=ax overlays that series in the same figure. If you use different column names or units, update both the y arguments and the labels so they describe the data being plotted.
For the values in this example, the displayed chart has age along the horizontal axis, Height (cm) on the left, and Weight (kg) on the right. The blue height line rises across the four ages, and the orange weight line does too; the two lines are interpreted using their respective y-axis labels and scales. The labels should follow the columns actually plotted, so rename them when changing the selected columns or units. Passing the existing ax keeps both series in one figure, while secondary_y=True assigns the second series to its right-side scale.