library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.5.3
library(ggindex)Maps and annotated figures often mark a few places with numbers and explain the numbers in a legend. ggplot2 has no direct way to draw this: a legend key shows a symbol, not the number that labels a point. geom_focus() draws the numbered markers and builds the legend for you.
The examples here are scatter plots and maps. For line charts, bar charts and distributions, see Numbered markers on other plots. For colours, shapes, fonts, themes and facets, see Styling numbered markers. For why geom_text() and geom_label() aren’t enough, see Why not geom_text() or geom_label()?.
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.5.3
library(ggindex)Map info to the description that goes in the legend. The entries are numbered 1, 2, 3, … in the order they appear in the data.
sites <- data.frame(
x = c(6, 7, 8, 9, 10),
y = c(6, 9, 7, 10, 8),
name = c("Library", "Main hall", "Sports centre", "Cafeteria", "Car park")
)
ggplot(sites, aes(x, y, info = name)) +
geom_focus() +
theme_minimal()To choose the numbers yourself, map label. Legend entries are sorted by label, so the legend reads in the same order as the numbers. Markers grow to fit longer labels.
sites$code <- c(12, 3, 104, 7, 45)
ggplot(sites, aes(x, y, label = code, info = name)) +
geom_focus() +
theme_minimal()scale_info_discrete() is added automatically when info is mapped; call it yourself to set the legend title or other scale arguments.
Map focus to a logical variable to number only some observations. geom_focus() draws only the numbered markers, so add geom_point() to show the rest.
cars <- mtcars
cars$model <- rownames(cars)
cars$rank <- rank(-cars$mpg, ties.method = "first")
ggplot(cars, aes(wt, mpg)) +
geom_point(colour = "grey60") +
geom_focus(aes(label = rank, focus = rank <= 5, info = model)) +
scale_info_discrete("Most efficient") +
labs(x = "Weight (1000 lbs)", y = "Miles per gallon") +
theme_minimal()label, focus and info are mapped in geom_focus(), not in ggplot(). Layers inherit the mapping of ggplot(), so with info mapped there the geom_point() layer would add every car to the legend.
Markers are drawn at the data positions and don’t move apart, so points that nearly coincide, like 3 and 4 above, overlap. Map nudge_x or nudge_y and set position = "nudge" to move individual markers aside:
ggplot(cars, aes(wt, mpg)) +
geom_point(colour = "grey60") +
geom_focus(
aes(
label = rank,
focus = rank <= 5,
info = model,
nudge_x = ifelse(model == "Lotus Europa", -0.12, 0)
),
position = "nudge"
) +
theme_minimal()geom_sf_focus() numbers simple features from the sf package. Markers are placed on each feature with stat_sf_coordinates().
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
nc <- sf::st_transform(nc, 32119)
nc_large <- nc[nc$AREA > 0.2, ]
ggplot(nc) +
geom_sf(fill = "grey90", colour = "white") +
geom_sf_focus(aes(info = NAME), data = nc_large) +
scale_info_discrete("Largest counties") +
theme_void()