Use log-log and semilog axes to turn power laws and exponentials into straight lines, then read the exponent or rate from a linear fit.
Why this matters
Many physical laws are not straight lines. A pendulum's period grows with the square root of its length. Radioactive activity, capacitor voltage during discharge and first-order reaction concentrations fall exponentially. Fatigue life, sound intensity and earthquake energy span many powers of ten. Plotted on ordinary axes, these curves hide their structure and squash small values into a corner. Logarithmic axes spread them out and, for the right kind of law, turn the curve into a straight line whose slope you can read off and fit.
Two shapes, two kinds of axis
Power law: y = a x^b. Take logs of both sides:
log y = log a + b log x
On log-log axes (both axes logarithmic) this is a straight line with slope b (the exponent) and intercept log a.
Exponential: y = A e^(k t) (decay when k < 0). Take the natural log of y only:
ln y = ln A + k t
On semilog axes (log y, linear t) this is a straight line with slope k.
A quick diagnostic: plot your data both ways. Whichever plot is straight tells you the type of law.
Plotting with log axes
import numpy as np
import matplotlib.pyplot as plt
L = np.array([0.10, 0.20, 0.40, 0.80, 1.60]) # pendulum length, m
T = np.array([0.636, 0.898, 1.268, 1.795, 2.538]) # period, s
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(7, 3))
ax1.plot(L, T, "o")
ax1.set_xlabel("Length (m)"); ax1.set_ylabel("Period (s)")
ax2.loglog(L, T, "o") # same as ax.set_xscale("log"); ax.set_yscale("log")
ax2.set_xlabel("Length (m)"); ax2.set_ylabel("Period (s)")
ax.semilogy(t, y) sets only the y-axis to log. A log axis keeps the original values on its tick labels (0.1, 1, 10), which is easier to read than plotting np.log10(y) on a linear axis.
Fitting on the linearised data
To get numbers, fit a straight line to the transformed data with np.polyfit(x, y, 1), which returns [slope, intercept].
Worked example 1: pendulum power law
b, log_a = np.polyfit(np.log(L), np.log(T), 1)
a = np.exp(log_a)
print(round(b, 3), round(a, 3)) # 0.5 2.006
The exponent is 0.5, matching T = 2π sqrt(L / g). The prefactor a = 2π / sqrt(g) gives g = (2π / a)^2 ≈ 9.81 m/s².
Which log base you use does not matter for the exponent, as long as you use the same base on both axes; the prefactor must be converted back with the matching inverse (np.exp for np.log, 10** for np.log10).
Worked example 2: capacitor discharge
A capacitor discharges through a resistor: V(t) = V0 e^(-t / τ).
t = np.array([0, 1, 2, 3, 4, 5], dtype=float) # ms
V = np.array([9.00, 5.46, 3.31, 2.01, 1.22, 0.74]) # volts
k, ln_V0 = np.polyfit(t, np.log(V), 1)
tau = -1 / k
print(round(tau, 2), round(np.exp(ln_V0), 2)) # 2.0 ms, 9.0 V
The half-life is τ ln 2 ≈ 1.39 ms: the voltage halves every 1.39 ms, whatever its starting value. That constant-ratio behaviour is the signature of an exponential.
Caveats of fitting in log space
Linearised fits are quick, robust and usually good enough. Know their limits:
- Zero and negative values have no logarithm. Remove them (and say so) or use a model that handles an offset, such as
y = A e^(kt) + C, fitted with non-linear least squares (next module). - Noise is reshaped. A least-squares fit to
log yweights small values more heavily, because a fixed error is a bigger fraction of a small number. If your noise is constant in absolute terms, the log fit gives slightly biased parameters; a non-linear fit on the original scale is more correct. - Offsets break straightness. A background level (dark current, baseline absorbance) makes a semilog plot curve at long times. Subtract the background first if you know it.
- Range matters. A power law that is straight over two decades may bend outside them. Do not extrapolate beyond the data.
Common mistakes
- Fitting
yagainstlog xwhen you meant log-log, or forgetting to transformyfor an exponential. - Reporting
log aasa. Convert the intercept back withexpor10**. - Mixing bases: fitting with
np.log10and converting back withnp.exp. - Taking the log of data containing zeros, which gives
-infand aRuntimeWarning, then a fit full ofnan. - Reading slopes off a log axis by eye using tick distances instead of fitting the transformed values.
Quick recap
- Power law
y = a x^b: straight on log-log; slope =b. - Exponential
y = A e^(kt): straight on semilog-y; slope =k, time constantτ = -1/k. ax.loglog,ax.semilogyfor plotting;np.polyfiton the logged data for numbers.- Watch for zeros, offsets and noise reshaping; use a non-linear fit when they matter.
Try it
In the Do tab you will write power-law and exponential fitting functions and test them on noisy, seeded data.