Dear useRs, I have an issue with the argument nrow of ggplot2::facet_wrap(). Let's consider some sample data: mydf <- data.frame(grp = rep(letters[1:6], each = 15), cat = rep(1:3, 30), var = rnorm(90)) And let's try to plot with 5 rows: library(ggplot2) ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp, nrow = 5) It plots 2 rows and 3 columns rather than 5 rows and 2 columns as wanted. These plots are as expected: ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp, nrow = 2) ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp, nrow = 6) My guess is that 5 rows is not ideal for 6 facets (5 facets in 1st column and only 1 facet for 2nd column) so it overrides the value of nrow. In the case of 2 or 6 rows, the facets are well distributed in the layout. The reason why I need 5 rows with 6 facets is that this facet plot is part of a patchwork and I would like to have the same number of rows for all facet plots of the patchwork (so that they all align well). Is there a way to force the number of rows in the facet_wrap()? Thank you in advance. Best, Ivan -- -- Dr. Ivan Calandra TraCEr, laboratory for Traceology and Controlled Experiments MONREPOS Archaeological Research Centre and Museum for Human Behavioural Evolution Schloss Monrepos 56567 Neuwied, Germany +49 (0) 2631 9772-243 https://www.researchgate.net/profile/Ivan_Calandra
Dear Ivan, I don't think it is possible to force a number of rows - but I'm honestly just guessing. What you can do is to add an empty plot. Here I use cowplot, but gridExtra should also work well. I add an indication of the row number for the plot to the initial data.frame, and loop over these. In the first variant, I add an unused factor to the grp which creates an empty facet. I personally think this looks a little confusing, so in the second variant, I add a number of empty plots. HTH Ulrik ``` mydf <- data.frame( grp = rep(letters[1:6], each = 15), cat = rep(1:3, 30), var = rnorm(90), row_num = rep(c(1, 1, 2, 3, 4, 5), each = 15) ) s_mydf <- split(mydf, mydf$row_num) plots_mydf <- lapply(s_mydf, function(x){ # Ensure no unused factors x$grp <- droplevels.factor(x$grp) if(length(unique(x$grp)) == 1){ x$grp <- factor(x$grp, levels = c(unique(x$grp), "")) } ggplot(data = x, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp, drop=FALSE) }) cowplot::plot_grid(plotlist = plots_mydf, nrow = 5) # Maybe more elegant output plots_mydf <- lapply(s_mydf, function(x, ncol = 2){ # Ensure no unused factors x$grp <- droplevels.factor(x$grp) x <- split(x, x$grp) p <- lapply(x, function(x){ ggplot(data = x, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp) }) if(length(p) < ncol){ pe <- rep(list(ggplot() + theme_void()), ncol - length(p)) p <- c(p, pe) } cowplot::plot_grid(plotlist = p, ncol = ncol) }) cowplot::plot_grid(plotlist = plots_mydf, ncol = 1) # Or if you prefer not to split the plots on the same row plots_mydf <- lapply(s_mydf, function(x, ncol = 2){ p <- list(ggplot(data = x, aes(x = cat, y = var)) + geom_point() + facet_wrap(~grp)) if(length(unique(x$grp)) < ncol){ pe <- rep(list(ggplot() + theme_void()), ncol - length(p)) p <- c(p, pe) }else{ ncol <- 1 } cowplot::plot_grid(plotlist = p, ncol = ncol) }) cowplot::plot_grid(plotlist = plots_mydf, ncol = 1) ``` On 2020-09-09 17:30, Ivan Calandra wrote:> Dear useRs, > > I have an issue with the argument nrow of ggplot2::facet_wrap(). > > Let's consider some sample data: > mydf <- data.frame(grp = rep(letters[1:6], each = 15), cat = rep(1:3, > 30), var = rnorm(90)) > > And let's try to plot with 5 rows: > library(ggplot2) > ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + > facet_wrap(~grp, nrow = 5) > It plots 2 rows and 3 columns rather than 5 rows and 2 columns as > wanted. > > These plots are as expected: > ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + > facet_wrap(~grp, nrow = 2) > ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + > facet_wrap(~grp, nrow = 6) > > My guess is that 5 rows is not ideal for 6 facets (5 facets in 1st > column and only 1 facet for 2nd column) so it overrides the value of > nrow. In the case of 2 or 6 rows, the facets are well distributed in > the > layout. > > The reason why I need 5 rows with 6 facets is that this facet plot is > part of a patchwork and I would like to have the same number of rows > for > all facet plots of the patchwork (so that they all align well). > > Is there a way to force the number of rows in the facet_wrap()? > > Thank you in advance. > Best, > Ivan > > -- > > > -- > Dr. Ivan Calandra > TraCEr, laboratory for Traceology and Controlled Experiments > MONREPOS Archaeological Research Centre and > Museum for Human Behavioural Evolution > Schloss Monrepos > 56567 Neuwied, Germany > +49 (0) 2631 9772-243 > https://www.researchgate.net/profile/Ivan_Calandra > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Thank you Ulrik for the suggestions. I was thinking of a similar approach using a nested patchwork (which would be easier for me). It's just a shame that it is not possible to force a number of rows. It's good that ggplot2 tries to do things in the most "appropriate" way, but at some point, when the user decides it needs to have 5 rows, then ggplot2 should listen, potentially issuing a warning like "the number of rows specified is not appropriate, consider other values instead (e.g. 2)". Best, Ivan PS: our email server is having troubles today, so I have not received any other R-related emails. Are there few today or is it just me? There might even be more answers to my question... -- Dr. Ivan Calandra TraCEr, laboratory for Traceology and Controlled Experiments MONREPOS Archaeological Research Centre and Museum for Human Behavioural Evolution Schloss Monrepos 56567 Neuwied, Germany +49 (0) 2631 9772-243 https://www.researchgate.net/profile/Ivan_Calandra On 10/09/2020 11:54, Ulrik Stervbo wrote:> Dear Ivan, > > I don't think it is possible to force a number of rows - but I'm > honestly just guessing. > > What you can do is to add an empty plot. Here I use cowplot, but > gridExtra should also work well. > > I add an indication of the row number for the plot to the initial > data.frame, and loop over these. > > In the first variant, I add an unused factor to the grp which creates > an empty facet. I personally think this looks a little confusing, so > in the second variant, I add a number of empty plots. > > HTH > Ulrik > > ``` > mydf <- data.frame( > ? grp = rep(letters[1:6], each = 15), > ? cat = rep(1:3, 30), > ? var = rnorm(90), > ? row_num = rep(c(1, 1, 2, 3, 4, 5), each = 15) > ) > > s_mydf <- split(mydf, mydf$row_num) > > plots_mydf <- lapply(s_mydf, function(x){ > ? # Ensure no unused factors > ? x$grp <- droplevels.factor(x$grp) > ? if(length(unique(x$grp)) == 1){ > ??? x$grp <- factor(x$grp, levels = c(unique(x$grp), "")) > ? } > ? ggplot(data = x, aes(x = cat, y = var)) + geom_point() + > ??? facet_wrap(~grp, drop=FALSE) > }) > > cowplot::plot_grid(plotlist = plots_mydf, nrow = 5) > > # Maybe more elegant output > plots_mydf <- lapply(s_mydf, function(x, ncol = 2){ > ? # Ensure no unused factors > ? x$grp <- droplevels.factor(x$grp) > ? x <- split(x, x$grp) > > ? p <- lapply(x, function(x){ > ??? ggplot(data = x, aes(x = cat, y = var)) + geom_point() + > ????? facet_wrap(~grp) > ? }) > > ? if(length(p) < ncol){ > ??? pe <- rep(list(ggplot() + theme_void()), ncol - length(p)) > ??? p <- c(p, pe) > ? } > ? cowplot::plot_grid(plotlist = p, ncol = ncol) > }) > > cowplot::plot_grid(plotlist = plots_mydf, ncol = 1) > > # Or if you prefer not to split the plots on the same row > plots_mydf <- lapply(s_mydf, function(x, ncol = 2){ > > ? p <- list(ggplot(data = x, aes(x = cat, y = var)) + geom_point() + > ??? facet_wrap(~grp)) > > ? if(length(unique(x$grp)) < ncol){ > ??? pe <- rep(list(ggplot() + theme_void()), ncol - length(p)) > ??? p <- c(p, pe) > ? }else{ > ??? ncol <- 1 > ? } > ? cowplot::plot_grid(plotlist = p, ncol = ncol) > }) > > cowplot::plot_grid(plotlist = plots_mydf, ncol = 1) > > ``` > > On 2020-09-09 17:30, Ivan Calandra wrote: >> Dear useRs, >> >> I have an issue with the argument nrow of ggplot2::facet_wrap(). >> >> Let's consider some sample data: >> mydf <- data.frame(grp = rep(letters[1:6], each = 15), cat = rep(1:3, >> 30), var = rnorm(90)) >> >> And let's try to plot with 5 rows: >> library(ggplot2) >> ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + >> facet_wrap(~grp, nrow = 5) >> It plots 2 rows and 3 columns rather than 5 rows and 2 columns as >> wanted. >> >> These plots are as expected: >> ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + >> facet_wrap(~grp, nrow = 2) >> ggplot(data = mydf, aes(x = cat, y = var)) + geom_point() + >> facet_wrap(~grp, nrow = 6) >> >> My guess is that 5 rows is not ideal for 6 facets (5 facets in 1st >> column and only 1 facet for 2nd column) so it overrides the value of >> nrow. In the case of 2 or 6 rows, the facets are well distributed in the >> layout. >> >> The reason why I need 5 rows with 6 facets is that this facet plot is >> part of a patchwork and I would like to have the same number of rows for >> all facet plots of the patchwork (so that they all align well). >> >> Is there a way to force the number of rows in the facet_wrap()? >> >> Thank you in advance. >> Best, >> Ivan >> >> -- >> >> >> -- >> Dr. Ivan Calandra >> TraCEr, laboratory for Traceology and Controlled Experiments >> MONREPOS Archaeological Research Centre and >> Museum for Human Behavioural Evolution >> Schloss Monrepos >> 56567 Neuwied, Germany >> +49 (0) 2631 9772-243 >> https://www.researchgate.net/profile/Ivan_Calandra >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide >> http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. >