aelwan - 1 year ago 82
R Question

# ggplot: how to add common x and y labels to a grid of plots

Using

diamonds
, I want to plot
carat
vs
price
for 4 levels (
Fair
,
Good
,
Very Good
and
Premimum
) of
cut
.

facet_wrap()
to control the breaks in the axes, I made four plots to control the breaks in axes.

library(ggplot2)
library(egg)
library(grid)
f1 <-
ggplot(diamonds[diamonds$cut=="Fair",], aes(carat, price))+ geom_point()+ facet_wrap(~cut, ncol =2)+ scale_x_continuous(limits = c(0,4), breaks=c(0, 1, 2, 3, 4))+ scale_y_continuous(limits = c(0,10000), breaks=c(0, 2500, 5000, 7500, 10000))+ labs(x=expression(" "), y=expression(" ")) f2 <- ggplot(diamonds[diamonds$cut=="Good",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_y_continuous(limits = c(0,5000), breaks=c(0,  1000, 2000, 3000, 4000, 5000))+
labs(x=expression(" "),
y=expression(" "))

f3 <-
ggplot(diamonds[diamonds$cut=="Very Good",], aes(carat, price))+ geom_point()+ facet_wrap(~cut, ncol =2)+ scale_x_continuous(limits = c(0,1), breaks=c(0, 0.2, 0.4, 0.6, 0.8, 1))+ scale_y_continuous(limits = c(0,1000), breaks=c(0, 200, 400, 600, 800, 1000))+ labs(x=expression(" "), y=expression(" ")) f4 <- ggplot(diamonds[diamonds$cut=="Premium",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_x_continuous(limits = c(0,1.5), breaks=c(0, 0.2,  0.4, 0.6, 0.8, 1, 1.2, 1.4))+
scale_y_continuous(limits = c(0, 3000), breaks=c(0,  500, 1000, 1500, 2000, 2500, 3000))+
labs(x=expression(" "),
y=expression(" "))

fin_fig <- ggarrange(f1, f2, f3, f4, ncol =2)
fin_fig


RESULT

Each plot has a range of different y values

QUESTION

In all facets, x and y axes are the same. The only difference is the min, max and the breaks. I want to add x and y labels to this figure. I can do this manually in any word document or image editor. Is there anyway to do it in R directly?

UPDATE

I just used
diamonds
in the reporducible example instead of using my
data.frame
. My
data.frame
has a variable that have different levels (
param1
,
param2
,
param3
,
param4
). Each level has different max value.

for example:

param1
ranges from
0
to
0.4

param2
ranges from
0.01
to
0.05

param3
ranges from
0
to
5

param4
ranges from
0
to
1.25

But all have the same unit (y label concentration mg L-1). That's the reason I made four different plots using
diamonds
.

In addition to using functions from the gridExtra package (as suggested by @user20650), you can also create your plots with less code by splitting the diamonds data frame by levels of cut and using mapply:

library(ggplot2)
library(gridExtra)
library(grid)
library(scales)


Remove rows where cut is "Ideal":

dat = diamonds[diamonds$cut != "Ideal",] dat$cut = droplevels(dat$cut)  Create four plots, one for each remaining level of cut and store in a list. We use mapply (instead of lapply) so that we can provide both separate data frames for each level of cut and a vector of custom ymax values to set the highest value on the y-axis separately for each plot: pl = mapply(FUN = function(df, ymax) { ggplot(df, aes(carat, price))+ geom_point()+ facet_wrap(~cut, ncol=2)+ scale_x_continuous(limits = c(0,4), breaks=0:4)+ scale_y_continuous(limits = c(0, ymax), labels=dollar_format()) + labs(x=expression(" "), y=expression(" ")) }, df=split(dat, dat$cut), ymax=c(1e4,5e3,1e3,3e3), SIMPLIFY=FALSE)

grid.arrange(grobs=pl, ncol=2,
bottom=textGrob("Carat", gp=gpar(fontface="bold", col="red")),
left=textGrob("Price", gp=gpar(fontface="bold", col="blue"), rot=90))