Dataslope logoDataslope

Labels, Titles, and Annotations

Turning a correct chart into a communicative one — labs(), titles, direct annotations, and reference lines that guide the reader's eye.

A chart can be technically correct and still fail to communicate. The final layer of craft is labeling and annotation: titles that state the message, axis labels in plain language, and marks that point the reader to what matters. These are small additions with an outsized effect.

labs(): one place for all the text

labs() sets every text label on the plot — axis titles, the legend title, the plot title, subtitle, and caption. Notice that the legend title comes from the aesthetic name, so you label it by naming the aesthetic:

Code Block
R 4.6.0

Make the title the takeaway, not the topic

"Bigger engines are less fuel-efficient" tells the reader the conclusion. "MPG vs. displacement" only names the axes — information the axis labels already provide. A good title states what you want the reader to learn, turning a chart into an argument.

The role of each text slot:

Annotating directly on the plot

Legends cost the reader a glance back and forth. Often it is clearer to write directly on the plot with annotate(), which adds a single text label or shape at coordinates you choose — not tied to the data:

Code Block
R 4.6.0

annotate() differs from a geom: it draws one thing from values you supply, rather than one mark per data row. Use it for callouts, shaded regions, and arrows that explain.

Reference lines guide the eye

Horizontal, vertical, and diagonal reference lines give the reader a baseline to compare against — an average, a target, a threshold:

Code Block
R 4.6.0
  • geom_hline(yintercept = ...) — horizontal line (a target/average)
  • geom_vline(xintercept = ...) — vertical line (a date, a cutoff)
  • geom_abline(slope =, intercept =) — any diagonal (e.g. y = x)

The dashed line instantly answers "which cars are above average?" without the reader doing arithmetic.

The communication layer

Step back and see what these tools share: none of them change the analysis. They change how readily a reader extracts the message. This is the last mile of the grammar — once the components correctly encode the data, labels and annotations make the encoding legible.

QuestionSelect one

In labs(), how do you set the legend title for a color legend?

With a special legend.title argument.

You cannot change a legend title.

By setting the argument named after the aesthetic, e.g. labs(color = "Drivetrain").

By editing the data column name only.

QuestionSelect one

How does annotate("text", ...) differ from adding a geom_text() layer?

annotate() is just an alias for geom_text().

annotate() can only draw rectangles, not text.

annotate() draws a single element from values you supply directly, while geom_text() draws one label per row of mapped data.

geom_text() cannot use the plot's coordinate system.

QuestionSelect one

What is the best practice for a plot title?

Restate the axis variables, e.g. "MPG vs. displacement."

Leave it blank so the chart speaks for itself.

State the takeaway or conclusion, e.g. "Bigger engines are less fuel-efficient," so the chart reads as an argument.

Put the data source in the title.

Key takeaways

  • labs() sets all plot text — title, subtitle, caption, axis titles, and legend titles (named by their aesthetic).
  • Make the title the takeaway, not a restatement of the axes.
  • annotate() adds one-off text or shapes from supplied coordinates; geom_text() labels every row.
  • Reference lines (geom_hline/vline/abline) give the reader a baseline to compare against.
  • This layer changes legibility, not analysis — the final mile of the grammar.

On this page