How to Plot a Matplotlib Secondary Y-Axis with a Log Scale

Plotting data with vastly different scales on the same chart can be a real headache. I’ve often found myself staring at a flat line on a linear scale, simply because one dataset overshadowed the other.

In this tutorial, I will show you how to implement a secondary Y-axis and apply a logarithmic scale. This is a technique I use frequently when comparing growth rates against absolute volumes.

1. Use the twinx() Method with set_scale

The most common way I handle this is by using the twinx() function. This creates a new axes object that shares the same X-axis but allows for an independent Y-axis.

When I’m dealing with financial data, like the market cap of tech companies versus their stock price volatility, a log scale on the second axis is essential for clarity.

Example: U.S. Tech Stock Volume vs. Price

In this example, we will plot the trading volume (linear scale) and the stock price (logarithmic scale) for a hypothetical U.S. company.

import matplotlib.pyplot as plt
import numpy as np

# Sample data: Last 10 days of trading for a US Tech Stock
days = np.arange(1, 11)
trading_volume = [1500000, 2100000, 1800000, 3500000, 4200000, 3800000, 5000000, 4800000, 5500000, 6000000]
stock_price = [150, 155, 180, 250, 400, 650, 1100, 1800, 3200, 5000]

# Create the figure and the first axis
fig, ax1 = plt.subplots(figsize=(10, 6))

# Plotting the Trading Volume on the first Y-axis (Linear)
color_vol = 'tab:blue'
ax1.set_xlabel('Trading Days (Day No.)')
ax1.set_ylabel('Trading Volume (Shares)', color=color_vol)
ax1.bar(days, trading_volume, color=color_vol, alpha=0.3, label='Volume')
ax1.tick_params(axis='y', labelcolor=color_vol)

# Create a twin axis for the price
ax2 = ax1.twinx()

# Plotting the Stock Price on the second Y-axis (Logarithmic)
color_price = 'tab:red'
ax2.set_ylabel('Stock Price (USD) - Log Scale', color=color_price)
ax2.plot(days, stock_price, color=color_price, marker='o', linewidth=2, label='Price')

# Setting the second Y-axis to Log Scale
ax2.set_yscale('log')
ax2.tick_params(axis='y', labelcolor=color_price)

# Adding a title
plt.title('U.S. Tech Stock Performance: Volume vs. Price Growth')

# Grid and Layout
ax1.grid(True, which='both', linestyle='--', alpha=0.5)
fig.tight_layout()

plt.show()

You can see the output in the screenshot below.

Plot Matplotlib Secondary Y-Axis with Log Scale

I prefer using the set_yscale(‘log’) command directly on the twin object. It keeps the code clean and ensures that only the secondary axis is affected.

2. Handle Log Scale with secondary_yaxis

Matplotlib introduced secondary_yaxis in version 3.1. This is a slightly different approach where the second axis is essentially a transformation of the first.

However, for completely independent datasets, I still find twinx() more reliable. I use secondary_yaxis mostly when the second axis represents a unit conversion (like Fahrenheit to Celsius).

When to Use a Log Scale on the Secondary Axis

I often see developers forcing both datasets onto a linear scale. This is a mistake if your secondary data grows exponentially, such as U.S. national debt figures or COVID-19 case counts over time.

By applying a log scale to only the secondary axis, you preserve the visual integrity of the primary data while making the secondary trends readable.

3. Customize Ticks and Formatting

One thing I’ve noticed is that Matplotlib’s default log ticks can sometimes look sparse. To fix this, I use the LogLocator and ScalarFormatter.

This gives me total control over how the numbers appear, which is vital when presenting reports to stakeholders who might not be familiar with scientific notation.

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np

# Data: Year and U.S. GDP vs. Public Debt (Simplified for demonstration)
years = np.array([2010, 2012, 2014, 2016, 2018, 2020, 2022])
gdp_trillions = [14.9, 16.2, 17.5, 18.7, 20.6, 21.0, 25.4]
national_debt = [13.5, 16.0, 17.8, 19.5, 21.5, 27.7, 31.4] # Debt often spikes faster

fig, ax1 = plt.subplots(figsize=(10, 6))

# Primary Axis: GDP
ax1.plot(years, gdp_trillions, color='green', marker='s', label='U.S. GDP (Trillions)')
ax1.set_ylabel('GDP in Trillions ($)', color='green')
ax1.tick_params(axis='y', labelcolor='green')

# Secondary Axis: Debt with Log Scale
ax2 = ax1.twinx()
ax2.set_yscale('log')
ax2.plot(years, national_debt, color='darkred', linestyle='--', marker='^', label='National Debt')
ax2.set_ylabel('National Debt (Log Scale)', color='darkred')

# Formatting Log Ticks to be more readable
ax2.yaxis.set_major_formatter(ticker.ScalarFormatter())
ax2.yaxis.get_major_formatter().set_scientific(False)

plt.title('U.S. Economic Indicators: GDP vs. Debt Growth')
plt.show()

You can see the output in the screenshot below.

How to Plot a Matplotlib Secondary Y-Axis with a Log Scale

In this code, I used the ScalarFormatter. This prevents the axis from showing “10^1” and instead shows “10,” which I find much more user-friendly for business charts.

Important Considerations for Log Scales

When you use a log scale on a secondary axis, remember that you cannot plot zero or negative values.

I’ve spent hours debugging code only to realize my dataset had a single ‘0’ value that broke the log transformation. If your data includes zeros, consider using a symlog (symmetrical log) scale instead.

Symmetrical Log (symlog) for Secondary Axes

If your data includes values close to zero or negative numbers, ax.set_yscale(‘symlog’) is your best friend. It allows for a linear region around zero while maintaining logarithmic behavior for larger values.

Summary of Best Practices

I always recommend these three rules when using secondary Y-axes:

  1. Always label both Y-axes clearly, including the scale type.
  2. Use different colors for the lines/bars and their corresponding axis labels.
  3. Only use a log scale if the data spans several orders of magnitude.

Applying these techniques will make your Python visualizations significantly more professional and easier to interpret.

I hope you found this tutorial helpful! Using a secondary Y-axis with a log scale is a powerful way to reveal hidden patterns in your data. Whether you are analyzing U.S. market trends or scientific data, this approach provides the flexibility you need.

If you have any questions or run into issues with your plots, feel free to experiment with the tick formatters. They are often the key to making a complex chart look simple.

You may read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.