Menu

ClinicalLive Code Editor
152 researchers ran this analysis this month

Bland-Altman Plot in Python

Technique overview

Assess agreement between two measurement methods with bias, limits of agreement, and proportional bias diagnostics.

A Bland-Altman plot evaluates agreement between two measurement methods by plotting the difference between methods against their mean. Correlation alone is not enough for method comparison because two methods can correlate strongly while still having clinically unacceptable bias. Bland-Altman analysis shows the average bias, the 95% limits of agreement, outliers, and whether the bias changes across the measurement range.

Key points

  • Assess agreement between two measurement methods with bias, limits of agreement, and proportional bias diagnostics.
  • A Bland-Altman plot evaluates agreement between two measurement methods by plotting the difference between methods against their mean.
  • Correlation alone is not enough for method comparison because two methods can correlate strongly while still having clinically unacceptable bias.
  • Bland-Altman analysis shows the average bias, the 95% limits of agreement, outliers, and whether the bias changes across the measurement range.
numpymatplotlibscipy

Example Visualization

Review the example first, then use the live editor below to run and customize the full workflow.

Mathematical Foundation

A Bland-Altman plot evaluates agreement between two measurement methods by plotting the difference between methods against their mean.

bias = mean(A - B); limits = bias +/- 1.96 * SD(A - B)

Equation

bias = mean(A - B); limits = bias +/- 1.96 * SD(A - B)

Parameter breakdown

A and BPaired measurements from two methods
meanAverage of the two methods for each sample
differenceMethod A minus method B
biasMean difference across pairs
limits of agreementExpected range for most differences

When to use this technique

Use Bland-Altman analysis when validating a new instrument, assay, reader, or algorithm against a reference method.

Apply This Technique Now

Run this analysis workflow with AI in seconds. Use the prepared technique prompt or bring your own dataset.

View example prompt
Example AI Prompt

"Create a Bland-Altman plot comparing my two measurement methods, annotate the mean bias and limits of agreement, and flag any outlier points"

How to apply this technique in 30 seconds

1

Upload Data

Upload your CSV or Excel file in Analyze and keep your column names as-is.

2

Generate

Run the example prompt and let AI generate this technique automatically.

3

Refine and Export

Adjust code or prompt, then export publication-ready figures.

Implementation Code

The core data processing logic. Copy this block and replace the sample data with your measurements.

import numpy as np
from scipy import stats

np.random.seed(21)
reference = np.linspace(20, 120, 45) + np.random.normal(0, 4, 45)
new_method = reference + 2.5 + 0.04 * reference + np.random.normal(0, 6, 45)

mean_values = (reference + new_method) / 2
diff = new_method - reference
bias = np.mean(diff)
sd_diff = np.std(diff, ddof=1)
loa_low = bias - 1.96 * sd_diff
loa_high = bias + 1.96 * sd_diff
slope, intercept, r, p_prop, _ = stats.linregress(mean_values, diff)

print(f"Bias: {bias:.2f}")
print(f"95% limits of agreement: {loa_low:.2f} to {loa_high:.2f}")
print(f"Proportional bias p-value: {p_prop:.4f}")

Visualization Code

Complete matplotlib code for a publication-ready figure. Copy, paste into your notebook, and adjust labels to match your data.

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

np.random.seed(21)
reference = np.linspace(20, 120, 45) + np.random.normal(0, 4, 45)
new_method = reference + 2.5 + 0.04 * reference + np.random.normal(0, 6, 45)

mean_values = (reference + new_method) / 2
diff = new_method - reference
bias = np.mean(diff)
sd = np.std(diff, ddof=1)
loa_low, loa_high = bias - 1.96 * sd, bias + 1.96 * sd
slope, intercept, _, p_prop, _ = stats.linregress(mean_values, diff)
x_line = np.linspace(mean_values.min(), mean_values.max(), 100)

fig, ax = plt.subplots(figsize=(7, 5))
ax.scatter(mean_values, diff, color="#111111", s=30, alpha=0.75)
ax.axhline(bias, color="#9240ff", lw=2, label=f"Bias = {bias:.2f}")
ax.axhline(loa_high, color="#888888", lw=1.4, ls="--", label=f"+1.96 SD = {loa_high:.2f}")
ax.axhline(loa_low, color="#888888", lw=1.4, ls="--", label=f"-1.96 SD = {loa_low:.2f}")
ax.plot(x_line, intercept + slope * x_line, color="#e8a020", lw=1.5,
        label=f"Proportional bias p = {p_prop:.3f}")
ax.set_xlabel("Mean of Methods")
ax.set_ylabel("New Method - Reference")
ax.set_title("Bland-Altman Agreement Plot")
ax.legend(frameon=False, fontsize=9)
ax.spines[["top", "right"]].set_visible(False)
plt.tight_layout()
plt.savefig("bland_altman_plot.png", dpi=300, bbox_inches="tight")
plt.show()

Percent Difference Bland-Altman Plot

When measurement error scales with magnitude, plot percent difference instead of absolute difference.

percent_diff = 100 * (new_method - reference) / mean_values
percent_bias = np.mean(percent_diff)
percent_limits = percent_bias + np.array([-1.96, 1.96]) * np.std(percent_diff, ddof=1)
print(f"Percent bias: {percent_bias:.2f}%")
print(f"Percent limits: {percent_limits[0]:.2f}% to {percent_limits[1]:.2f}%")

Common Errors and How to Fix Them

Using correlation as evidence of agreement

Why: Correlation measures association, not interchangeability.

Fix: Report bias and limits of agreement, then judge whether those limits are acceptable for the use case.

Limits of agreement are too wide but called acceptable

Why: Statistical limits must be interpreted against clinical or analytical tolerances.

Fix: Define acceptable agreement before analysis and compare the limits to that threshold.

Proportional bias is ignored

Why: Differences may increase with measurement magnitude.

Fix: Regress differences against means and consider percent differences or transformation.

Frequently Asked Questions

Apply Bland-Altman Plot in Python to Your Data

Upload your dataset and Plotivy generates the Python code, runs the analysis, and produces a publication-ready figure.

Generate Code for This Technique

Python Libraries

numpymatplotlibscipy

Quick Info

Domain
Clinical
Typical Audience
Clinical researchers, diagnostic scientists, and method comparison studies evaluating agreement between instruments or assays

Related Chart Guides

Apply to your data

Upload a dataset and get Python code instantly

Get Started Free