aelwan aelwan - 3 months ago 20
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
.

Instead of allowing
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

enter image description here

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
.

Answer

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))

enter image description here

Comments