I am trying to plot multiple plots (of different sizes) onto a grid, using specific coordinates. To do this, I am creating a treemap using the treemap
package to get coordinates and then, using these coordinates, Im trying to place my individual plots. Hopefully my example below will explain better my problem.
To begin, I create some barplots and then, I create a treemap, like so:
library(ggplot2)
library(treemap)
#create data
df <- data.frame(var1 = c("A", "B", "C"),
var2 = runif(3),
var3 = runif(3),
var4 = runif(3),
size = c(10, 5, 3),
labels = c(1:3))
# Basic barplot
p1 <- ggplot(data=df, aes(x=var1, y=var2)) +
geom_bar(stat="identity")
p2 <- ggplot(data=df, aes(x=var1, y=var3)) +
geom_bar(stat="identity")
p3 <- ggplot(data=df, aes(x=var1, y=var4)) +
geom_bar(stat="identity")
#create treemap
tm <- treemap(df,
index = "labels",
vSize = "size",
palette = "Set2")
If we take a look at the treemap object tm
, we can see that it provides the coordinates of the treemap shown below, where x0
, y0
, w
, and h
are the coordinates.
> tm$tm
labels vSize vColor stdErr vColorValue level x0 y0 w h color
1 1 10 1 10 NA 1 0.0000000 0.000 0.5555556 1.000 #66C2A5
2 2 5 1 5 NA 1 0.5555556 0.375 0.4444444 0.625 #FC8D62
3 3 3 1 3 NA 1 0.5555556 0.000 0.4444444 0.375 #8DA0CB
So, what Im trying to do is to take my three barplots p1
,p2
,and p3
and place them into the treemap so that p1
will be in position 1
of the treemap.... p2
will be in position 2
etc...
For clarity, My desired result would look something like this:
Any suggestions as to how I could do this? I tried using the patchwork
package but ran into issues of the plots overlapping... but im open to suggestions using any package (eg gridExtra
or just ggplot
)
EDIT
to clarify things a little, as per the answer given by Peter below in relation to the patchwork
package, I cant manually input the coordinates as the plot layout (I was originally using the area
function in patchwork
and inputting the coordinates of the treemap into the area
function). But, as mentioned in the comments below, if I have numerous barplots, and the size and shape of the treemap changes, then I cant manually input the layout values. I am trying to find a way to automate the process
This requires some arithmetic, and isn't perfect, but should be a start toward using patchwork
's more complex layout options. There are a couple tricks to address:
treemap
scales its dimensions based on the viewport, which means the positions it calculates depend on the viewer in e.g. RStudio's plot pane. Instead, it's not strictly necessary, but you should probably decide on an aspect ratio to make sure the positions of boxes are something you'd want.library(ggplot2)
library(treemap)
library(dplyr)
asp <- 1.25
tm <- treemap(df, index = "labels", vSize = "size", palette = "Set2", sortID = "labels",
aspRatio = asp)
denoms <- tm$tm %>%
tidyr::pivot_longer(w:h, names_to = "direction") %>%
filter(value < 1) %>%
group_by(direction) %>%
slice_max(value, n = 1) %>%
mutate(denom = MASS::fractions(value) %>%
stringr::str_extract("\\d+$") %>%
as.numeric()) %>%
select(direction, denom) %>%
tibble::deframe()
denoms
#> h w
#> 8 9
areas <- tm$tm %>%
mutate(across(c(x0, w), ~. * denoms[["w"]]),
across(c(y0, h), ~. * denoms[["h"]]),
top = y0 + 1,
left = x0 + 1,
bottom = top + h - 1,
right = left + w - 1) %>%
select(top:right) %>%
purrr::pmap(function(top, left, bottom, right) patchwork::area(top, left, bottom, right)) %>%
purrr::reduce(c)
patchwork::wrap_plots(p1, p2, p3, design = areas)