Answer

Centering vs standardizing predictors in regression: when to do which?

Inspired by a question on Cross Validated ·

regressionnormalization

The short answer

Neither one changes the model's fit, R-squared or predictions. Center a predictor when zero is not a sensible value, so the intercept and the main effects in interaction or polynomial models become interpretable. Standardize (center, then divide by the SD) when you want effects per standard deviation, or when a scale-sensitive method such as lasso, ridge or k-nearest neighbours, or a fussy optimizer, needs predictors on similar scales.

What the two transformations actually change

Centering shifts a variable so that a chosen value becomes zero, usually its mean: x - mean(x). Standardizing centers the variable and then rescales it to units of one standard deviation: (x - mean(x)) / sd(x), often called a z-score.

In an ordinary least squares model, both are linear re-expressions of the predictors, so the model sees exactly the same information. The fitted values, residuals, R-squared, overall F test and the test of the highest-order term (an interaction, or the squared term in a quadratic) come out identical. What changes is the meaning of the individual coefficients, and with it their size, and for lower-order terms also their standard errors and p-values. So the choice is about interpretation and computation, not about getting a better model.

When to center

You do not have to center at the mean. Any value that makes zero meaningful works, such as age 18, a clinical cutoff or the scale midpoint. In a model with no interactions or polynomial terms, centering changes only the intercept; every slope and its test stay the same.

When to standardize

Standardizing does not reveal which predictor is objectively more important. A one-SD change depends on how much the variable happens to vary in your sample, so the same effect looks larger in a diverse sample and smaller in a narrow one. Report raw units whenever they mean something to your readers, and think twice before standardizing a 0/1 dummy variable, whose SD depends on how the groups are split.

See it in R and Python

This simulation fits the same interaction model three times: with raw predictors (age in years and weekly work hours), with centered predictors, and with standardized predictors. The R version uses base R only; the Python tab runs the same analysis with NumPy.

R

set.seed(24)
n <- 200
age   <- rnorm(n, mean = 45, sd = 10)   # years
hours <- rnorm(n, mean = 35, sd = 8)    # weekly work hours
y <- 20 + 0.10 * age + 0.30 * hours - 0.02 * (age - 45) * (hours - 35) + rnorm(n, sd = 3)

# Three versions of the same predictors
age_c <- age - mean(age);   hours_c <- hours - mean(hours)   # centered
age_z <- age_c / sd(age);   hours_z <- hours_c / sd(hours)   # standardized

raw <- lm(y ~ age * hours)
ctr <- lm(y ~ age_c * hours_c)
std <- lm(y ~ age_z * hours_z)

tab <- function(m) round(summary(m)$coefficients[, 1:3], 3)   # estimate, SE, t
tab(raw); tab(ctr); tab(std)

# Same fit every time: identical R-squared and fitted values
round(sapply(list(raw = raw, centered = ctr, standardized = std),
             function(m) summary(m)$r.squared), 4)
all.equal(fitted(raw), fitted(ctr))

# Collinearity between a main effect and its interaction term
round(c(raw = cor(age, age * hours), centered = cor(age_c, age_c * hours_c)), 2)

# Confidence interval for the standardized age effect
round(confint(std)["age_z", ], 2)

Python

import numpy as np

rng = np.random.default_rng(24)
n = 200
age = rng.normal(45, 10, n)     # years
hours = rng.normal(35, 8, n)    # weekly work hours
y = 20 + 0.10 * age + 0.30 * hours - 0.02 * (age - 45) * (hours - 35) + rng.normal(0, 3, n)

# Three versions of the same predictors
age_c, hours_c = age - age.mean(), hours - hours.mean()                  # centered
age_z, hours_z = age_c / age.std(ddof=1), hours_c / hours.std(ddof=1)    # standardized

def fit(a, b):
    # OLS for y ~ a * b; returns estimate, SE, t table plus R-squared and fitted values
    X = np.column_stack([np.ones(n), a, b, a * b])
    beta, *_ = np.linalg.lstsq(X, y, rcond=None)
    fitted = X @ beta
    resid = y - fitted
    sigma2 = resid @ resid / (n - X.shape[1])
    se = np.sqrt(np.diag(sigma2 * np.linalg.inv(X.T @ X)))
    r2 = 1 - resid @ resid / np.sum((y - y.mean()) ** 2)
    return np.column_stack([beta, se, beta / se]), r2, fitted

raw, ctr, std = fit(age, hours), fit(age_c, hours_c), fit(age_z, hours_z)
for name, (table, r2, _) in zip(("raw", "centered", "standardized"), (raw, ctr, std)):
    print(name, "R-squared", round(r2, 4))
    print(np.round(table, 3))   # rows: intercept, a, b, a:b; columns: estimate, SE, t

# Same fit every time: identical fitted values
print(np.allclose(raw[2], ctr[2]))

# Collinearity between a main effect and its interaction term
print(round(np.corrcoef(age, age * hours)[0, 1], 2),
      round(np.corrcoef(age_c, age_c * hours_c)[0, 1], 2))

The figures below come from one seeded run of the R code. Python uses a different random number generator, so its figures differ slightly, but the pattern is the same.

Common mistakes

How to report standardized regression coefficients in APA style (7th edition)

Say in the method section which variables were centered or standardized, and around what value, because the coefficients cannot be interpreted without it. Using the standardized model above as an example:

"Age and weekly work hours were standardized before forming their product term. Holding work hours at their mean, a one-SD increase in age was associated with a 1.18-point higher score, b = 1.18, 95% CI [0.76, 1.61], t(196) = 5.49, p < .001. The model explained 59% of the variance, R² = .59."

If you standardize the outcome as well, label the coefficients β and say so. In a regression table, give b, SE, the 95% CI and p for each term, and add a table note stating how each predictor was centered or scaled.

Related tools and guides

More answered questions

Working with your own data?

General answers only go so far. Send us your situation and we'll reply by email within two business days.

Ask your question

Written by AskStats with AI assistance. This is general information, not advice for your specific data or study. When the results matter, check your approach with a qualified statistician.