Module 5 · Section 4 of 12
Lesson 5.3 - Correlation & Covariance
Target: ~9 min read - 20 min hands-on
Overview
Pearson correlation measures the strength of a linear relationship (-1 to +1). Spearman correlation measures a monotonic relationship using ranks, more robust to outliers. Both are silent on causation - correlation != causation is a discipline you actively maintain when interpreting results.
Why This Matters (Engineering Context)
Machine vibration and defect rate are correlated on a production line - but so are many things that rise when the line runs harder. A responsible analysis states the correlation, then explicitly discusses the mechanism (or the confounder) rather than letting the correlation imply causation.
Code-Along
np.random.seed(60)
# 48 months of line data. throughput drives BOTH vibration AND defects -> a confounder.
n = 48
throughput_kunits = np.random.poisson(8, n) + np.random.normal(0, 1.0, n) # thousands of units / month
vibration_mm_s = 2.0 + 0.35 * throughput_kunits + np.random.normal(0, 0.4, n)
defects = np.round(4 + 1.6 * throughput_kunits + np.random.normal(0, 2.0, n)).clip(0) # .clip(0): no negatives
# pearsonr = strength of a LINEAR relationship; spearmanr = of a MONOTONIC one (rank-based)
pearson_r, pearson_p = stats.pearsonr(vibration_mm_s, defects)
spearman_r, spearman_p = stats.spearmanr(vibration_mm_s, defects)
print(f"Pearson r: {pearson_r:.3f} (p={pearson_p:.4f})")
print(f"Spearman r: {spearman_r:.3f} (p={spearman_p:.4f})")
# np.cov returns the 2x2 covariance matrix; [0, 1] is the cross-covariance term
print(f"\nCovariance: {np.cov(vibration_mm_s, defects)[0, 1]:.2f}")
# both variables are strongly correlated with the hidden driver...
r_tp_vib, _ = stats.pearsonr(throughput_kunits, vibration_mm_s)
r_tp_def, _ = stats.pearsonr(throughput_kunits, defects)
print(f"\nCorrelation(throughput, vibration): {r_tp_vib:.3f}")
print(f"Correlation(throughput, defects): {r_tp_def:.3f}")
print("\nBoth vibration and defects are driven by the same upstream cause (throughput);")
print("vibration doesn't directly 'cause' every defect in this simplified model.")
fig, ax = plt.subplots(figsize=(6, 5))
ax.scatter(vibration_mm_s, defects, alpha=0.6, color="darkorange")
ax.set_xlabel("Vibration (mm/s)"); ax.set_ylabel("Monthly defect count")
ax.set_title(f"Vibration vs Defects (Pearson r={pearson_r:.2f})")
plt.tight_layout(); plt.show()
Run it: both correlations come out strongly positive, since vibration and defects genuinely move together. The second half shows that both are actually driven by throughput - a reminder that a strong correlation is a starting point for investigation, not a finished causal explanation.
Practice Exercises
- Compute the correlation between vibration and defects within months whose
throughput_kunitsis between 7 and 9 only - does the relationship weaken once the confounder is held roughly constant? - Add a clear outlier (one month with vibration 12 mm/s but 0 defects) and compare how much the Pearson vs Spearman correlation shifts - which is more robust?
- In 2-3 sentences, describe a plausible confounding variable for a correlation you've seen in your own engineering work.
# Try the practice exercises here
Knowledge Check
- What does Pearson correlation measure that Spearman does not require?
- Why is Spearman more robust to outliers than Pearson?
- What is a "confounding variable," using this lesson's example?
Answer key
- Pearson measures linear strength; Spearman only requires a monotonic relationship, using ranks
- It operates on ranks, so one extreme value can't dominate the calculation
- Throughput - it drives both vibration and defects, creating a correlation between them even though neither directly causes the other
47 / 63 sections · Course home · Join the coaching cohort