Twin Axes & Secondary Y
Matplotlib is a Python library for creating charts and visualizations — and twin axes let you overlay two series with completely different scales, like temperature and rainfall, on a single shared x-axis.
Learn Twin Axes & Secondary Y in our free Matplotlib course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Matplotlib course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll create a second y-axis with ax.twinx(), color-code each axis to its line, and combine both series into one legend.
Imagine plotting temperature (around 20°C) and rainfall (around 200 mm) on the same y-axis. The rainfall values are ten times bigger, so the temperature line would be squashed flat at the bottom. A twin axis gives each series its own scale.
What you'll see: two lines over the same months — a red temperature line rising left-to-right, and a blue rainfall line, each read against its own y-axis (temperature on the left, rainfall on the right).
With two y-axes, the reader needs to know which scale belongs to which line. The convention is to color each set_ylabel to match its line — and color the tick labels too with ax.tick_params(axis='y', labelcolor=...) .
What you'll see: the same two-line chart, but now the left axis label and ticks are red (matching the temperature line) and the right axis label and ticks are blue (matching rainfall) — so it's obvious which scale each line uses.
Because each line lives on a different axes, a normal ax.legend() would only show one of them. The fix: keep the line objects that plot() returns, then build a single legend from both.
What you'll see: the dual-scale chart with a single legend box in the upper-left listing both "Temp (°C)" and "Rain (mm)" together — even though the two lines belong to different axes.
Replace each ___ to add a second y-axis and label it.
The two series share a single y-axis. Add ax2 = ax.twinx() and plot the second series on ax2 .
Each axes has its own legend. Keep both line objects and call ax.legend([line1, line2], [...]) .
Plot a stock's price and trading volume on twin axes with matching colors and a shared legend.
Lesson 15 complete — two scales, one chart!
You created a secondary y-axis with ax.twinx(), color-matched each axis to its line, and merged two series into a single shared legend.
🚀 Up next: Plotting with Pandas — chart straight from DataFrames.
Practice quiz
What is a twin axis?
- A second figure window
- A duplicated chart title
- A second y-axis that shares the same x-axis
- Two separate subplots side by side
Answer: A second y-axis that shares the same x-axis. A twin axis is a second y-axis sharing the same x-axis, made with ax.twinx().
Which call creates a second y-axis sharing the x-axis?
- ax2 = ax.twinx()
- ax2 = ax.copy()
- ax2 = plt.second_axis()
- ax2 = ax.clone()
Answer: ax2 = ax.twinx(). ax2 = ax.twinx() makes a new axes with an independent y-axis on the right.
When is a twin axis most useful?
- When both series use the same units
- When you have only one series
- When you want a 3D chart
- When two series share x but have very different scales
Answer: When two series share x but have very different scales. It gives each series its own y-scale so one isn't squashed flat.
How do you color a y-axis label to match its line?
- ax.color_label('red')
- ax.set_ylabel('Temp', color='tab:red')
- ax.label_color('red')
- ax.ylabel('Temp').color('red')
Answer: ax.set_ylabel('Temp', color='tab:red'). set_ylabel('Temp', color='tab:red') colors the label to match the line.
Which call colors the y-tick labels of an axis?
- ax.set_tickcolor('red')
- ax.color_ticks('red')
- ax.tick_params(axis='y', labelcolor='tab:red')
- ax.yticks(color='red')
Answer: ax.tick_params(axis='y', labelcolor='tab:red'). tick_params(axis='y', labelcolor=...) recolors the y-tick labels.
Why does a plain ax.legend() show only one line on twin axes?
- Each axes has its own separate lines
- Legends are disabled on twins
- twinx() deletes labels
- Only the last line is kept
Answer: Each axes has its own separate lines. Each line lives on a different axes, so one axes' legend sees only its own lines.
What does the trailing comma do in 'line1, = ax.plot(...)'?
- Adds a second line
- Sets the line color
- Reverses the data
- Unpacks the single Line2D from the returned list
Answer: Unpacks the single Line2D from the returned list. plot() returns a list; the trailing comma unpacks the single Line2D object.
How do you build one legend covering both lines?
- Call ax.legend() twice
Gather the saved line objects and pass them both to ax.legend([...], [...]).
What problem does twinx() solve when units differ greatly?
- It changes the x-axis labels
- It adds gridlines
- One series being squashed flat against a single shared y-axis
- It rotates the chart
Answer: One series being squashed flat against a single shared y-axis. Without a twin, the smaller-scale series flattens; the twin gives it its own scale.
On which side does ax.twinx() place the new y-axis?
- The right side of the chart
- The left side
- The top
- The bottom
Answer: The right side of the chart. twinx() adds an independent y-axis on the right while sharing the x-axis.