Statistical figures are usually comparisons: condition A against condition B, or the same relationship across several samples. ggplot2 has one idea for each — map the group to an aesthetic, or facet into small multiples — and this lesson uses both.

Step 1 — A grouped dataset

library(ggplot2)

df <- data.frame(
  time     = rep(1:6, times = 2),
  signal   = c(2.0, 3.9, 8.1, 15.8, 32.5, 63.0,
               2.1, 3.0, 4.4, 6.5, 9.8, 14.6),
  condition = rep(c("treated", "control"), each = 6)
)

Step 2 — Map the group to colour

One aesthetic turns a pile of points into a comparison:

ggplot(df, aes(x = time, y = signal, colour = condition)) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 2) +
  labs(x = "Time (h)", y = "Signal", colour = NULL)

ggplot2 splits the data by condition, draws each with its own colour, and builds the legend. colour = NULL in labs() drops the redundant legend title.

Step 3 — Or facet into small multiples

When curves overlap too much to read, give each group its own panel instead:

ggplot(df, aes(x = time, y = signal)) +
  geom_line() +
  geom_point(size = 1.5) +
  facet_wrap(~ condition) +
  labs(x = "Time (h)", y = "Signal")

facet_wrap(~ condition) makes one panel per condition with shared axes — the honest way to compare shapes without spaghetti.

Step 4 — Theme it for print

The grey default is fine on screen and noisy on paper. A minimal theme with a readable base size:

ggplot(df, aes(x = time, y = signal, colour = condition)) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 2) +
  labs(x = "Time (h)", y = "Signal", colour = NULL) +
  theme_minimal(base_size = 13) +
  theme(legend.position = "top")

A legend on top keeps the plotting area full-width — worth it in a single-column figure.

Step 5 — Export or insert

As always: Export / Insert for a vector PDF or a placed figure with a \label, with the script saved as the figure’s source.

Tip: If the y-values span decades, add scale_y_log10() as one more layer — an exponential that looks like a hockey stick becomes a straight line whose slope readers can actually judge.