Simple Linear Regression in R: Model One Predictor

Fit a straight line between a predictor and a numeric outcome, interpret the slope and R², and test whether the relationship is real — lm() the practical way

Biostatistics

Learn simple linear regression in R — model a numeric outcome from a single predictor with lm(). Visualize the relationship, read and interpret the full output (intercept, slope, R², the F-test), get confidence intervals, and make a prediction. The foundation of regression modelling.

Published

June 23, 2026

Modified

July 7, 2026

TipKey takeaways
  • Simple linear regression models a numeric outcome as a straight line of a single predictor: outcome = intercept + slope × predictor.
  • Fit it with base R lm(outcome ~ predictor, data = ...) and read the summary.
  • The slope is the change in the outcome per one-unit increase in the predictor; the intercept is the outcome when the predictor is 0; is the share of variation the model explains.
  • The F-test (and the slope’s t-test) tells you whether the relationship is statistically significant; confint() gives the slope’s confidence interval.
  • Use predict() to estimate the outcome for new predictor values.

Introduction

Simple linear regression fits a straight line between one predictor (explanatory variable) and a numeric outcome, so you can describe and quantify their relationship — and predict the outcome from the predictor. It is the foundation of regression modelling and the starting point for everything from multiple regression to logistic regression.

The scenario: a company wants to know how advertising budget drives sales. Here we model sales from the YouTube advertising budget, using the marketing data — and read off how much each extra dollar of budget is worth.

The data: advertising and sales

We use the marketing dataset from datarium — the advertising budget (in thousands of dollars) on youtube, facebook and newspaper, and the resulting sales, for 200 campaigns:

data("marketing", package = "datarium")
head(marketing, 4)
  youtube facebook newspaper sales
1  276.12    45.36     83.04 26.52
2   53.40    47.16     54.12 12.48
3   20.64    55.08     83.16 11.16
4  181.80    49.56     70.20 22.20

Look at the relationship first

Always plot before modelling. A scatter plot of sales against youtube, with a fitted line, shows a clear positive, roughly linear relationship:

library(ggpubr)

data("marketing", package = "datarium")

ggscatter(marketing, x = "youtube", y = "sales", add = "reg.line",
          add.params = list(color = "#3a86d4"),
          xlab = "YouTube budget (k$)", ylab = "Sales")

A scatter plot of sales versus youtube advertising budget for 200 campaigns, with a fitted blue regression line rising steadily; sales increase with budget.

Fit the model

lm() fits the line; summary() reports the full output:

data("marketing", package = "datarium")

model <- lm(sales ~ youtube, data = marketing)
summary(model)

Call:
lm(formula = sales ~ youtube, data = marketing)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.0632  -2.3454  -0.2295   2.4805   8.6548 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 8.439112   0.549412   15.36   <2e-16 ***
youtube     0.047537   0.002691   17.67   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 3.91 on 198 degrees of freedom
Multiple R-squared:  0.6119,    Adjusted R-squared:  0.6099 
F-statistic: 312.1 on 1 and 198 DF,  p-value: < 2.2e-16

Interpret the full output

Read the summary piece by piece — not just the p-value:

  • Coefficients. The intercept is 8.44: a campaign with zero youtube budget is predicted to sell ~8.4 units. The youtube slope is 0.0475: each extra 1 k$ of youtube budget adds 0.0475 to sales — i.e. ~$47.5 of sales per extra $1000 spent.
  • Significance. The slope’s t-test has p < 2e-16, and so does the overall F-statistic (F(1, 198) ≈ 312) — the relationship is highly significant; youtube budget genuinely predicts sales.
  • R². Multiple R-squared = 0.61 — youtube budget alone explains 61% of the variation in sales. The rest is other factors (facebook, newspaper, noise).
  • Residual standard error (3.91) is the typical size of a prediction error, in sales units.

Confidence interval for the slope

confint() gives the plausible range for the true slope:

data("marketing", package = "datarium")
model <- lm(sales ~ youtube, data = marketing)

confint(model)
                 2.5 %     97.5 %
(Intercept) 7.35566312 9.52256140
youtube     0.04223072 0.05284256

The 95% CI for the youtube slope is [0.042, 0.053] — comfortably above 0, confirming a positive effect, and giving the range of “sales per k$” consistent with the data.

Predict new values

Use predict() to estimate sales for new budgets, with a confidence interval (for the mean) or a prediction interval (for a single new campaign):

data("marketing", package = "datarium")
model <- lm(sales ~ youtube, data = marketing)

new <- data.frame(youtube = c(100, 200))
predict(model, newdata = new, interval = "confidence")
       fit      lwr      upr
1 13.19278 12.51317 13.87239
2 17.94644 17.38703 18.50585

A youtube budget of 200 k$ predicts sales of ~18 units (with the interval showing the uncertainty).

Report

A simple linear regression found that YouTube advertising budget significantly predicted sales, F(1, 198) = 312, p < 0.001, explaining 61% of the variance (R² = 0.61). Each additional 1 k$ of budget was associated with a 0.047-unit increase in sales (95% CI 0.042–0.053).

The model is \(y = \beta_0 + \beta_1 x + \varepsilon\). Least squares chooses \(\beta_0, \beta_1\) to minimise the sum of squared residuals \(\sum_i (y_i - \hat{y}_i)^2\), giving slope \(\hat{\beta}_1 = \dfrac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sum (x_i - \bar{x})^2}\) and intercept \(\hat{\beta}_0 = \bar{y} - \hat{\beta}_1 \bar{x}\). is the fraction of variance explained, \(R^2 = 1 - \dfrac{\sum (y_i - \hat{y}_i)^2}{\sum (y_i - \bar{y})^2}\), and the F-test compares the model to an intercept-only model.

Check the assumptions

Linear regression trusts a few assumptions — linearity, constant residual variance, normal residuals, and no influential outliers. Base R’s plot(model) gives the four diagnostic plots:

data("marketing", package = "datarium")
model <- lm(sales ~ youtube, data = marketing)

par(mfrow = c(2, 2))
plot(model)

The four base-R regression diagnostic plots for the sales-vs-youtube model: residuals vs fitted, normal Q-Q, scale-location, and residuals vs leverage.

par(mfrow = c(1, 1))

A flat residuals-vs-fitted band and a straight Q-Q plot mean the assumptions hold reasonably here. The assumptions & diagnostics lesson covers how to read and fix each one.

Try it live

Fit a different predictor — does the facebook budget predict sales? Edit and re-run; the sandbox boots on first Run.

🟢 With an AI agent

Ask Prova “fit a linear regression of my outcome on a predictor, interpret the slope and R², and tell me whether it’s significant” — it answers with code you can run on your own data and walks you through the output. The runtime is the judge. Ask Prova →

Common issues

You interpreted the intercept literally when 0 is out of range. If the predictor never takes the value 0 (or near it), the intercept is just where the line meets the axis, not a meaningful prediction — focus on the slope.

You reported R² but not whether the slope is significant. A high R² with a non-significant slope (small sample) isn’t trustworthy; report the F-test / slope p-value and the confidence interval alongside R².

The relationship is curved. lm() fits a straight line; if the scatter plot bends, a linear model mis-fits — transform the predictor (e.g. log(x)) or add a polynomial term (poly(x, 2)), and check the residuals-vs-fitted plot, which will show a pattern when the straight line is wrong.

Frequently asked questions

The slope is the expected change in the outcome for a one-unit increase in the predictor, holding nothing else (there’s only one predictor). For sales ~ youtube with slope 0.047, each extra 1 k$ of youtube budget is associated with a 0.047-unit increase in sales. Report it with its confidence interval.

R² (R-squared) is the proportion of variance in the outcome explained by the model — from 0 (explains nothing) to 1 (explains everything). R² = 0.61 means the predictor accounts for 61% of the variation in the outcome; the remaining 39% is other factors and noise.

Look at the F-statistic’s p-value (overall model) and the predictor’s t-test p-value (the slope) in summary() — a value below 0.05 means the relationship is unlikely to be due to chance. Back it with the slope’s confidence interval (confint()); if it excludes 0, the effect is significant.

Test your understanding

  1. Run it. In the live cell, fit sales ~ facebook and read the slope and R². Fill the blank. Is facebook budget a significant predictor?
  2. Conceptual. Model A has R² = 0.61 with a slope p < 0.001; model B has R² = 0.61 with a slope p = 0.30 (n = 12). Which do you trust, and why?

Fill the blank with facebook. Look at the slope’s Pr(>|t|) and the R². For question 2, recall that R² and significance answer different questions.

model <- lm(sales ~ facebook, data = marketing)
summary(model)   #> facebook is a significant positive predictor; R² ≈ 0.33.

For question 2: trust model A. R² measures fit, but the p-value tells you whether the slope is distinguishable from 0. Model B’s high R² on only 12 points with p = 0.30 could easily be chance — the non-significant slope means there’s no reliable evidence of a real relationship despite the apparent fit.

TipWhich model when?

Conclusion

You can now run simple linear regression in R: plot the relationship, fit it with lm(outcome ~ predictor), and interpret the full output — the slope (effect per unit), the intercept, (variance explained), and the F-test / confidence interval for significance — then predict() new values and check the diagnostic plots. It is the foundation every other regression builds on.

Reuse

Citation

BibTeX citation:
@online{2026,
  author = {},
  title = {Simple {Linear} {Regression} in {R:} {Model} {One}
    {Predictor}},
  date = {2026-06-23},
  url = {https://www.datanovia.com/learn/biostatistics/regression/simple-linear-regression-in-r},
  langid = {en}
}
For attribution, please cite this work as:
“Simple Linear Regression in R: Model One Predictor.” 2026. June 23. https://www.datanovia.com/learn/biostatistics/regression/simple-linear-regression-in-r.