Data Analysis for Engineers/Module 5

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

  1. Compute the correlation between vibration and defects within months whose throughput_kunits is between 7 and 9 only - does the relationship weaken once the confounder is held roughly constant?
  2. 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?
  3. 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

  1. What does Pearson correlation measure that Spearman does not require?
  2. Why is Spearman more robust to outliers than Pearson?
  3. What is a "confounding variable," using this lesson's example?
Answer key
  1. Pearson measures linear strength; Spearman only requires a monotonic relationship, using ranks
  2. It operates on ranks, so one extreme value can't dominate the calculation
  3. 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