Answer
How do you interpret regression output in R?
The short answer
Each coefficient row gives the change in the outcome per unit of that predictor with the others held fixed (Estimate), its uncertainty (Std. Error), its distance from zero in standard errors (t value = Estimate / SE), and the p-value for a true coefficient of zero. Below the table, the residual standard error is the typical prediction error in the outcome's units, R-squared is the share of variance explained, and the F test checks all slopes at once.
A worked example
The easiest way to learn the output is to rebuild every number yourself. The code below simulates 100 students whose exam score depends on hours of study (true slope 3) and hours of sleep (true slope 2), plus noise with a standard deviation of 8. It fits the model with lm(), prints summary(), and then recomputes each figure from the data by hand. The Python tab reproduces the same table with NumPy and SciPy.
R
set.seed(5135)
n <- 100
# Simulated data: exam score depends on study hours and sleep
hours <- runif(n, 0, 10)
sleep <- rnorm(n, 7, 1)
score <- 50 + 3 * hours + 2 * sleep + rnorm(n, sd = 8)
fit <- lm(score ~ hours + sleep)
summary(fit)
# Rebuild every number by hand
X <- model.matrix(fit)
res <- residuals(fit)
p <- ncol(X) # coefficients, including intercept
df <- n - p # residual degrees of freedom
rse <- sqrt(sum(res^2) / df) # residual standard error
se <- sqrt(diag(rse^2 * solve(t(X) %*% X)))
t <- coef(fit) / se # t value = estimate / SE
pv <- 2 * pt(-abs(t), df) # two-sided p-value
round(cbind(estimate = coef(fit), se, t, p = pv), 4)
tss <- sum((score - mean(score))^2)
r2 <- 1 - sum(res^2) / tss
adj <- 1 - (1 - r2) * (n - 1) / df
Fst <- (r2 / (p - 1)) / ((1 - r2) / df)
round(c(rse = rse, df = df, r2 = r2, adj_r2 = adj, F = Fst,
F_p = pf(Fst, p - 1, df, lower.tail = FALSE)), 4)
round(mean(res), 10) # residuals average exactly 0
confint(fit) # 95% CIs: estimate +/- t-crit * SEPython
import numpy as np
from scipy import stats
rng = np.random.default_rng(5135)
n = 100
# Simulated data: exam score depends on study hours and sleep
hours = rng.uniform(0, 10, n)
sleep = rng.normal(7, 1, n)
score = 50 + 3 * hours + 2 * sleep + rng.normal(0, 8, n)
# Every number in R's summary(lm(score ~ hours + sleep)), by hand
X = np.column_stack([np.ones(n), hours, sleep])
beta, *_ = np.linalg.lstsq(X, score, rcond=None)
res = score - X @ beta
p = X.shape[1] # coefficients, including intercept
df = n - p # residual degrees of freedom
rse = np.sqrt(res @ res / df) # residual standard error
se = np.sqrt(np.diag(rse**2 * np.linalg.inv(X.T @ X)))
t = beta / se # t value = estimate / SE
pv = 2 * stats.t.sf(np.abs(t), df) # two-sided p-value
for name, b, s, tv, pp in zip(["(Intercept)", "hours", "sleep"], beta, se, t, pv):
print(f"{name:12s} estimate={b:8.4f} se={s:.4f} t={tv:8.4f} p={pp:.4g}")
print("residual quartiles:", np.round(np.percentile(res, [0, 25, 50, 75, 100]), 4))
tss = np.sum((score - score.mean()) ** 2)
r2 = 1 - res @ res / tss
adj = 1 - (1 - r2) * (n - 1) / df
F = (r2 / (p - 1)) / ((1 - r2) / df)
print(f"rse={rse:.4f} on {df} df, R2={r2:.4f}, adjR2={adj:.4f}, "
f"F={F:.4f} on {p - 1} and {df} df, p={stats.f.sf(F, p - 1, df):.3g}")
print("mean residual:", round(float(res.mean()), 10) + 0.0) # 0 up to rounding
tcrit = stats.t.ppf(0.975, df) # 95% CIs: estimate +/- t-crit * SE
print(np.round(np.column_stack([beta - tcrit * se, beta + tcrit * se]), 4))The numbers quoted on this page come from one seeded run of the R code. Python draws different random numbers, so its figures differ slightly (for example a slope of 3.19 for hours instead of 3.24), but every hand calculation matches its own fitted model in the same way. The key part of the R summary looks like this:
Residuals:
Min 1Q Median 3Q Max
-23.7202 -5.0724 -0.2699 5.0583 22.8493
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 44.1002 5.8127 7.587 2e-11 ***
hours 3.2380 0.2895 11.186 < 2e-16 ***
sleep 2.4201 0.7642 3.167 0.00206 **
Residual standard error: 7.884 on 97 degrees of freedom
Multiple R-squared: 0.5735, Adjusted R-squared: 0.5647
F-statistic: 65.2 on 2 and 97 DF, p-value: < 2.2e-16
The residuals and the coefficient table
- Residuals. A residual is an observed score minus the fitted score, and the five numbers are the minimum, quartiles, median and maximum. With an intercept the residuals always average exactly zero, so look for balance: here the median (-0.27) is near zero and the quartiles (-5.07 and 5.06) nearly mirror each other. That hints at symmetric errors; only residual and Q-Q plots can check normality.
- Estimate. The least-squares coefficient. For
hours, 3.24 means that among students with the same amount of sleep, one extra hour of study goes with a score about 3.24 points higher. The phrase "holding the other predictors fixed" matters: in a model with different predictors, the same variable can get a very different coefficient. - Intercept. The predicted score when every predictor equals zero. Here that is a student with no study and no sleep, well outside the data, so its value (44.10) has no practical meaning. Centering predictors makes the intercept interpretable.
- Std. Error. How much the coefficient would vary from sample to sample: the square root of the residual variance times the matching diagonal element of the inverse of X'X. In simple regression it is the residual standard error divided by the square root of the sum of squared deviations of x, so more data, less noise and a wider spread of x all shrink it.
- t value. Simply Estimate divided by Std. Error: 3.2380 / 0.2895 = 11.19. It counts how many standard errors the estimate lies from zero.
- Pr(>|t|). The two-sided p-value: the chance of a t value at least this far from zero if the true coefficient were zero, from a t distribution with the residual degrees of freedom (97). For
sleep, t = 3.17 gives p = .002. < 2e-16and the stars. That display means the p-value is smaller than R will print, not literally that number. The stars are only shorthand for p-value bands.
The t test for a coefficient answers a narrow question: is this slope different from zero, given the other predictors in the model? It says nothing about whether the effect is large. The 95% confidence interval from confint() (the estimate plus or minus about 1.98 standard errors here) is usually more informative: [2.66, 3.81] for hours and [0.90, 3.94] for sleep, both containing the true values used in the simulation. Our page on p-values and t values covers the logic of the test in more detail.
The lines below the table
- Residual standard error (7.884 on 97 degrees of freedom). The square root of the residual sum of squares divided by n minus the number of coefficients (100 - 3 = 97; dividing by 97, not 100, allows for the three estimated coefficients). It estimates the noise SD in the outcome's units: a typical prediction misses by about 8 points, close to the true SD of 8.
- Multiple R-squared (0.5735). One minus the residual sum of squares divided by the total sum of squares: the model accounts for about 57% of the variation in scores. It never falls when you add predictors, even useless ones.
- Adjusted R-squared (0.5647). R-squared with a penalty for the number of predictors, computed as 1 - (1 - R²)(n - 1)/(n - p). It can drop when a weak predictor is added, which makes it fairer for comparing models of different sizes. See whether R-squared is useful or misleading for its limits.
- F-statistic (65.2 on 2 and 97 DF). A test of all the slopes at once against an intercept-only model, comparing variance explained per predictor with unexplained variance per residual degree of freedom. A small p-value says at least one predictor helps, not which one.
- One predictor. With a single predictor, F equals the square of its t value and the two p-values are identical.
Common misreadings
- Reading the stars as effect sizes. Three stars mean a small p-value, which large samples produce even for tiny effects. Judge size from the estimate and its interval.
- Comparing t values across predictors as importance. Predictors measured in different units, or correlated with each other, make these comparisons misleading. Standardized coefficients or a clear substantive argument work better.
- Treating a non-significant slope as zero. A large p-value means the data cannot rule out zero, not that the effect is absent. A wide confidence interval shows how much is still uncertain.
- Skipping the diagnostics. Every p-value and standard error in the table assumes independent errors with constant variance and, for small samples, roughly normal errors.
plot(fit)shows the standard diagnostic plots.
How to report a multiple regression in APA style (7th edition)
Report the overall model test and fit first, then each coefficient with its interval. Italicize statistical symbols, round to two decimals, and drop the leading zero for p and R², which cannot exceed 1. Using the example above:
"A multiple linear regression showed that study hours and sleep together predicted exam scores, F(2, 97) = 65.20, p < .001, R² = .57, adjusted R² = .56. Holding sleep constant, each additional hour of study was associated with a 3.24-point higher score, b = 3.24, 95% CI [2.66, 3.81], t(97) = 11.19, p < .001. Sleep also predicted scores, b = 2.42, 95% CI [0.90, 3.94], t(97) = 3.17, p = .002."
With several predictors, a table is clearer: one row per predictor with b, SE, the 95% CI, t and p, and R², adjusted R² and the F test in a note or the bottom rows.
Related tools and guides
- APA 7 formatter for regression
- Check a reported p-value
- What do p-values and t values mean?
- Is R-squared useful or misleading?
- Which statistical test should I use?
- Ordinary least squares (Wikipedia)
More answered questions
- What do p values and t values actually mean?
- Centering vs standardizing predictors in regression: when to do which?
- Is R-squared useful or misleading?
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 questionWritten 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.