guido-s / meta

Official Git repository of R package meta
http://cran.r-project.org/web/packages/meta/index.html
GNU General Public License v2.0
82 stars 32 forks source link

Adjust PDF size to plot size #23

Closed SBCV closed 4 years ago

SBCV commented 4 years ago

For each of my meta analyses, I use something like the following code snippet to create a pdf file with a single forest plots.

pdf(file=output_file_path, width=8, height=3)
meta::forest(...)
dev.off()

Since I perform many different meta analyses with varying number of studies, the amount of (white) space above / below the plot is different for each analysis.

I would like to automatically adjust the value of height for each study. As far as I can see it is difficult to determine the height of meta::forest(...), since the function does not return an object. Am I missing something here?

I found the following information in the documentation:

The forest function is based on the grid graphics system. In order to print the forest plot, (i) resize the graphics window, (ii) either use dev.copy2eps or dev.copy2pdf.

However, I'm afraid that this is a bit unclear to me.

Any help would be highly appreciated!

Bests, Sebastian

guido-s commented 4 years ago

R functions dev.copy2eps() and dev.copy2pdf() can only be used interactively.

I am sorry, however, I do not know an easy way to determine the height of the forest plot under the grid graphics system. I typically do not generate lots of forest plots and thus set the height and width of the PDF file manually.

You could use the number of studies in your meta-analyses in order to (semi-)automatically set the height of the PDF file. E.g.,

setheight <- function(k, cutpoints, heights) {
 height <- heights[as.numeric(cut(k, c(0, cutpoints)))]
 height
}
# Set height:
# k = 1 - 5 -> 3
# k = 6 - 10 -> 4
# k = 11 - 15 -> 5
# k = 16 - 20 -> 6
#
m1 <- metagen(1:20, rep(1, 20))
m2 <- metagen(1:10, rep(1, 10))
pdf("a.pdf",
    height = setheight(m1$k, c(5, 10, 15, 20), 3:6),
    width = 9)
forest(m1)
dev.off()
pdf("b.pdf",
    height = setheight(m2$k, c(5, 10, 15, 20), 3:6),
    width = 9)
forest(m2)
dev.off()

In setheight() you could also use default settings for the arguments 'cutpoints' and 'heights'.

SBCV commented 4 years ago

Thanks for the quick reply!

I found another solution that determines the actual plot size with a high accuracy - maybe it is useful for someone else.

setheight <- function(k) {

  # fixed_height represents space required by fixed elements such as 
  #   the headlines of the columns
  #   the line required for the fixed / random effects model (only one, not both)
  #   the space required for the axis (including ticks) at the bottom of the plot
  fixed_height = 1.35

  # dynamic_height increases with the number of studies (one row for each study)
  row_height = 0.2
  dynamic_height = row_height * k

  # this adds some more white space to the bottom of the plot, 
  # in order to make it symmetric with the white space in above the plot
  bottom_space = 0
  #bottom_space = 3 * row_height

  total_height = fixed_height + dynamic_height + bottom_space
  return (total_height)
}

m1 <- meta::metagen(1:20, rep(1, 20))
m2 <- meta::metagen(1:10, rep(1, 10))
m3 <- meta::metagen(1:2, rep(1, 2))
pdf("a.pdf",
    height = setheight(m1$k),
    width = 9)
meta::forest(m1, comb.fixed = FALSE)
dev.off()
pdf("b.pdf",
    height = setheight(m2$k),
    width = 9)
meta::forest(m2, comb.fixed = FALSE)
dev.off()
pdf("c.pdf",
    height = setheight(m3$k),
    width = 9)
meta::forest(m3, comb.fixed = FALSE)
dev.off()
daattali commented 2 years ago

I came across a similar issue. I want to use the forest plot in a shiny app so I need to know what height to use. This might not work for everyone, but in my case the following seems to work well for the plot output height:

  output$plot <- renderPlot({
    meta::forest(...)
  }, height = function() 115 + num_studies() * 15)

where num_studies() is a reactive variable that has the number of studies. For example, if there are 10 studies, then the plot height should be 115+10*15 = 265

guido-s commented 1 year ago

I finally found time to address this issue. Forest plots can be saved directly in a file in R function forest.meta() which determines the height of the graphics file using the internal function meta:::gh; see news(package = "meta") and help("forest.meta"), subsection "Saving forest plots".

daattali commented 1 year ago

@guido-s If I understand your comment correctly, the issue of choosing a size for saving a file is fixed. But the issue I reported, where I want to choose a size for the plot in a shiny app, is not addressed, correct?

guido-s commented 1 year ago

@daattali

I just added a new list element 'figheight' to the invisibly return list of forest.meta().

Something like rows = meta::forest(...)$figheight$total_rows should work to determine the approximate number of rows in the forest plot.