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.