I have several lists, each of them containing a diferent number of datasets (minimal example of a list below):
library(tidyverse)
mylist = list()
mylist[[1]] = mtcars
mylist[[2]] = mtcars |> filter(carb %in% 1:2)
mylist[[3]] = mtcars |> filter(carb == 1)
For each dataset in a list, I want to make a separate figure showing faceted data, and have all the figures in an RMarkdown or Quarto document rendered as html. To do this, I used a loop to generate all the figures and, in order to have the same size for all the the panels across all figures, I first tried to configure fig.width
and fig.height
in the corresponding chunk with appropiate numeric vectors so that the total size of each figure is dependent on the number of panels it contains. However, I failed to get the same size for all panels across figures:
{r, fig.width= c(2,4,6), fig.height= c(3,3,6)}
library(ggplot2)
for(i in 1:length(mylist)){
p1 = ggplot(mylist[[i]], aes(group= gear, y = wt)) +
geom_boxplot() +
facet_wrap(~carb)
print(p1)
cat("\n \n")
}
I then tried set_panel_size
from the egg
package. Although it seems to do the job, the figures are too far apart from each other. I also get some text about the grobs that I do not wish displayed on the html document:
```{r}
library(egg)
for(i in 1: length(mylist)){
p1 = ggplot(mylist[[i]], aes(group= gear, y = wt)) +
geom_boxplot() +
facet_wrap(~carb, ncol = 3)
print( grid.arrange(grobs = list(set_panel_size(p = p1,
g = ggplot2::ggplotGrob(p1),
width = unit(2, "in"),
height = unit(5,"cm")))))
}
```
I next tried force_panelsizes
from the ggh4x
package, and have a similar problem regarding distance among figures:
library(ggh4x)
for(i in 1:length(mylist)){
p1 = ggplot(mylist[[i]], aes(group= gear, y = wt)) +
geom_boxplot() +
facet_wrap(~carb) +
force_panelsizes(rows = unit(5, "cm"), cols = unit(2, "in"))
print(p1)
}
I also tried facet_wrap2
from the same package, but the result was similar to the first try using size options in the chunk.
So, how can I make the size of each panel to be the same across figures with diferent numbers of panels without having the figures so fart apart from each other?
Thanks in advance!
One option would be to use a child document to render plots where I sticked with your ggh4x
approach to fix the panel sizes. Doing so allows to have each plot in a separate chunk with an individual plot height.
---
title: gg-loop
output: html_document
date: "2024-01-17"
---
```{r include=FALSE}
library(tidyverse)
library(ggh4x)
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- mtcars |> filter(carb %in% 1:2)
mylist[[3]] <- mtcars |> filter(carb == 1)
```
```{r results='asis', echo = FALSE}
res <- lapply(seq_along(mylist), \(i) {
knitr::knit_child("gg-child.Rmd", envir = environment(), quiet = TRUE)
})
cat(unlist(res), sep = "\n")
```
```{r echo=FALSE, fig.height= 6.5 * (if (i == 1) 2 else 1) / 2.54}
ggplot(mylist[[i]], aes(group = gear, y = wt)) +
geom_boxplot() +
facet_wrap(~carb) +
force_panelsizes(rows = unit(5, "cm"), cols = unit(2, "in"))
```