geom_smooth draws a fit, but a paper needs the numbers behind the line: coefficients, uncertainties, R². This lesson fits the model explicitly with lm(), quotes it, and then plots exactly that model — so the line in the figure and the numbers in the text can never disagree.

Step 1 — Data with a trend

library(ggplot2)

set.seed(11)
df <- data.frame(dose = runif(40, 0, 10))
df$response <- 2.0 + 0.85 * df$dose + rnorm(40, 0, 0.9)

Step 2 — Fit and read the summary

fit <- lm(response ~ dose, data = df)
summary(fit)

In the printed summary: the dose row’s Estimate is your slope, Std. Error its uncertainty, and Multiple R-squared the fraction of variance explained. “response increased by 0.85 ± 0.05 per unit dose (R² = 0.87)” — every number comes from this one output.

Step 3 — Predict on a fine grid

Evaluate the fitted model on a smooth grid, asking for the confidence interval:

grid <- data.frame(dose = seq(0, 10, length.out = 200))
pred <- predict(fit, newdata = grid, interval = "confidence")
grid <- cbind(grid, as.data.frame(pred))
head(grid)   # fit, lwr, upr per dose

Step 4 — Plot data, line, and ribbon

ggplot(df, aes(x = dose, y = response)) +
  geom_ribbon(data = grid, aes(y = fit, ymin = lwr, ymax = upr),
              alpha = 0.2) +
  geom_line(data = grid, aes(y = fit), linewidth = 0.9) +
  geom_point(size = 1.8) +
  labs(x = "Dose (mg)", y = "Response") +
  theme_minimal(base_size = 13)

Ribbon first, then line, then points — later layers draw on top, so the data stay visible over the model. This is the same picture geom_smooth(method = "lm") gives, except now it is your fit object drawing it — the one whose coefficients you quoted.

Step 5 — Beyond straight lines

lm fits anything linear in the parameters — a quadratic is one term away:

fit2 <- lm(response ~ dose + I(dose^2), data = df)
anova(fit, fit2)

anova compares the two: a large p-value says the quadratic term isn’t earning its place, which is worth a sentence in the paper all by itself.

Step 6 — Export or insert

Export / Insert — vector PDF, or into the paper with a \label, with the script saved as the figure’s source.

Tip: interval = "confidence" bounds the line; interval = "prediction" bounds where new points would fall and is much wider. Quoting the narrow one when you mean the wide one is a classic reviewer catch — pick on purpose.