Annotating text on individual facet in ggplot2
Function annotate()
adds the same label to all panels in a plot with facets. If the intention is to add different annotations to each panel, or annotations to only some panels, a geometry has to be used instead of annotate()
. To use a geometry, such as geom_text()
we need to assemble a data frame containing the text of the labels in one column and columns for the variables to be mapped to other aesthetics, as well as the variable(s) used for faceting. This answer exemplifies this for both facet_wrap()
and facet_grid()
.
Here's the plot without text annotations:
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
facet_grid(. ~ cyl) +
theme(panel.spacing = unit(1, "lines"))
p
Let's create an additional data frame to hold the text annotations:
dat_text <- data.frame(
label = c("4 cylinders", "6 cylinders", "8 cylinders"),
cyl = c(4, 6, 8)
)
p + geom_text(
data = dat_text,
mapping = aes(x = -Inf, y = -Inf, label = label),
hjust = -0.1,
vjust = -1
)
Alternatively, we can manually specify the position of each label:
dat_text <- data.frame(
label = c("4 cylinders", "6 cylinders", "8 cylinders"),
cyl = c(4, 6, 8),
x = c(20, 27.5, 25),
y = c(4, 4, 4.5)
)
p + geom_text(
data = dat_text,
mapping = aes(x = x, y = y, label = label)
)
We can also label plots across two facets:
dat_text <- data.frame(
cyl = c(4, 6, 8, 4, 6, 8),
am = c(0, 0, 0, 1, 1, 1)
)
dat_text$label <- sprintf(
"%s, %s cylinders",
ifelse(dat_text$am == 0, "automatic", "manual"),
dat_text$cyl
)
p +
facet_grid(am ~ cyl) +
geom_text(
size = 5,
data = dat_text,
mapping = aes(x = Inf, y = Inf, label = label),
hjust = 1.05,
vjust = 1.5
)
Notes:
- You can use
-Inf
andInf
to position text at the edges of a panel. - You can use
hjust
andvjust
to adjust the text justification. - The text label data frame
dat_text
should have a column that works with yourfacet_grid()
orfacet_wrap()
.
Function annotate()
adds the same label to all panels in a plot with facets. If the intention is to add different annotations to each panel, or annotations to only some panels, a geometry has to be used instead of annotate()
. To use a geometry, such as geom_text()
we need to assemble a data frame containing the text of the labels in one column and columns for the variables to be mapped to other aesthetics, as well as the variable(s) used for faceting.
Typically you'd do something like this:
ann_text <- data.frame(mpg = 15,wt = 5,lab = "Text",
cyl = factor(8,levels = c("4","6","8")))
p + geom_text(data = ann_text,label = "Text")
It should work without specifying the factor variable completely, but will probably throw some warnings: