8

I have a number off ggplot objects created based off dichotomous count data. I have combined them together using ggarrange. In this function, there is an option to create a shared legend, but as far as I can see no way to create shared x and y axis labels. In addition, the spacing of the figures is very weird - there is a huge gap between the two figure columns, and in addition a large amount of vertical space before the shared legend. So in sum I would like to be able to create shared x and y axes and minimise the unnecessary vertical and horizontal space.

I checked out the following threads: ggplot2 grid_arrange_shared_legend share axis labels

ggplot: align plots together and add common labels and legend

Add common axis titles with lines/arrows for multiple plots in ggplot

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

But I think what I want to do is quite a bit simpler, and I don't know how to combine ggarrange with facet.grid which was suggested a few times.

I have copied a reproducible example below.

require(tidyverse)
require(ggpubr)
require(reshape2) 

condition <- c("a", "a", "a", "b", "b", "b", "c", "c", "c", "c")
binary_1 <- c(0,0,0,0,0,1,1,1,1,1)
binary_2 <- c(1,1,1,1,1,1,0,0,0,0)
binary_3 <- c(0,1,1,1,1,1,1,1,0,0)
binary_4 <- c(1,1,1,0,0,0,0,0,0,0)


df <- data.frame(condition, binary_1, binary_2, binary_3, binary_4)
df

gg_df <- df %>%
  mutate(binary_1 = as.factor(binary_1), binary_2 = as.factor(binary_2), binary_3 = as.factor(binary_3), binary_4 = as.factor(binary_4))

gg_melt <- melt(gg_df)

gg_1 <- ggplot(gg_melt, aes(x=condition, fill = binary_1)) +
  geom_bar(stat="count") +
  scale_fill_manual(values = c("#FDAE61", "#9E0142"), name = "Behaviour Observed", labels = c("0" = "Absent", "1" = "Present")) +
  scale_x_discrete(labels = c(a = "Condition A", b = "Condition B", c = "Condition C")) + 
  xlab("Condition") + 
  ylab("Number of Participants") +
  ggtitle("Binary 1") +
  theme(plot.title = element_text(size = 10, face="bold", hjust = 0.5)) +
  theme(aspect.ratio = 1) +
  theme(legend.title=element_text(size=10, face = "bold"), axis.title = element_text(size=10, face = "bold"), axis.text = element_text(size=10))+
  theme(legend.box.just = "center")

gg_2 <- ggplot(gg_melt, aes(x=condition, fill = binary_2)) +
  geom_bar(stat="count") +
  scale_fill_manual(values = c("#FDAE61", "#9E0142"), name = "Behaviour Observed", labels = c("0" = "Absent", "1" = "Present")) +
  scale_x_discrete(labels = c(a = "Condition A", b = "Condition B", c = "Condition C")) + 
  xlab("Condition") + 
  ylab("Number of Participants") +
  ggtitle("Binary 2") +
  theme(plot.title = element_text(size = 10, face="bold", hjust = 0.5)) +
  theme(aspect.ratio = 1) +
  theme(legend.title=element_text(size=10, face = "bold"), axis.title = element_text(size=10, face = "bold"), axis.text = element_text(size=10))+
  theme(legend.box.just = "center")

gg_3 <- ggplot(gg_melt, aes(x=condition, fill = binary_3)) +
  geom_bar(stat="count") +
  scale_fill_manual(values = c("#FDAE61", "#9E0142"), name = "Behaviour Observed", labels = c("0" = "Absent", "1" = "Present")) +
  scale_x_discrete(labels = c(a = "Condition A", b = "Condition B", c = "Condition C")) + 
  xlab("Condition") + 
  ylab("Number of Participants") +
  ggtitle("Binary 3") +
  theme(plot.title = element_text(size = 10, face="bold", hjust = 0.5)) +
  theme(aspect.ratio = 1) +
  theme(legend.title=element_text(size=10, face = "bold"), axis.title = element_text(size=10, face = "bold"), axis.text = element_text(size=10))+
  theme(legend.box.just = "center")

gg_4 <- ggplot(gg_melt, aes(x=condition, fill = binary_4)) +
  geom_bar(stat="count") +
  scale_fill_manual(values = c("#FDAE61", "#9E0142"), name = "Behaviour Observed", labels = c("0" = "Absent", "1" = "Present")) +
  scale_x_discrete(labels = c(a = "Condition A", b = "Condition B", c = "Condition C")) + 
  xlab("Condition") + 
  ylab("Number of Participants") +
  ggtitle("Binary 4") +
  theme(plot.title = element_text(size = 10, face="bold", hjust = 0.5)) +
  theme(aspect.ratio = 1) +
  theme(legend.title=element_text(size=10, face = "bold"), axis.title = element_text(size=10, face = "bold"), axis.text = element_text(size=10))+
  theme(legend.box.just = "center")

figure <- ggarrange(gg_1, gg_2, gg_3, gg_4,
                    labels = NULL,
                    ncol = 2, nrow = 4,
                    common.legend = TRUE, legend = "bottom",
                    align = "hv",
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))

pdf("figure.pdf")
figure
dev.off()
 
1
  • Try using pdf("figure.pdf", width=7, height=14). Remember that in your plot there are 2 empty rows (nrow = 2 would be the right choice in ggarrange). Commented Nov 9, 2020 at 19:05

1 Answer 1

18

For common axes using ggarrange, you could try changing to:

require(grid)   # for the textGrob() function

figure <- ggarrange(gg_1 + rremove("ylab") + rremove("xlab"), gg_2 + rremove("ylab") + rremove("xlab"), gg_3 + rremove("ylab") + rremove("xlab"), gg_4+ rremove("ylab") + rremove("xlab"), # remove axis labels from plots
                    labels = NULL,
                    ncol = 2, nrow = 2,
                    common.legend = TRUE, legend = "bottom",
                    align = "hv", 
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))

annotate_figure(figure, left = textGrob("Common y-axis", rot = 90, vjust = 1, gp = gpar(cex = 1.3)),
                    bottom = textGrob("Common x-axis", gp = gpar(cex = 1.3)))

The gp = gpar(cex = 1.3) part changes the font size. The reason there was so much space before the common legend is because you specified nrow = 4 in ggarrange, but the last 2 rows were not populated. The reason there is a gap between figure columns is because you included theme(aspect.ratio = 1) for each plot, so to reduce this gap you have to decreases the width of the ggarrange figure, or else comment out/delete the aspect ratio bit.

Sign up to request clarification or add additional context in comments.

2 Comments

the function textGrob seems to be from grid library. include require(grid) to run the code and display the plots
Hello, I am trying to implement this solution to a similar problem. But When I try the second code 'annotate_figure', I am getting this error message: Error in gList(...) : only 'grobs' allowed in "gList". Do you happen to know what is going on?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.