Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default panel layout of ggplot2::facet_wrap()?

I'm trying to understand the default behavior of ggplot2::facet_wrap(), in terms of how the panel layout is decided as the number of facets increases.

I've read the ?facet_wrap help file, and also googled this topic with limited success. In one SO post, facet_wrap() was said to "return a symmetrical matrix of plots", but I did not find anything that explained what exactly the default behavior would be.

So next I made a series of plots which had increasing numbers of facets (code shown further down).

Set of plots with increasing number of facets

The pattern in the image makes it seem like facet_wrap() tries to "make a square"...

Questions

  1. Is that correct? Does facet_wrap try to render the facet panels so in totality they are most like a square, in terms of the number of elements in the rows and columns?
  2. If not, what is it actually doing? Do graphical parameters factor in?

Code that made the plot

# load libraries
library(ggplot2)
library(ggpubr)

# plotting function
facetPlots <- function(facets, groups = 8){
   # sample data  
   df <- data.frame(Group = sample(LETTERS[1:groups], 1000, replace = T),
                    Value = sample(1:10000, 1000, replace = T),
                    Facet = factor(sample(1:facets, 1000, replace = T)))
   # get means
   df <- aggregate(list(Value = df$Value), 
                   list(Group = df$Group, Facet = df$Facet), mean)

   # plot
   p1 <- ggplot(df, aes(x= Group, y= Value, fill = Group))+
           geom_bar(stat="identity", show.legend = FALSE)+
           facet_wrap(. ~ Facet) +
           theme_bw()+
     theme(strip.text.x = element_text(size = 6, 
        margin = margin(.1, 0, .1, 0, "cm")),
       axis.text.x=element_blank(),
       axis.ticks=element_blank(),
       axis.title.x=element_blank(),
       axis.text.y=element_blank(),
       axis.title.y=element_blank(),
       plot.margin = unit(c(3,3,3,3), "pt"))
  p1

}

# apply function to list
plot_list <- lapply(c(1:25), facetPlots)
# unify into single plot
plot <- ggpubr::ggarrange(plotlist = plot_list)  
like image 971
xilliam Avatar asked Sep 13 '25 05:09

xilliam


1 Answers

Here is how the default number of rows and columns are calculated:

ncol <- ceiling(sqrt(n))
nrow <- ceiling(n/ncol)

Apparently, facet_wrap tends to prefer wider grids, since "most displays are roughly rectangular" (according to the documentation). Hence, the number of columns would be greater than or equal to the number of rows.

For your example:

n <- c(1:25)

ncol <- ceiling(sqrt(n))
nrow <- ceiling(n/ncol)

data.frame(n, ncol, nrow)

Here are the computed numbers of rows/cols:

#   n   ncol   nrow
#   1      1      1
#   2      2      1
#   3      2      2
#   4      2      2
#   5      3      2
#   6      3      2
#   7      3      3
#   8      3      3
#   9      3      3
#  10      4      3
#  11      4      3
#  12      4      3
#  13      4      4
#  14      4      4
#  15      4      4
#  16      4      4
#  17      5      4
#  18      5      4
#  19      5      4
#  20      5      4
#  21      5      5
#  22      5      5
#  23      5      5
#  24      5      5
#  25      5      5
like image 83
Taher A. Ghaleb Avatar answered Sep 15 '25 21:09

Taher A. Ghaleb