Home > Blockchain >  Arranging two forestplots into a single graphic without overlap of elements
Arranging two forestplots into a single graphic without overlap of elements

Time:10-10

I have created several plots using the forestplot package and the link shown here. <https://cran.r-project.org/web/packages/forestplot/vignettes/forestplot.html > Great package with beautiful plots in my own data.

Next step is to combine two plots into a single graphic. The code provided on the link results in 'bleeding' of the graphics/text into each other. I don't want to clip it as I need the text elements. I am guessing the problem involves the combination of text and graphics in the 'plot'. I fooled around with the original post and also did some hunting online but no luck Thanks in advance.

library(foresplot)
data("dfHRQoL")

#create individual forest plots for Sweden and Denmark
fp_sweden <- dfHRQoL |> 
  filter(group == "Sweden") |> 
  mutate(est = sprintf("%.2f", mean), .after = labeltext) |> 
  forestplot(labeltext = c(labeltext, est), 
             title = "Sweden",
             clip = c(-.1, Inf),
             xlab = "EQ-5D index",
             new_page = FALSE)

fp_denmark <- dfHRQoL |> 
  filter(group == "Denmark") |> 
  mutate(est = sprintf("%.2f", mean), .after = labeltext) |> 
  forestplot(labeltext = c(labeltext, est), 
             title = "Denmark",
             clip = c(-.1, Inf),
             xlab = "EQ-5D index",
             new_page = FALSE)



#now combine into a single plot using the web code; but this one bleeds into each other
library(grid)

#####
#Put plots together using grid graphics
#Attempt 1 from website

#####
grid.newpage()
borderWidth <- unit(4, "pt")
width <- unit(convertX(unit(1, "npc") - borderWidth, unitTo = "npc", valueOnly = TRUE)/2, "npc")
pushViewport(viewport(layout = grid.layout(nrow = 1, 
                                           ncol = 3, 
                                           widths = unit.c(width,
                                                           borderWidth,
                                                           width))
)
)
pushViewport(viewport(layout.pos.row = 1,
                      layout.pos.col = 1))
fp_sweden 
upViewport()
pushViewport(viewport(layout.pos.row = 1,
                      layout.pos.col = 2))
grid.rect(gp = gpar(fill = "grey", col = "red"))
upViewport()
pushViewport(viewport(layout.pos.row = 1,
                      layout.pos.col = 3))
fp_denmark 
upViewport(2)


####
#Attempt 2 from website, still a problem. 
####
grid.newpage()
borderWidth <- unit(4, "pt")
width <- unit(convertX(unit(1, "npc") - borderWidth, unitTo = "npc", valueOnly = TRUE)/2, "npc")
pushViewport(viewport(layout = grid.layout(nrow = 1, 
                                           ncol = 3, 
                                           widths = c(0.45, 0.1, 0.45))
)
)
pushViewport(viewport(layout.pos.row = 1,
                      layout.pos.col = 1))
fp_sweden 
upViewport()

pushViewport(viewport(layout.pos.row = 1,
                      layout.pos.col = 3))
fp_denmark 
upViewport(2)

###
#Attempt 3 converting to grobs and use patchwork 
###
library(ggplotify)
library(patchwork)

fpd_grob <- grid2grob(print(fp_denmark))

p1 <- grid2grob(print(fp_denmark))
p2 <- grid2grob(print(fp_sweden))
p_both <- wrap_elements(p1)   wrap_elements(p2)
p_both

#same problem with grid.arrange()**strong text**

CodePudding user response:

While I appreciate your effort to achieve your desired result using forestplot sometimes IMHO it might be worthwhile to get rid of out-of-the-box solutions and build plots from scratch.

Hence, if taking this route is an option for you then my code below provides a possible approach using ggplot2. This requires some effort to achieve the forestplot look but in the end requires less effort in searching for some solution and gives you a lot of options for customization:

Note: One thing I was not able to figure out is what determines the size of the mean points. Hence I simply mapped the mean on size.

data("dfHRQoL", package = "forestplot")

library(dplyr)
library(ggplot2)

th_lower <- -.1

dfHRQoL <- dfHRQoL |>
  mutate(est = sprintf("%.2f", mean), .after = labeltext) |>
  mutate(
    arrow_lower = lower < th_lower,
    lower = pmax(lower, th_lower),
    y_label = paste(labeltext, est)
  )

ggplot(dfHRQoL, aes(y = labeltext, yend = labeltext))  
  geom_vline(xintercept = 0, color = "grey80")  
  geom_segment(data = ~ subset(.x, !arrow_lower), aes(x = lower, xend = upper), 
               size = .25, color = "grey80")  
  geom_segment(data = ~ subset(.x, arrow_lower), aes(x = lower, xend = upper), 
               size = .25, color = "grey80", arrow = arrow(ends = "first"))  
  geom_point(aes(x = mean, size = mean), shape = 15)  
  geom_text(aes(x = th_lower * 1.2, label = est), hjust = 1, 
            size = .8 * 11 / .pt, color = "grey30")  
  facet_wrap(~group, scales = "free_y")  
  theme_minimal()  
  theme(
    panel.grid = element_blank(),
    axis.line.x = element_line(),
    axis.ticks.x = element_line(),
    axis.ticks.length.x = unit(5, "pt"),
    strip.text.x = element_text(face = "bold"),
    axis.text.y = element_text(hjust = 0, margin = margin(r = 20))
  )  
  coord_cartesian(clip = "off")  
  labs(x = "EQ-5D index", y = NULL)  
  guides(size = "none")

CodePudding user response:

This problem is most likely due to that your font size is too large and the text doesn't fit. I suggest that you try to enlarge the image. I've tested with the latest 3.1.0 in the vignette and it works there.

  • Related