In simple linear regression, independent, mean-zero measurement error in a predictor pulls the population slope toward zero. This is attenuation bias, or regression dilution. More observations improve precision but do not remove it.
Consider one clinic blood-pressure reading used to represent usual resting blood pressure. Temporary fluctuations and measurement noise can make the reading differ from that target.
In a hypothetical example, usual blood pressure has a between-person variance of 100 mmHg², and independent measurement error contributes 25 mmHg². Then:
Reliability = Var(true predictor) / [Var(true predictor) + Var(error)] = 100 / 125 = 0.80.
Under this model, 80% of recorded variance reflects differences in usual blood pressure. It does not mean 80% of readings are correct. These illustrative numbers are not findings from a blood-pressure study. In real research, repeated measurements or validation data help estimate reliability, which can differ across populations.
The simple regression slope is predictor–outcome covariance divided by predictor variance. Independent measurement noise increases the denominator without adding population covariance with the outcome. Under the classical error assumptions:
Recorded-predictor slope = true-predictor slope × reliability.
We checked this using synthetic data: X and outcome noise were independent standard normal variables, with Y = 1 + 2X + outcome noise. We recorded W = X + measurement noise, independent of both X and outcome noise, and fitted Y on W with an intercept.
Across 2,000 datasets of 1,000 observations each:
| Error SD | Reliability | Population slope | Average fitted slope |
|---|---|---|---|
| 0 | 1.00 | 2.00 | 1.999 |
| 0.5 | 0.80 | 1.60 | 1.600 |
| 1 | 0.50 | 1.00 | 1.001 |
| 2 | 0.20 | 0.40 | 0.401 |
Here Var(X) = 1, so reliability is 1/(1 + error SD²), known from the simulation design. A reliability of 0.50 halves the population slope. Individual samples fluctuate; not every estimate must shrink. The National Cancer Institute’s primer explains the measurement-error models behind this result.
This result concerns additive predictor error independent of the true predictor and outcome disturbance in simple linear regression. Normality is not essential. Outcome-dependent errors, correlated predictors, and nonlinear models need separate analysis; bias need not point toward zero.
Independent, mean-zero error added to the outcome alone leaves the population slope unchanged, though precision worsens. Neither result establishes causation.
Attenuation and regression to the mean are related but distinct. Both involve imperfect correlation, which measurement error can produce. Attenuation describes a regression slope pulled toward zero; regression to the mean describes how a group selected for extreme initial scores tends to have less-extreme scores on another imperfectly correlated measurement. Measurement error can contribute to both, but regression to the mean can also arise from real variation without measurement error.
Dividing a slope by reliability reverses this model’s population attenuation, but reliability estimates introduce uncertainty and may not transfer between settings. Alpha or omega is not automatically the appropriate correction factor: internal consistency may describe different errors from those affecting your predictor.
R and Python versions follow, each with fixed seed 20261018. The two languages use different random-number generators, so their draws differ, but both reproduce the table to within about 0.001. The Python version produced the exact figures shown. The full verification script additionally checked all 8,000 fits against matrix least squares and an exact sample-covariance identity. All simulated averages were within five Monte Carlo standard errors of their population targets.
R
set.seed(20261018) # fixed seed (R's generator, so draws differ from NumPy's)
noise_sds <- c(0, 0.5, 1, 2) # measurement-error SDs to compare
slopes <- replicate(2000, { # 2,000 simulated datasets
x <- rnorm(1000) # true predictor, Var(X) = 1
y <- 1 + 2 * x + rnorm(1000) # outcome: true slope = 2
u <- rnorm(1000) # one error draw, rescaled for each SD
sapply(noise_sds, function(s) {
w <- x + s * u # recorded predictor W = X + error
cov(w, y) / var(w) # OLS slope of Y on W (same as lm())
})
}) # result: 4 x 2000 matrix
reliability <- 1 / (1 + noise_sds^2) # Var(X) / [Var(X) + error variance]
data.frame(error_sd = noise_sds,
reliability = reliability,
population = 2 * reliability, # true slope x reliability
avg_fitted = round(rowMeans(slopes), 3)) # Monte Carlo average
Python (NumPy)
import numpy as np
rng = np.random.default_rng(20261018)
noise_sds = (0, 0.5, 1, 2)
estimates = {s: [] for s in noise_sds}
for _ in range(2000):
x = rng.normal(size=1000)
y = 1 + 2*x + rng.normal(size=1000)
u = rng.normal(size=1000)
for s in noise_sds:
w = x + s*u
wc, yc = w - w.mean(), y - y.mean()
estimates[s].append(wc @ yc / (wc @ wc))
for s in noise_sds:
reliability = 1 / (1 + s*s)
print(s, reliability, 2*reliability,
round(np.mean(estimates[s]), 3))
In the Python run, the average fitted slope at reliability 0.50 was 1.000991, with Monte Carlo standard error 0.000872. That describes uncertainty in the simulation average, not a single study’s regression standard error.
If you need to assess measurement quality before interpreting a regression, DASS supports researchers with analysis planning and review.
One email whenever we publish something new. No spam, unsubscribe anytime.
{{ subscribeErrorMsg }}