TEC-DATA85-05 · Lesson 6 · 11 clock hours · lab
Outlier Detection and Treatment
Objective. Students will detect numeric outliers using IQR fences, z-scores, and boxplot inspection, then apply a documented treatment (removal, Winsorization, or flagging) that is appropriate for the stated analysis goal.
⚠ Pending professional review
This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.
VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.
What Is an Outlier?
An outlier is an observation that lies an unusual distance from other values in a dataset. Outliers are not automatically errors — they may be genuine extreme values, data-entry mistakes, or signals of exactly the event you are trying to detect. Because outliers can distort means, standard deviations, regression slopes, and machine-learning model weights, you must decide what to do with them before analysis — and document every decision.
Method 1: The IQR Fence Rule
The interquartile range (IQR) measures the spread of the middle 50 percent of a distribution.
1. Compute Q1 (25th percentile) and Q3 (75th percentile) for the column.
2. IQR = Q3 − Q1
3. Lower fence = Q1 − 1.5 × IQR
4. Upper fence = Q3 + 1.5 × IQR
Any value below the lower fence or above the upper fence is flagged as a mild outlier. Multiplying by 3.0 instead of 1.5 gives the "extreme outlier" fences. This rule is nonparametric — it makes no assumption about the distribution shape — and it is the same rule seaborn uses when drawing a boxplot's whiskers.
In pandas:
```python
Q1 = df['salary'].quantile(0.25)
Q3 = df['salary'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df['salary'] < lower) | (df['salary'] > upper)]
```
Method 2: Z-Scores
A z-score expresses how many standard deviations a value sits from the column mean. The formula is:
> z = (x − mean) / standard deviation
Values with |z| > 3 are commonly flagged as outliers in normally distributed data. The z-score method is sensitive to the very outliers it is trying to detect because extreme values inflate the mean and standard deviation. For that reason, use it alongside the IQR method, not instead of it.
In pandas/numpy:
```python
from scipy import stats
df['salary_z'] = stats.zscore(df['salary'])
outliers_z = df[df['salary_z'].abs() > 3]
```
Method 3: Boxplot Inspection
A seaborn boxplot draws the box from Q1 to Q3, a line at the median, whiskers at the fences, and individual dots for values beyond the fences. Visual inspection lets you see the count and distribution of outliers at a glance. Always produce boxplots before and after any treatment so reviewers can verify your work.
```python
import seaborn as sns, matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
sns.boxplot(y=df['salary'], ax=axes[0]).set_title('Before – n outliers=12')
sns.boxplot(y=df_clean['salary'], ax=axes[1]).set_title('After removal – n outliers=0')
plt.tight_layout()
```
Annotate each plot with the count of affected records so any reader can audit your choices.
Choosing a Treatment
The right treatment depends on the analysis goal, not just the data.
| Goal | Recommended treatment | Reasoning |
|---|---|---|
| Estimate a population mean (e.g., average city salary) | Remove or Winsorize | Extreme values pull the mean away from the typical worker |
| Detect fraud or anomalies | Flag and retain | The outlier is the signal; removing it destroys evidence |
| Build a predictive model | Investigate first, then decide | Could be noise or a rare but real pattern |
Removal deletes the flagged rows. Document how many rows were removed and confirm the remaining dataset is still large enough to support your analysis.
Flagging adds a boolean column (`is_outlier = True/False`) and keeps the row. Downstream analysis can then include or exclude outliers as needed.
Winsorization caps values at the fence boundaries rather than removing them. The row count stays the same, but extreme values are pulled in to the fence. This preserves sample size while limiting distortion.
```python
from scipy.stats.mstats import winsorize
import numpy as np
df['salary_w'] = winsorize(df['salary'], limits=[0.05, 0.05])
```
`limits=[0.05, 0.05]` caps the bottom 5 percent and the top 5 percent at their respective 5th- and 95th-percentile values. Adjust the limits to match the actual fence positions in your data.
Comparing Before and After
After any treatment, produce a summary table of mean, median, and standard deviation before and after. A well-executed Winsorization typically:
- Lowers the mean slightly if there were high outliers
- Leaves the median nearly unchanged (the median is already resistant to outliers)
- Reduces the standard deviation
If the median changes substantially, investigate — you may have over-Winsorized.
Data Safety and Documentation Standards
Data cleaning is irreversible if you overwrite the original file. Always work on a copy of the dataset and keep the raw CSV untouched. Use version control (Git) or clearly named file versions (`salary_raw.csv`, `salary_clean_v1.csv`). In a professional setting, every outlier treatment decision should be recorded in a data-cleaning log or notebook markdown cell, stating the method used, the threshold applied, the number of records affected, and the business reason for the choice. This is an auditable record that protects you and your organization if results are questioned later.
Key terms8
OutlierAn observation that lies an unusually large distance from the bulk of values in a dataset; may represent error, natural variation, or a meaningful event depending on context.
Interquartile Range (IQR)The difference between the 75th percentile (Q3) and the 25th percentile (Q1) of a distribution; measures the spread of the middle 50 percent of data and is used to set outlier fences.
IQR FenceA threshold computed as Q1 − 1.5×IQR (lower) or Q3 + 1.5×IQR (upper); values outside these boundaries are flagged as mild outliers.
Z-ScoreA standardized measure of how many standard deviations a value falls from the column mean; values with an absolute z-score greater than 3 are commonly flagged as outliers.
WinsorizationAn outlier treatment that replaces extreme values with the value at a specified percentile boundary rather than removing rows, preserving sample size while limiting distortion.
FlaggingAn outlier treatment that adds a boolean indicator column marking suspicious records without deleting them, allowing downstream analysis to include or exclude them as needed.
BoxplotA graphical summary showing the median, Q1, Q3, IQR fences (whiskers), and individual outlier points; used for visual outlier detection and comparison before and after treatment.
Treatment decisionThe documented choice of how to handle detected outliers — removal, Winsorization, or flagging — made based on the stated analysis goal rather than the data alone.
Worked examples4
1. A salary column has Q1 = $42,000 and Q3 = $78,000. Compute the IQR and both 1.5×IQR fences. Is a salary of $155,000 an outlier by this rule?
- Compute IQR: IQR = Q3 − Q1 = 78,000 − 42,000 = 36,000
- Compute 1.5 × IQR: 1.5 × 36,000 = 54,000
- Lower fence = Q1 − 54,000 = 42,000 − 54,000 = −12,000 (no practical lower outliers for salary)
- Upper fence = Q3 + 54,000 = 78,000 + 54,000 = 132,000
- Check $155,000: 155,000 > 132,000, so yes, it lies beyond the upper fence.
Answer: Upper fence = $132,000. A salary of $155,000 exceeds this threshold and is flagged as an outlier by the 1.5×IQR rule.
2. A salary value is $198,000. The column mean is $65,000 and the standard deviation is $22,000. Compute the z-score and determine whether it is an outlier using the common threshold.
- Apply the z-score formula: z = (x − mean) / std
- z = (198,000 − 65,000) / 22,000
- z = 133,000 / 22,000
- z ≈ 6.05
- Since |6.05| > 3, the value is flagged as an outlier.
Answer: z ≈ 6.05. Because this exceeds the threshold of 3, $198,000 is an outlier by the z-score method.
3. Before Winsorization a salary column has mean = $74,200, median = $68,500, and std = $31,400. After applying winsorize with limits=[0.05, 0.05] the values become mean = $69,800, median = $68,300, and std = $18,600. By how many dollars did the mean change, and which statistic changed the least? What does this pattern indicate?
- Change in mean: 74,200 − 69,800 = 4,400 (mean decreased by $4,400)
- Change in median: 68,500 − 68,300 = 200 (median decreased by only $200)
- Change in std: 31,400 − 18,600 = 12,800 (std decreased by $12,800)
- The median changed the least (by $200), consistent with it being a resistant statistic.
- The large drop in std shows the high-end outliers that were capped were inflating spread significantly.
Answer: The mean fell by $4,400, the standard deviation fell by $12,800, and the median changed by only $200. This pattern confirms Winsorization worked as expected: it reduced distortion from extreme high values while the resistant median remained nearly stable.
4. A dataset has 500 salary rows. The IQR rule flags 18 rows as outliers. A colleague proposes removing all 18. The analysis goal is to calculate the fraud-risk score for the top earners. Should you remove, Winsorize, or flag? Justify with numbers.
- Identify the analysis goal: detect wage fraud among top earners — the outliers are the primary subjects of interest.
- If you remove all 18 flagged rows, you eliminate the very records most likely to represent fraud.
- Removal rate: 18/500 = 3.6% of rows — small enough that removal would not hurt sample size for a mean calculation, but catastrophic for a fraud-detection goal.
- Winsorization caps values rather than removes them, but distorts the magnitudes that a fraud analyst needs to see.
- Flagging adds a boolean column (is_outlier=True) to those 18 rows and retains them, allowing a fraud analyst to prioritize them for review.
Answer: Flag and retain. Removing or Winsorizing destroys the signal. The 18 outlier rows (3.6% of data) should receive an is_outlier flag so they can be investigated, not discarded.
The math in this lesson1
Learners compute IQR fences at 1.5 × IQR and z-scores to flag outliers.
S-ID.3
In class: Students compute IQR fences and z-scores for five numeric columns in a salary dataset; they produce side-by-side boxplots before and after treatment using seaborn and annotate each plot with the number of records affected. · Case-comparison activity: instructor presents two analysis scenarios (calculating city-wide average salary vs. detecting wage fraud); students argue in writing why the same outlier should be treated differently depending on the goal—removal for the first, retention and flagging for the second. · Students apply scipy.stats.mstats.winsorize to a column with extreme high values, then compare mean, median, and standard deviation before and after Winsorization in a summary table and write a one-paragraph interpretation.
Materials: Salary dataset CSV, Jupyter Lab, pandas, numpy, scipy, seaborn, matplotlib
Check: Submitted notebook must include correct IQR/z-score calculations (verified against answer key), annotated plots for all five columns, and written case-comparison argument; pass at 75 % on a four-criteria rubric (calculation accuracy, plot quality, written justification, summary table).
Practice check8
Answer each question, then check it. Nothing is recorded; this is your own practice.
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.