Skip to content

Exploratory Data Analysis: Statistical Diagnostics & Feature Profiling

Created: 2026-11-08  ·  Last updated: 2026-11-08  ·  Nejat Hakan

Executive Summary: Novice data practitioners frequently rush to train complex neural networks without validating fundamental statistical assumptions, leading to catastrophic failure on real-world Linux server metrics. Bimodal latency spikes, heavy-tailed disk queues, and severe feature multicollinearity mislead gradient-based estimators. This guide details how to execute rigorous Exploratory Data Analysis (EDA) on Debian: diagnosing distributions with Empirical Cumulative Distribution Functions (ECDF), isolating anomalies using robust Interquartile Range (IQR) fences, evaluating monotonic dependencies via Spearman rank correlations, and detecting collinear features using the Variance Inflation Factor (VIF).

  • Distribution Diagnostics


    Look beyond naive means: quantify skewness, kurtosis, and bimodality to determine whether variables require log-transformations or robust medians.

  • ECDF vs. Histogram Binning


    Eliminate bin-width bias: utilize Empirical Cumulative Distribution Functions to inspect 100% of observations without information loss.

  • Multicollinearity & VIF


    Prevent model instability: calculate Variance Inflation Factors (VIF > 5) to detect redundant, tightly coupled telemetry features.

  • Robust Outlier Isolation


    Differentiate sensor noise from real hardware degradation using non-parametric IQR fences and Huber loss thresholding.


1. The Anatomy of Statistical Deception: Anscombe & Bimodality

Relying solely on summary statistics (mean and std) is mathematically dangerous. Radically different datasets can exhibit identical summary statistics:

%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
    RAW["Raw Production Telemetry<br/>1,000,000 Request Latencies"]

    subgraph Deception ["⚠️ The Summary Statistic Trap"]
        MEAN["Mean = 125 ms | Std = 45 ms<br/>(Hides the real truth!)"]
    end

    subgraph Reality ["🔍 Statistical Distribution Reality"]
        BIMODAL["Bimodal Mixture Distribution<br/>Cluster A (Healthy Cache): 15 ms<br/>Cluster B (Lock Contention): 450 ms"]
    end

    RAW --> Deception
    RAW --> Reality

Why Naive Histograms Lie:

A standard histogram groups continuous values into arbitrary discrete bins (e.g., 20 bins). Choosing slightly different bin widths completely alters the perceived shape of the distribution.

The solution is the Empirical Cumulative Distribution Function (ECDF):

Fn(t) = 1/n · ∑i=1..n 𝟏(xi ≤ t)

An ECDF plots every single data point along the percentile axis (0.0 → 1.0), directly revealing exact percentiles (p50, p95, p99) without arbitrary binning artifacts.


2. Robust Outlier Detection: IQR vs. Z-Score

Parametric methods like the Z-Score (Z = (x - μ) / σ) assume data follows a Gaussian (normal) bell curve. When severe outliers exist, they distort the mean (μ) and artificially inflate the standard deviation (σ), blinding the Z-score to the anomalies!

The Interquartile Range (IQR) is completely non-parametric and resistant to extreme values:

%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
    Q1["25th Percentile (Q1)"]
    MED["50th Percentile (Median)"]
    Q3["75th Percentile (Q3)"]
    IQR["IQR = Q3 - Q1<br/>(Middle 50% of healthy observations)"]

    LOWER["Lower Outer Fence<br/>Q1 - 1.5 × IQR"]
    UPPER["Upper Outer Fence<br/>Q3 + 1.5 × IQR"]

    Q1 --> IQR
    Q3 --> IQR
    IQR --> LOWER
    IQR --> UPPER

Any data point falling beyond [Q1 - 1.5 × IQR, Q3 + 1.5 × IQR] is classified as an empirical outlier.


3. Detecting Feature Redundancy: VIF & Rank Correlation

When multiple features measure essentially the same underlying phenomenon (e.g., cpu_user_pct, cpu_system_pct, and cpu_total_pct), machine learning models experience multicollinearity: coefficient estimates oscillate wildly, and feature importance interpretations become meaningless.

3.1. Pearson (r) vs. Spearman (ρ)

  • Pearson Correlation: Measures strictly linear relationships. Susceptible to outliers.
  • Spearman Rank Correlation: Evaluates whether two variables move monotonically together, regardless of linearity:

ρ = 1 - (6 · ∑ di2) / (n · (n2 - 1))

3.2. Variance Inflation Factor (VIF)

The Variance Inflation Factor regresses each feature against all other features:

VIFj = 1 / (1 - Rj2)

  • VIF = 1: Completely independent.
  • VIF > 5: Severe collinearity. One of the correlated features should be dropped.

4. Production Telemetry Profiling Lab

Deploy this comprehensive diagnostic pipeline to evaluate real-world infrastructure metrics:

#!/usr/bin/env python3
# File: /opt/ds-ops/eda_diagnostics.py
import numpy as np
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor

# 1. Generate Realistic Heterogeneous Server Telemetry
np.random.seed(42)
n_records = 250_000

# Bimodal latency: 90% fast cache hits + 10% slow database lock stalls
latencies = np.concatenate([
    np.random.exponential(scale=12.0, size=int(n_records * 0.9)),
    np.random.normal(loc=350.0, scale=40.0, size=int(n_records * 0.1))
])

cpu_util = np.random.uniform(10.0, 95.0, size=n_records)
# Collinear feature: load_avg is heavily dependent on cpu_util
load_avg = (cpu_util * 0.15) + np.random.normal(0, 0.5, size=n_records)
network_rx_mb = np.random.gamma(shape=2.0, scale=15.0, size=n_records)

df = pd.DataFrame({
    "latency_ms": latencies,
    "cpu_util": cpu_util,
    "load_avg": load_avg,
    "network_rx_mb": network_rx_mb
})

print("=== 1. Non-Parametric Quantile Distribution ===")
quantiles = [0.25, 0.50, 0.75, 0.90, 0.95, 0.99]
print(df.quantile(quantiles).T)

print("\n=== 2. IQR Outlier Isolation (latency_ms) ===")
q25, q75 = df["latency_ms"].quantile(0.25), df["latency_ms"].quantile(0.75)
iqr = q75 - q25
upper_bound = q75 + (1.5 * iqr)
outliers = df[df["latency_ms"] > upper_bound]
print(f"IQR: {iqr:.2f} ms | Upper Fence: {upper_bound:.2f} ms")
print(f"Isolated {len(outliers):,} outliers ({len(outliers)/len(df)*100:.2f}%)")

print("\n=== 3. Spearman Monotonic Correlation Matrix ===")
print(df.corr(method="spearman").round(3))

print("\n=== 4. Multicollinearity Diagnostics (Variance Inflation Factor) ===")
# VIF requires standard features with constant intercept
features = df[["cpu_util", "load_avg", "network_rx_mb"]]
vif_data = pd.DataFrame({
    "feature": features.columns,
    "VIF": [variance_inflation_factor(features.values, i) for i in range(features.shape[1])]
})
print(vif_data.sort_values(by="VIF", ascending=False))

Typical diagnostic output:

=== 4. Multicollinearity Diagnostics (Variance Inflation Factor) ===
         feature       VIF
0       cpu_util  18.42104   <-- SEVERE COLLINEARITY (Drop one!)
1       load_avg  17.98101   <-- SEVERE COLLINEARITY (Drop one!)
2  network_rx_mb   2.14012   <-- Healthy

By identifying high VIF values during EDA, engineers eliminate redundant features before model training, drastically boosting estimator stability.