Home / Tools / lm() Output Interpreter

lm() Output Interpreter

R's lm() fits linear regression, the workhorse model for continuous outcomes. Paste a summary(lm(...)) block and get a per-coefficient plain-English read (direction, magnitude, significance), an R-squared and F-test verdict, coefficient confidence intervals, and a compare-models view with AIC, BIC and a nested anova F-test. Everything runs in your browser.

iNew to reading lm() output? Read the 4-min primer

What lm() does. R's lm() fits a linear model by ordinary least squares. You give it a formula like y ~ x1 + x2 and a data frame; it finds the coefficients (slopes and intercept) that minimize the sum of squared residuals. summary() on the fit object prints a structured report with the formula, the residual quantiles, a coefficient table, the model-level R^2 and F-statistic, and the residual standard error.

Reading the coefficient table. Each row is one term in the model. Estimate is the slope (or for a factor level, the gap from the reference). Std. Error is its sampling SE. t value is estimate divided by SE; under the null of no effect, it follows a t distribution. Pr(>|t|) is the two-sided p-value. The trailing *** / ** / * stars rank significance at 0.001, 0.01, 0.05.

What R^2, F, and residuals mean. Multiple R^2 is the fraction of variance in the outcome that the model explains. Adjusted R^2 penalizes adding predictors that do not help. The F-statistic tests whether the model as a whole is better than the intercept-only baseline; its p-value is the model-level significance. Residual standard error is the typical size of a residual on the outcome's scale, on a given degrees of freedom (n - k - 1).

Picking which model to trust. When you have two nested models, an anova(fit1, fit2) F-test asks whether the extra terms are worth their parameters. For non-nested models on the same data, compare AIC or BIC: lower is better, with delta < 2 being effectively a tie and delta > 7 being decisive. Always sanity-check residuals (a Q-Q plot, a fitted-vs-residual plot) before celebrating a high R^2.

Try a worked example

Coefficient CI level
Paste summary(lm(...)) output
When to use this & what to paste
Use when

Inputs needed
    Awaiting paste…
    Coefficient forest plotVISUAL
    Estimate ± 95% CI per term; the dashed line marks zero.
    Paste a summary(lm()) block to render.

    The same read in R

    No data leaves your browser Verified against R's lm(), confint() & anova() Free, no sign-up

    The math behind the read

    Coefficient CIs, the model F p-value, AIC, BIC, log-likelihood and the nested anova F-test are recomputed from the parsed numbers, not lifted from the printout. Here is what each identity is doing.

    Read moreAnatomy of summary(lm)
    Sum of squares decomposition: SS_total = sum( (y_i - mean(y))^2 ) SS_resid = sum( (y_i - y_hat_i)^2 ) SS_model = SS_total - SS_resid R^2 = SS_model / SS_total Adj R^2 = 1 - (SS_resid / (n - k - 1)) / (SS_total / (n - 1))
    Variance partition. Total variation in y is split into the part the model explains (SS_model) and the part it does not (SS_resid). R^2 is the explained share; the adjusted version penalizes adding predictors that do not pull their weight by replacing the SS ratios with their mean-square (df-corrected) versions.
    Coefficient SE and t-statistic: Var(beta_hat) = sigma^2 * (X^T X)^(-1) SE(beta_j) = sqrt( Var(beta_hat)[j, j] ) t_j = beta_hat_j / SE(beta_j) under H0: t_j ~ Student-t with (n - k - 1) df
    Where the SE comes from. Each coefficient's standard error is read off the diagonal of sigma^2 (X^T X)^(-1), where sigma^2 is estimated by the residual mean square. Dividing the estimate by its SE gives the t-statistic; large |t| means the estimate is many SEs away from zero. The reference distribution is Student-t with the residual df.
    Overall F-test: F = (SS_model / k) / (SS_resid / (n - k - 1)) under H0 (all slopes = 0): F ~ F(k, n - k - 1)
    Model-level test. The F-statistic compares the explained-per-parameter to the unexplained-per-residual-df. Under the null that every slope is zero, F follows an F distribution; the printed p-value is the right-tail probability. A significant F means the model as a whole beats the intercept-only baseline.
    Residual standard error: sigma_hat = sqrt( SS_resid / (n - k - 1) )
    Typical residual size. Residual SE (RSE) is the square root of the residual mean square: it tells you, in the outcome's units, how big a typical miss is. Compare it to the scale of the intercept and to the spread of y; if RSE is close to sd(y) the model has not learned much.
    Nested-model F-test (anova): F = ((SS_resid_small - SS_resid_big) / (df_small - df_big)) / (SS_resid_big / df_big) under H0 (extra terms = 0): F ~ F(df_small - df_big, df_big)
    Comparing nested models. When model B contains every predictor of model A plus one or more extras, anova(A, B) runs an F-test on whether the residual SS dropped by more than chance. Equivalent to a likelihood-ratio test for Gaussian linear models. If you instead need to compare non-nested fits, use AIC / BIC.
    CaveatsWhen this is the wrong tool
    If you have…
    Use instead
    Binary, count, or proportion outcome
    Use the glm() output interpreter (logistic / Poisson / quasi-binomial). lm() assumes Gaussian residuals; for non-Gaussian outcomes the SEs and p-values from this tool will not transfer.
    Clustered or repeated-measures data
    Use a mixed-effects model (lme4 / nlme) so within-cluster correlation does not deflate your standard errors. A planned future tool (mixed-effects interpreter) will cover this.
    Suspected multicollinearity
    Run a VIF analysis (planned VIF-checker tool, scoped). lm()'s SEs balloon under collinearity; the diagnostic callouts here flag the most extreme cases but a real VIF check is needed.
    Need to inspect residuals visually
    The diagnostic plot tool (planned, scoped) will render the four plot(lm) diagnostics. This interpreter only sees the printed summary, so it cannot speak to leverage, normality, or heteroscedasticity directly.
    Time-series or autocorrelated residuals
    Standard lm() ignores serial correlation. Switch to ARIMA / GLS / Newey-West, or use lmtest::dwtest first to check whether independence is plausible.

    Frequently asked questions

    What does the (Intercept) row mean in summary(lm)?

    The intercept is the predicted outcome when all predictors equal zero, or, for factor predictors, when each is at its reference level. If predictors are not centered, the intercept can sit far outside the data range and may not be interpretable on its own. Center continuous predictors when the intercept needs to mean something.

    How do I interpret a negative coefficient in linear regression?

    A negative coefficient means the outcome decreases as the predictor increases, holding the other variables constant. In mtcars, wt -3.9 *** means each additional 1000 lbs of weight is associated with a 3.9 mpg decrease, after adjusting for the other terms. The "after adjusting" qualifier matters: a sign can flip when you add or remove confounders.

    What is the difference between R-squared and adjusted R-squared?

    R-squared is the share of variance explained; it always rises when you add a predictor, even a useless one. Adjusted R-squared penalizes for the number of predictors and only rises when the new term genuinely improves fit. Use adjusted R-squared to compare models with different numbers of predictors.

    Go deeper

    Numerical notes: the parser handles "< 2e-16", scientific notation, and Signif. codes lines. Coefficient CIs, the F-test p-value, AIC, BIC, log-likelihood, and the nested anova F-test are recomputed with a math library verified against R 4.6.0 (lm, confint, anova, AIC, BIC) to better than 1e-9 relative error. The "Reproduce in R" snippet is copy-ready and reproduces every number shown; run it in the R session where you already fit the model.