Data Analysis for Engineers/Module 4

Module 4 · Section 5 of 10

Lesson 4.4 - Seaborn for Statistical Plots

Target: ~9 min read - 20 min hands-on

Overview

Seaborn builds on matplotlib with higher-level statistical chart types: boxplots and violin plots for comparing distributions across categories, heatmaps for correlation matrices, and pairplots for scanning relationships across many variables. We'll visualize supplier-to-supplier variation in a measured component dimension.

Why This Matters (Engineering Context)

A boxplot comparing a measured property across suppliers or batches makes QA/QC variability immediately visible in a way a table of numbers doesn't - exactly the chart that supports (or challenges) a supplier's quality claim.

Code-Along

import seaborn as sns   # statistical charts built on top of matplotlib

# Build a long-format DataFrame: one row per (supplier, batch) measurement
np.random.seed(15)
suppliers = ["Supplier A", "Supplier B", "Supplier C"]
means = {"Supplier A": 25.02, "Supplier B": 25.00, "Supplier C": 24.98}
stds = {"Supplier A": 0.020, "Supplier B": 0.045, "Supplier C": 0.015}
batch_rows = []
for sup in suppliers:
    for batch in range(20):
        batch_rows.append((sup, batch, round(np.random.normal(means[sup], stds[sup]), 3)))
parts_df = pd.DataFrame(batch_rows, columns=["supplier", "batch", "diameter_mm"])

# seaborn takes data=DataFrame + column names for x / y; it groups by x automatically
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.boxplot(data=parts_df, x="supplier", y="diameter_mm", ax=axes[0])    # box = quartiles
axes[0].axhline(25.00, color="red", linestyle="--", label="nominal")     # horizontal reference line
axes[0].set_title("Component Diameter by Supplier (Boxplot)"); axes[0].legend()
sns.violinplot(data=parts_df, x="supplier", y="diameter_mm", ax=axes[1]) # violin = full density shape
axes[1].axhline(25.00, color="red", linestyle="--")
axes[1].set_title("Component Diameter by Supplier (Violin)")
plt.tight_layout(); plt.show()

# --- Heatmap of a correlation matrix ---
corr_df = df[["energy_kwh", "ambient_c"]].copy()
corr_df["day_of_year"] = df["date"].dt.dayofyear
fig, ax = plt.subplots(figsize=(5, 4))
# .corr() -> pairwise correlation table; annot=True prints the numbers in each cell
sns.heatmap(corr_df.corr(), annot=True, cmap="coolwarm", vmin=-1, vmax=1, ax=ax)
ax.set_title("Correlation Matrix")
plt.tight_layout(); plt.show()

# pairplot: a grid of scatter plots for every pair of numeric columns,
# with histograms on the diagonal; hue colours the points by a category
sns.pairplot(parts_df[["batch", "diameter_mm"]].assign(supplier=parts_df["supplier"]),
             hue="supplier", height=2.2)
plt.show()

Run it: the boxplot and violin plot both show Supplier B with the widest spread (largest std, 0.045 vs 0.020 and 0.015) - the violin additionally shows the shape of that spread. The heatmap shows a mild positive correlation between energy_kwh and day_of_year (the cooling-season pattern) and a stronger one between energy_kwh and ambient_c. The pairplot renders a grid of scatter/histogram combinations, colored by supplier.

Practice Exercises

  1. Add a 4th supplier with a mean of 24.90 mm (biased low) and re-run the boxplot - how obvious is the problem visually?
  2. Compute the exact correlation coefficient between energy_kwh and ambient_c with .corr() and compare it to the heatmap.
  3. Try sns.stripplot() instead of boxplot/violin - what does showing every point add that the boxplot hides?
# Try the practice exercises here

Knowledge Check

  1. What does a violin plot show that a boxplot doesn't?
  2. What does a heatmap of a correlation matrix visualize?
  3. What is a pairplot useful for with several numeric variables?
Answer key
  1. The estimated shape (density) of the full distribution, not just quartiles
  2. The strength and direction of pairwise linear relationships, color-coded
  3. Quickly scanning scatter relationships and individual distributions across every pair at once

38 / 63 sections · Course home · Join the coaching cohort