Growth, latency and frequency data often span decades, where a linear axis hides everything but the largest values.
ax.set_yscale("log") (or ax.set_xscale) spaces ticks by powers of ten, so equal distances mean equal ratios. Exponential growth becomes a straight line, and small and huge values are both visible. ax.loglog, ax.semilogy and ax.semilogx are shortcuts that plot and set scales at once.
Log scales cannot show zero or negative values. By default those points are masked (not drawn). If your data crosses zero, use:
"symlog": linear withinlinthreshof zero and logarithmic beyond, symmetric for negatives."asinh": a smooth alternative with similar behavior."logit"for probabilities very close to 0 or 1.
A twin axis shares the x axis but has an independent y axis on the right: ax2 = ax.twinx(). Use it to overlay, say, temperature and rainfall over the same months. Each Axes has its own lines, so a combined legend needs the handles from both:
h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(h1 + h2, l1 + l2)Color each y axis label like its line so readers know which scale applies.
Use twin axes sparingly: two independent scales let a chart suggest correlations that depend only on how you set the limits. Side-by-side subplots with a shared x are often more honest.
Example
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
days = np.arange(1, 31)
users = 10 * 1.3 ** days
fig, ax = plt.subplots()
ax.plot(days, users, color="C0", label="users")
ax.set_yscale("log") # exponential -> straight line
ax.set_ylabel("Users (log)", color="C0")
ax2 = ax.twinx() # second y axis, same x
ax2.plot(days, np.gradient(users) / users * 100, "C1--", label="growth %")
ax2.set_ylabel("Daily growth (%)", color="C1")
h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(h1 + h2, l1 + l2, loc="upper left")
print(ax.get_yscale(), ax2.get_yscale()) # log linear
fig.savefig("growth.png")Remember
- Log scales show ratios; exponential growth becomes linear
- Use symlog or asinh when data includes zero or negatives
ax.twinx()adds an independent right y axis; merge legends manually
Watch out for
- Plotting zeros on a log axis and silently losing those points.