xbe.at

Data visualisation

Outlier Detection in Python Visualizing and Analyzing Anomalies

10 min read, 16 sections

Contents
  1. Understanding Outliers in Python
  2. Identifying Outliers: Z-Score Method
  3. Visualizing Outliers: Box Plot
  4. Interquartile Range (IQR) Method
  5. Handling Outliers: Removal
  6. Handling Outliers: Winsorization
  7. Handling Outliers: Transformation
  8. Real-Life Example: Weather Data Analysis
  9. Real-Life Example: Quality Control in Manufacturing
  10. Outlier Detection in Time Series Data
  11. Robust Statistics for Outlier Handling
  12. Machine Learning and Outliers: Impact on Model Performance
  13. Outlier Detection in High-Dimensional Data: t-SNE Visualization
  14. Outlier Detection in Clustering: DBSCAN
  15. Dealing with Outliers in Time Series Forecasting
  16. Additional Resources

Understanding Outliers in Python

Outliers are data points that significantly differ from other observations in a dataset. They can greatly impact statistical analyses and machine learning models. In this presentation, we'll explore how to identify, visualize, and handle outliers using Python.

import numpy as np
import matplotlib.pyplot as plt

# Generate sample data with outliers
np.random.seed(42)
data = np.random.normal(0, 1, 1000)
outliers = np.random.uniform(10, 15, 5)
data = np.concatenate([data, outliers])

# Plot histogram
plt.figure(figsize=(10, 6))
plt.hist(data, bins=30, edgecolor='black')
plt.title('Histogram of Data with Outliers')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()

Identifying Outliers: Z-Score Method

The Z-score method is a common approach to detect outliers. It measures how many standard deviations away a data point is from the mean. Typically, data points with a Z-score greater than 3 or less than -3 are considered outliers.

from scipy import stats

def identify_outliers_zscore(data, threshold=3):
    z_scores = np.abs(stats.zscore(data))
    return np.where(z_scores > threshold)[0]

outliers_indices = identify_outliers_zscore(data)
print(f"Outliers found at indices: {outliers_indices}")
print(f"Outlier values: {data[outliers_indices]}")

Visualizing Outliers: Box Plot

Box plots are excellent for visualizing the distribution of data and identifying outliers. They display the median, quartiles, and potential outliers in a single graph.

plt.figure(figsize=(10, 6))
plt.boxplot(data, vert=False)
plt.title('Box Plot of Data with Outliers')
plt.xlabel('Value')
plt.show()

Interquartile Range (IQR) Method

The IQR method is another popular technique for identifying outliers. It uses the interquartile range to determine the boundaries beyond which data points are considered outliers.

def identify_outliers_iqr(data):
    Q1 = np.percentile(data, 25)
    Q3 = np.percentile(data, 75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return np.where((data < lower_bound) | (data > upper_bound))[0]

outliers_iqr = identify_outliers_iqr(data)
print(f"Outliers found using IQR method: {outliers_iqr}")
print(f"Outlier values: {data[outliers_iqr]}")

Handling Outliers: Removal

One way to handle outliers is to remove them from the dataset. This approach should be used cautiously, as it can lead to loss of important information.

def remove_outliers(data, outlier_indices):
    return np.delete(data, outlier_indices)

data_without_outliers = remove_outliers(data, outliers_indices)

plt.figure(figsize=(10, 6))
plt.hist(data_without_outliers, bins=30, edgecolor='black')
plt.title('Histogram of Data After Removing Outliers')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()

Handling Outliers: Winsorization

Winsorization is a technique where extreme values are replaced with less extreme values. This method preserves the data points while reducing their impact on analyses.

from scipy.stats.mstats import winsorize

def winsorize_outliers(data, limits):
    return winsorize(data, limits=limits)

winsorized_data = winsorize_outliers(data, limits=[0.01, 0.01])

plt.figure(figsize=(10, 6))
plt.hist(winsorized_data, bins=30, edgecolor='black')
plt.title('Histogram of Winsorized Data')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()

Handling Outliers: Transformation

Data transformation can help reduce the impact of outliers. Common transformations include logarithmic, square root, and Box-Cox transformations.

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import boxcox

# Generate sample data with outliers
np.random.seed(42)
data = np.random.lognormal(0, 1, 1000)

# Apply logarithmic transformation
log_data = np.log1p(data)

# Apply Box-Cox transformation
boxcox_data, lambda_param = boxcox(data)

# Plot original and transformed data
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))

ax1.hist(data, bins=30, edgecolor='black')
ax1.set_title('Original Data')

ax2.hist(log_data, bins=30, edgecolor='black')
ax2.set_title('Log-transformed Data')

ax3.hist(boxcox_data, bins=30, edgecolor='black')
ax3.set_title('Box-Cox Transformed Data')

plt.tight_layout()
plt.show()

Real-Life Example: Weather Data Analysis

Let's analyze temperature data to identify unusual weather patterns. We'll use daily temperature readings from a weather station and identify days with extreme temperatures.

import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

# Generate sample weather data
np.random.seed(42)
dates = pd.date_range(start='2023-01-01', end='2023-12-31')
temperatures = np.random.normal(20, 5, len(dates))
temperatures += 10 * np.sin(np.arange(len(dates)) * 2 * np.pi / 365)  # Seasonal pattern
temperatures[150:155] += 15  # Add some outliers (heat wave)

weather_data = pd.DataFrame({'date': dates, 'temperature': temperatures})

# Identify outliers using Z-score
z_scores = np.abs(stats.zscore(weather_data['temperature']))
outliers = weather_data[z_scores > 3]

# Plot the data
plt.figure(figsize=(12, 6))
plt.plot(weather_data['date'], weather_data['temperature'], label='Temperature')
plt.scatter(outliers['date'], outliers['temperature'], color='red', label='Outliers')
plt.title('Daily Temperatures with Outliers')
plt.xlabel('Date')
plt.ylabel('Temperature (°C)')
plt.legend()
plt.show()

print(f"Number of outliers detected: {len(outliers)}")
print("Outlier dates and temperatures:")
print(outliers)

Real-Life Example: Quality Control in Manufacturing

In a manufacturing process, we'll use outlier detection to identify potentially faulty products based on their measurements.

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Generate sample product measurement data
np.random.seed(42)
measurements = np.random.normal(100, 2, 1000)
faulty_products = np.random.uniform(90, 95, 10)
measurements = np.concatenate([measurements, faulty_products])

# Identify outliers using IQR method
Q1 = np.percentile(measurements, 25)
Q3 = np.percentile(measurements, 75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = measurements[(measurements < lower_bound) | (measurements > upper_bound)]

# Plot the data
plt.figure(figsize=(12, 6))
plt.hist(measurements, bins=50, edgecolor='black', alpha=0.7)
plt.axvline(lower_bound, color='red', linestyle='dashed', label='Lower bound')
plt.axvline(upper_bound, color='red', linestyle='dashed', label='Upper bound')
plt.title('Product Measurements with Outliers')
plt.xlabel('Measurement')
plt.ylabel('Frequency')
plt.legend()
plt.show()

print(f"Number of potential faulty products: {len(outliers)}")
print(f"Faulty product measurements: {outliers}")

Outlier Detection in Time Series Data

Time series data often requires special consideration when detecting outliers. We'll use the seasonal decomposition method to identify anomalies in a time series.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose

# Generate sample time series data
np.random.seed(42)
date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
trend = np.linspace(0, 10, len(date_rng))
seasonality = 5 * np.sin(np.arange(len(date_rng)) * 2 * np.pi / 365)
noise = np.random.normal(0, 1, len(date_rng))
ts_data = trend + seasonality + noise

# Add some outliers
ts_data[50] += 20
ts_data[150] -= 15
ts_data[250] += 25

time_series = pd.Series(ts_data, index=date_rng)

# Perform seasonal decomposition
result = seasonal_decompose(time_series, model='additive', period=365)

# Calculate residuals and identify outliers
residuals = result.resid
threshold = 3 * np.std(residuals)
outliers = time_series[np.abs(residuals) > threshold]

# Plot the results
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

ax1.plot(time_series, label='Original')
ax1.scatter(outliers.index, outliers, color='red', label='Outliers')
ax1.set_title('Time Series with Outliers')
ax1.legend()

ax2.plot(residuals, label='Residuals')
ax2.axhline(y=threshold, color='r', linestyle='--', label='Threshold')
ax2.axhline(y=-threshold, color='r', linestyle='--')
ax2.set_title('Residuals with Threshold')
ax2.legend()

plt.tight_layout()
plt.show()

print(f"Number of outliers detected: {len(outliers)}")
print("Outlier dates and values:")
print(outliers)

Robust Statistics for Outlier Handling

Robust statistics are less sensitive to outliers. We'll compare mean and median as measures of central tendency, and standard deviation with median absolute deviation (MAD) as measures of spread.

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Generate sample data with outliers
np.random.seed(42)
data = np.random.normal(0, 1, 1000)
outliers = np.random.uniform(10, 15, 5)
data = np.concatenate([data, outliers])

# Calculate statistics
mean = np.mean(data)
median = np.median(data)
std_dev = np.std(data)
mad = stats.median_abs_deviation(data)

# Plot histogram with statistics
plt.figure(figsize=(12, 6))
plt.hist(data, bins=50, edgecolor='black', alpha=0.7)
plt.axvline(mean, color='red', linestyle='dashed', label=f'Mean: {mean:.2f}')
plt.axvline(median, color='green', linestyle='dashed', label=f'Median: {median:.2f}')
plt.axvline(mean + std_dev, color='orange', linestyle=':', label=f'Mean + StdDev: {mean + std_dev:.2f}')
plt.axvline(median + mad, color='purple', linestyle=':', label=f'Median + MAD: {median + mad:.2f}')
plt.title('Comparison of Robust and Non-Robust Statistics')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.legend()
plt.show()

print(f"Mean: {mean:.2f}")
print(f"Median: {median:.2f}")
print(f"Standard Deviation: {std_dev:.2f}")
print(f"Median Absolute Deviation: {mad:.2f}")

Machine Learning and Outliers: Impact on Model Performance

Outliers can significantly affect machine learning models. We'll demonstrate this by comparing the performance of a linear regression model with and without outliers.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# Generate sample data with outliers
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 2 * X + 1 + np.random.normal(0, 1, X.shape)
outliers_X = np.array([[2], [8]])
outliers_y = np.array([15, -5])

# Combine regular data and outliers
X_with_outliers = np.vstack((X, outliers_X))
y_with_outliers = np.concatenate((y, outliers_y))

# Fit models
model_without_outliers = LinearRegression().fit(X, y)
model_with_outliers = LinearRegression().fit(X_with_outliers, y_with_outliers)

# Calculate MSE
mse_without_outliers = mean_squared_error(y, model_without_outliers.predict(X))
mse_with_outliers = mean_squared_error(y_with_outliers, model_with_outliers.predict(X_with_outliers))

# Plot results
plt.figure(figsize=(12, 6))
plt.scatter(X, y, color='blue', label='Regular data')
plt.scatter(outliers_X, outliers_y, color='red', label='Outliers')
plt.plot(X, model_without_outliers.predict(X), color='green', label='Model without outliers')
plt.plot(X, model_with_outliers.predict(X), color='orange', label='Model with outliers')
plt.title('Impact of Outliers on Linear Regression')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()

print(f"MSE without outliers: {mse_without_outliers:.4f}")
print(f"MSE with outliers: {mse_with_outliers:.4f}")

Outlier Detection in High-Dimensional Data: t-SNE Visualization

For high-dimensional data, we can use dimensionality reduction techniques like t-SNE to visualize outliers. We'll demonstrate this using a synthetic dataset.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from sklearn.datasets import make_blobs

# Generate high-dimensional data with outliers
np.random.seed(42)
X, _ = make_blobs(n_samples=1000, n_features=50, centers=5, cluster_std=2.0)
outliers = np.random.uniform(-15, 15, (10, 50))
X_with_outliers = np.vstack((X, outliers))

# Apply t-SNE
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X_with_outliers)

# Plot t-SNE results
plt.figure(figsize=(10, 8))
plt.scatter(X_tsne[:-10, 0], X_tsne[:-10, 1], alpha=0.5, label='Regular data')
plt.scatter(X_tsne[-10:, 0], X_tsne[-10:, 1], color='red', label='Outliers')
plt.title('t-SNE Visualization of High-Dimensional Data with Outliers')
plt.xlabel('t-SNE feature 1')
plt.ylabel('t-SNE feature 2')
plt.legend()
plt.show()

Outlier Detection in Clustering: DBSCAN

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) is a clustering algorithm that can effectively identify outliers in datasets with arbitrary shapes.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons

# Generate sample data
X, _ = make_moons(n_samples=300, noise=0.05, random_state=42)
X = np.concatenate([X, np.random.uniform(-1, 2, (10, 2))])  # Add outliers

# Apply DBSCAN
dbscan = DBSCAN(eps=0.2, min_samples=5)
labels = dbscan.fit_predict(X)

# Plot results
plt.figure(figsize=(10, 8))
plt.scatter(X[labels != -1, 0], X[labels != -1, 1], c=labels[labels != -1], cmap='viridis')
plt.scatter(X[labels == -1, 0], X[labels == -1, 1], color='red', label='Outliers')
plt.title('DBSCAN Clustering with Outlier Detection')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
plt.show()

print(f"Number of outliers detected: {sum(labels == -1)}")

Dealing with Outliers in Time Series Forecasting

When forecasting time series data, outliers can significantly impact model performance. We'll demonstrate how to handle outliers in a simple forecasting scenario using a moving average approach.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Generate sample time series data with outliers
np.random.seed(42)
date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
values = np.sin(np.arange(len(date_rng)) * 2 * np.pi / 365) + np.random.normal(0, 0.1, len(date_rng))
outliers = np.random.choice(len(date_rng), 10, replace=False)
values[outliers] += np.random.uniform(1, 2, 10) * np.random.choice([-1, 1], 10)

ts_data = pd.Series(values, index=date_rng)

# Function to replace outliers with moving average
def replace_outliers_ma(series, window=7, threshold=3):
    rolling_mean = series.rolling(window=window, center=True).mean()
    rolling_std = series.rolling(window=window, center=True).std()
    outliers = np.abs(series - rolling_mean) > (threshold * rolling_std)
    return series.where(~outliers, rolling_mean)

# Apply outlier replacement
ts_cleaned = replace_outliers_ma(ts_data)

# Plot results
plt.figure(figsize=(12, 6))
plt.plot(ts_data, label='Original', alpha=0.7)
plt.plot(ts_cleaned, label='Cleaned', linewidth=2)
plt.title('Time Series with Outlier Replacement')
plt.xlabel('Date')
plt.ylabel('Value')
plt.legend()
plt.show()

Additional Resources

For those interested in diving deeper into outlier detection and handling techniques, here are some valuable resources:

  1. "Outlier Analysis" by Charu C. Aggarwal (Springer, 2017)
  2. "Anomaly Detection: A Survey" by Chandola et al. (2009) - Available on ArXiv: https://arxiv.org/abs/0907.5118
  3. "A Comparative Evaluation of Unsupervised Anomaly Detection Algorithms for Multivariate Data" by Goldstein and Uchida (2016) - Available on ArXiv: https://arxiv.org/abs/1603.04052
  4. Scikit-learn documentation on Outlier Detection: https://scikit-learn.org/stable/modules/outlier_detection.html
  5. PyOD (Python Outlier Detection) library: https://github.com/yzhao062/pyod

These resources provide a mix of theoretical foundations and practical implementations for outlier detection and handling in various contexts.

More in Data visualisation

  1. Precision-Recall Plot Evaluating Classifier Performance5 min

    Precision and recall are fundamental metrics in binary classification problems. Precision measures the accuracy of positive predictions, while recall...

  2. Multi-Dimensional Data Visualization in Machine Learning with Python8 min

    Multi-dimensional data visualization is a critical aspect of machine learning that allows us to understand complex datasets with multiple features. It helps...

  3. Python Visualizations Waffle Charts, Word Clouds, and Regression Plots13 min

    Master Waffle Charts are a visually appealing alternative to pie charts, displaying data in a grid of squares. Each square represents a portion of the whole...

  4. Minesweeper AI Solver in Python with Matplotlib6 min

    Minesweeper is a classic game that involves uncovering a grid of tiles while avoiding hidden mines. Creating an AI to solve Minesweeper can be an exciting...

  5. Raincloud Plots Visualizing Data Distributions in Python12 min

    Raincloud plots are an innovative data visualization technique that combines aspects of box plots, violin plots, and scatter plots. They provide a...

  6. Matplotlib Subplot Mosaic A Flexible Alternative to subplots()12 min

    The plt.subplot\mosaic() method revolutionizes how we create complex subplot layouts in Matplotlib. Unlike traditional plt.subplots(), it allows defining...