rr-gridr-forestplot

How to assign unique colors to multiple vertical lines in R forestplot?


I am using forestplot and want to put a series of vertical lines in the figure. I am successful adding as many lines as I want, using the grid argument. But, I would like to assign a different color to each line, and so far I can only get them to share the same color.

library(dplyr)
library(forestplot)

df <- data.frame(
  model_name = rep(c('A','B','C','D'),3),
  group = c(rep("Qrt 2",4),rep("Qrt 3",4),rep("Qrt 4",4)),
  mean =  c(10, 9.5,  10.5,  11, 5, 4.75, 5.25, 5.05, 2,   1.9, 1.8, 1.7),
  lower = c(9,  8.5,  9.5,   10, 4, 4,    4.5,  4.25, 1.7, 1.6, 1.7, 1.65),
  upper = c(11, 10.5, 10.75, 12, 6, 5,    5.5,  5.8,  2.3, 2.2, 1.9, 1.75)
)

df |>
  group_by(group) |>
  forestplot(
    title = "Test Forest Plot",
    labeltext = model_name,
    boxsize = 0.2,
    vertices = TRUE,
    grid = structure(c(df[1,3], df[5,3], df[9,3]),
                     gp = gpar(lty = c(1,2,2), # line types other than the first one are ignored!
                               col = c("blue","green","red")))) |> # red and green are ignored!
  fp_set_style(box = c("blue", "green", "red"), # no problems with these colors, tho
               line = c("blue", "green", "red")) |>
  fp_add_header(model_name = c("Model")) |>
  fp_add_lines(h_2 = gpar(lwd = 1),
               h_3 = gpar(lwd = 1),
               h_4 = gpar(lwd = 1),
               h_5 = gpar(lwd = 1),
               h_6 = gpar(lwd = 1))

Result:

Forest plot but the 3 vertical lines are all blue

The 3 added vertical lines are all blue, but I want them to be blue, green, and red, corresponding to the color of the respective group (i.e, blue, green, red, from right to left). I don't care about the gray zero line, I'm ignoring it for now.

I've tried various permutations of structure(), c(), and list() encompassing the arguments passed to grid, but no luck so far. I've also experimented with fpColor: col = fpColors(vrtcl_lines = c("blue","green","red")) But, same lack of results.

It would also be nice to individually control line types, and I'm hoping that if I can solve the color problem, then the line type problem can be solved analogously.

Can anyone advise me how, if it's possible? Thanks for your consideration. (edit: made color order consistent in the text)


Solution

  • Define shapes_gp of the forestplot() function using a fpShapesGp object, which controls the graphical parameters of all the non-text elements.

    library(dplyr)
    library(forestplot)
    
    # Create your 'styles'
    styles <- fpShapesGp(grid = list(
          gpar(lty = 1, col = "blue"),
          gpar(lty = 2, col = "green"),
          gpar(lty = 2, col = "red")))
    
    # Provide your 'styles' to shapes_gp
    df |>
      group_by(group) |>
      forestplot(
        title = "Test Forest Plot",
        labeltext = model_name,
        boxsize = 0.2,
        vertices = TRUE,
        grid = c(df[1,3], df[5,3], df[9,3]),
        shapes_gp = styles) |>
      fp_set_style(box = c("blue", "green", "red"),
                   line = c("blue", "green", "red")) |>
      fp_add_header(model_name = c("Model")) |>
      fp_add_lines(h_2 = gpar(lwd = 1),
                   h_3 = gpar(lwd = 1),
                   h_4 = gpar(lwd = 1),
                   h_5 = gpar(lwd = 1),
                   h_6 = gpar(lwd = 1))
    

    shapes_gp-styles


    Raw data

    df <- data.frame(
      model_name = rep(c('A','B','C','D'),3),
      group = c(rep("Qrt 2",4),rep("Qrt 3",4),rep("Qrt 4",4)),
      mean =  c(10, 9.5,  10.5,  11, 5, 4.75, 5.25, 5.05, 2,   1.9, 1.8, 1.7),
      lower = c(9,  8.5,  9.5,   10, 4, 4,    4.5,  4.25, 1.7, 1.6, 1.7, 1.65),
      upper = c(11, 10.5, 10.75, 12, 6, 5,    5.5,  5.8,  2.3, 2.2, 1.9, 1.75)
    )