2.4 Removing Outliers with Standard Deviation and IQR
Key Takeaways
- The IQR rule flags values outside $[Q1 - 1.5 \times IQR,\; Q3 + 1.5 \times IQR]$ and is non-parametric, so it holds on skewed data.
- The standard-deviation (Z-score) rule flags $|z| > 3$ but assumes approximate normality, and its mean and standard deviation are themselves distorted by the outliers being sought.
- Compute the fences in Spark with `percentile_approx` or `approxQuantile`, then filter with a boolean predicate — never collect the column to the driver.
- Removal is one option among several: trimming deletes rows, Winsorizing caps values at chosen percentiles, and an indicator column preserves the fact that a value was extreme.
- Tree-based models are invariant to feature outliers because splits depend on rank order, so outlier work matters most for linear, distance-based, and gradient-descent models.
2.4 Removing Outliers with Standard Deviation and IQR
In machine learning feature engineering, an outlier is an observation that deviates substantially from the overall distribution of the dataset. Outliers can arise from measurement errors, sensor failures, data entry typos, data corruption, or genuine rare real-world phenomena (e.g., high-net-worth individuals in wealth management or flash-crash volume spikes in financial trading).
Understanding the mathematical nature of outliers and their downstream impact on specific algorithms is a core competency tested on the Databricks Certified Machine Learning Associate exam.
Algorithm Sensitivity to Outliers
Machine learning algorithms exhibit vastly different degrees of sensitivity to extreme values. The decision to invest time in outlier detection and remediation depends entirely on the chosen model family:
| Algorithm Family | Sensitivity Level | Mathematical Rationale |
|---|---|---|
| Ordinary Least Squares (OLS) Linear Regression | High | OLS minimizes the sum of squared residuals ($\sum (y_i - \hat{y}_i)^2$). An extreme outlier exerts high leverage, pulling the fitted hyperplane toward itself and distorting slope coefficients for the rest of the dataset. |
| Regularized Linear Models (Ridge, Lasso, ElasticNet) | High | Although penalties shrink coefficients, the underlying loss function remains squared error, leaving the model vulnerable to outlier distortion. |
| Logistic Regression & Neural Networks | High | Gradient descent weight updates are proportional to the magnitude of feature values ($x_{ij}$). Unbounded outlier values cause explosive gradient steps or push sigmoid/softmax activations into saturation zones where gradients vanish. |
| Distance-Based Models (k-NN, K-Means, SVM with RBF) | High | Distances (e.g., Euclidean metric $\sqrt{\sum (x_{ia} - x_{ib})^2}$) are dominated by dimensions with extreme magnitudes, rendering nearest neighbor and cluster assignment calculations inaccurate. |
| Principal Component Analysis (PCA) | High | PCA maximizes variance ($\sigma^2$). A single extreme outlier can define the direction of the first principal component entirely by itself. |
| Tree-Based Models (Decision Trees, Random Forests, XGBoost, LightGBM) | Low (Robust / Invariant) | Tree split algorithms evaluate monotonic ordering of features rather than absolute magnitudes. A split at $x \le 50$ produces identical partitions regardless of whether the maximum value is $100$ or $1,000,000$. (Note: Outliers in continuous regression targets y can still affect tree leaf mean predictions, but feature x outliers do not). |
Mathematical Outlier Detection Methods
The Interquartile Range (IQR) Rule (Tukey's Fences)
The IQR rule is a robust, non-parametric method that makes no assumptions regarding the underlying probability distribution of the data. It is resistant to extreme skewness.
Observations falling outside $[\text{Lower Inner Fence}, \text{Upper Inner Fence}]$ are classified as mild outliers. Observations beyond $3.0 \times \text{IQR}$ are classified as extreme outliers.
# Calculating IQR Fences using PySpark percentile_approx
from pyspark.sql import functions as F
quantiles = df.select(
F.percentile_approx("annual_income", [0.25, 0.75], 10000).alias("q")
).collect()[0]["q"]
q1, q3 = quantiles[0], quantiles[1]
iqr = q3 - q1
lower_fence = q1 - 1.5 * iqr
upper_fence = q3 + 1.5 * iqr
print(f"Q1: {q1}, Q3: {q3}, IQR: {iqr}")
print(f"Valid Range: [{lower_fence}, {upper_fence}]")
# Flag outliers in PySpark
df_flagged = df.withColumn(
"is_income_outlier",
(F.col("annual_income") < lower_fence) | (F.col("annual_income") > upper_fence)
)
The Z-Score Method (Standard Deviation Rule)
The Z-score measures how many standard deviations ($\sigma$) an observation $x$ lies away from the arithmetic mean ($\mu$):
Under a standard Gaussian (normal) distribution:
- $68.27%$ of values lie within $|z| \le 1$
- $95.45%$ of values lie within $|z| \le 2$
- $99.73%$ of values lie within $|z| \le 3$
Threshold: An observation is flagged as an outlier if $|z| > 3.0$.
Exam Warning: The Z-score assumes the underlying data is normally distributed. Furthermore, the calculation of $\mu$ and $\sigma$ is itself distorted by extreme outliers (the masking effect). If data is non-normal or skewed, use the IQR method or the Median Absolute Deviation (MAD) rather than standard Z-scores.
Choosing Between the Two Rules
| IQR / Tukey fences | Standard deviation / Z-score | |
|---|---|---|
| Assumption | None — non-parametric | Approximately normal distribution |
| Statistics used | Q1, Q3 (rank-based) | Mean, standard deviation |
| Robustness | High — quartiles barely move when a few extreme points are added | Low — the outliers inflate the very $\sigma$ used to detect them (masking) |
| Typical threshold | 1.5 × IQR (mild), 3.0 × IQR (extreme) | $\lvert z \rvert > 3$ |
| Best for | Skewed features: income, spend, latency, counts | Symmetric, roughly Gaussian measurements |
On a right-skewed feature such as income, the Z-score rule flags almost nothing on the left and far too little on the right, because a handful of very large values has already pushed the mean up and the standard deviation out. The IQR rule is the safer default and is what Databricks material generally demonstrates.
Filtering in Spark, end to end
from pyspark.sql import functions as F
q1, q3 = df.approxQuantile("annual_income", [0.25, 0.75], 0.01)
iqr = q3 - q1
lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr
clean_df = df.filter((F.col("annual_income") >= lower) & (F.col("annual_income") <= upper))
# Standard-deviation alternative, computed in one distributed pass
stats = df.select(F.mean("annual_income").alias("mu"),
F.stddev("annual_income").alias("sigma")).first()
z_clean_df = df.filter(F.abs((F.col("annual_income") - stats["mu"]) / stats["sigma"]) <= 3)
Two implementation rules the exam rewards:
- Compute the thresholds on the training split only. Fences derived from the full dataset leak test-set distribution information into training, exactly as an imputer fitted on everything would.
- Never
collect()the column.approxQuantileand the aggregate functions run distributed; pulling millions of values to the driver to sort them is the wrong answer even when it is written in valid Python.
Outlier Remediation Strategies
Once outliers are detected, data scientists select an appropriate treatment strategy:
- Trimming / Filtering (Row Deletion):
- Approach: Drop rows containing outlier values:
df.filter((col("x") >= lower) & (col("x") <= upper)). - When to use: Obvious data corruption or recording errors where the observation is invalid.
- Risks: Can remove genuine rare events, reduce sample size, and introduce selection bias.
- Approach: Drop rows containing outlier values:
- Winsorization (Percentile Capping):
- Approach: Cap extreme values at predetermined lower and upper percentiles (e.g., 1st and 99th percentiles, or 5th and 95th percentiles).
- When to use: When the observation is valid and the row must be preserved, but extreme magnitudes would destabilize parametric models.
- PySpark implementation:
# Winsorize / Cap feature values at 1st and 99th percentiles p01, p99 = df.select( F.percentile_approx("transaction_amount", [0.01, 0.99], 10000).alias("p") ).collect()[0]["p"] df_capped = df.withColumn( "transaction_amount_capped", F.when(F.col("transaction_amount") < p01, p01) .when(F.col("transaction_amount") > p99, p99) .otherwise(F.col("transaction_amount")) )
- Outlier Indicator Feature Encoding:
- Approach: Create a binary indicator column ($1$ if outlier, $0$ otherwise) before capping or imputing.
- Benefit: Preserves the informational signal that an anomaly occurred while preventing numerical instability in the primary feature column.
A dataset contains an annual revenue feature with a first quartile (Q1) of $40,000 and a third quartile (Q3) of $100,000. Under Tukey's standard 1.5 * IQR rule, which revenue value represents the threshold above which observations are classified as high outliers?
Which machine learning algorithm is inherently robust to extreme feature outliers, such that applying Winsorization or log transformations to independent feature columns will NOT alter its split decisions?
A feature holding customer support-call durations is strongly right-skewed. A colleague proposes flagging outliers with the rule |z| > 3. Why is the IQR rule the better choice here?