Label individual panels in a multi-panel ggplot2
Solution 1
I had the same problem and came up with the following solution, which is a bit different:
loading r packages
library(ggplot2)
library(grid)
library(gridExtra)
example data
a <- 1:20
b <- sample(a, 20)
c <- sample(b, 20)
d <- sample(c, 20)
create a data frame
mydata <- data.frame(a, b, c, d)
create example plots
myplot1 <- ggplot(mydata, aes(x=a, y=b)) + geom_point()
myplot2 <- ggplot(mydata, aes(x=b, y=c)) + geom_point()
myplot3 <- ggplot(mydata, aes(x=c, y=d)) + geom_point()
myplot4 <- ggplot(mydata, aes(x=d, y=a)) + geom_point()
set corner labels
myplot1 <- arrangeGrob(myplot1, top = textGrob("A", x = unit(0, "npc")
, y = unit(1, "npc"), just=c("left","top"),
gp=gpar(col="black", fontsize=18, fontfamily="Times Roman")))
myplot2 <- arrangeGrob(myplot2, top = textGrob("B", x = unit(0, "npc")
, y = unit(1, "npc"), just=c("left","top"),
gp=gpar(col="black", fontsize=18, fontfamily="Times Roman")))
myplot3 <- arrangeGrob(myplot3, top = textGrob("C", x = unit(0, "npc")
, y = unit(1, "npc"), just=c("left","top"),
gp=gpar(col="black", fontsize=18, fontfamily="Times Roman")))
myplot4 <- arrangeGrob(myplot4, top = textGrob("D", x = unit(0, "npc")
, y = unit(1, "npc"), just=c("left","top"),
gp=gpar(col="black", fontsize=18, fontfamily="Times Roman")))
plotting all plots on one page
grid.arrange(myplot1, myplot2, myplot3, myplot4, ncol = 2)
Solution 2
Two recent changes have made this a lot easier:
- The latest release of
ggplot2
has added thetag
caption which can be used to label subplots. - The package
patchwork
makes it really easy to plot multiple ggplot objects. https://github.com/thomasp85/patchwork
This means that no altering of grobs is required. Adapting the reproducible example provided by Kev:
library(ggplot2)
# install.package("patchwork")
library(patchwork)
a <- 1:20
b <- sample(a, 20)
c <- sample(b, 20)
d <- sample(c, 20)
mydata <- data.frame(a, b, c, d)
myplot1 <- ggplot(mydata, aes(x=a, y=b)) + geom_point() + labs(tag = "A")
myplot2 <- ggplot(mydata, aes(x=b, y=c)) + geom_point() + labs(tag = "B")
myplot3 <- ggplot(mydata, aes(x=c, y=d)) + geom_point() + labs(tag = "C")
myplot4 <- ggplot(mydata, aes(x=d, y=a)) + geom_point() + labs(tag = "D")
myplot1 + myplot2 + myplot3 + myplot4
Extension: Changing Style:
If you want to change the labelling style, you can either set this individually for each plot or set a theme default. I would recommend the second approach. Add the following line before you build your plots to make the font bold and blue
ggplot2::theme_update(plot.tag = element_text(face = "bold", colour = "blue"))
For more information on customising the theme of ggplot2, see here.
Solution 3
An example:
d <- data.frame(x = runif(16),
y = runif(16),
grp = rep(letters[1:4],each = 4))
ggplot(d,aes(x = x,y = y)) +
facet_wrap(~grp) +
geom_point() +
theme(strip.text = element_text(hjust = -0.05),
strip.background = element_blank())
Solution 4
Here's a solution using a custom labeller function. This doesn't invovle any manipulations to the data. Currently it only works with 1-dimensional facets (facet_wrap). I'm still working on how to increment along a 2-D grid...
Define the labeller function
make_labelstring <- function(mypanels) { mylabels <- sapply(mypanels, function(x) {LETTERS[which(mypanels == x)]}) return(mylabels) } label_panels <- ggplot2::as_labeller(make_labelstring)
Pass
label_panels
as the labeller tofacet_wrap
library(ggplot2) data("diamonds") # create a faceted plot ggplot(data = diamonds, aes(x = depth, y = price)) + geom_point() + facet_wrap(~cut, labeller = label_panels) + theme(strip.text = element_text(hjust = -0), strip.background = element_blank())
Related videos on Youtube
Comments
-
Thraupidae almost 2 years
I'm interested in trying to create simple corner labels for a multipanel figure I am preparing in ggplot. This is similar to this previously asked question, but the answers only explained how to include a label at the top of the plot, not produce a corner label in the format required by many journals. I hope to replicate something similar to the
plotrix
functioncorner.label()
inggplot2
.Here is an example using
plottrix
of what I would like to recreate inggplot2
.require(plotrix) foo1<-rnorm(50,25,5) foo2<-rpois(50,25) foo3<-rbinom(50,25,0.5) foo4<-rnbinom(50,25,0.5) par(mfrow=c(2,2)) hist(foo1) corner.label(label='a',figcorner=T) hist(foo2) corner.label(label='b',figcorner=T) hist(foo3) corner.label(label='c',figcorner=T) hist(foo4) corner.label(label='d',figcorner=T)
This produces the following:
Thanks for any help in advance!
-
Thraupidae almost 11 yearsIs there any way to have the labels outside the plot/axes region? Similar to the 'figcorner=T' option in corner.label()?
-
joran almost 11 years@Thraupidae You can set the
hjust
to be negative, but then b and d will drift into the other panels. -
joran almost 11 years@Thraupidae See my edit. I think that's closer to what you're after. (And should explain why I asked about the facet ribbons.)
-
Thraupidae almost 11 yearsOK and to prevent the drifting into other panels I suppose you just have to mess with the spacing using plot.margin?
-
Thraupidae almost 11 yearsAh, yes that looks very close to what I was hoping with the facet ribbons removed. Thanks!
-
DeanAttali over 8 yearsThis is great. This is much simpler and more generally applicable and easier to implement than the accepted solution IMO. Thanks!
-
M. Beausoleil about 3 yearsCan you make the
tag
in bold, change size, etc.? How would that be done? -
Michael Harper about 3 yearsGood question: added more to the original answer to cover your point. Pretty much every component of ggplot2 can be customised by the
theme
argument. -
M. Beausoleil about 3 yearsThanks! I was trying to find documentation, but it seems not a lot of people use it!