查看原文
其他

画一个好看的森林图

阿越就是我 医学和生信笔记 2023-02-25
关注公众号,发送R语言,获取学习资料!


目前使用R语言画森林图用的最多的应该是forestplot包(除外meta分析的森林图),在网络上找了很多这个包的介绍,但是都不全,而且这个包细节太多,也不支持图层语法,很难画出高质量的森林图。

最近手头又有一些工作需要用到森林图,于是更加认真地学习了这个包的用法,终于对这个包有了一些新的理解。

这个包主要是需要的数据格式比较复杂,需要各种占位符、NA等构成一些视觉效果,我们可以先在csv表格里把数据整理好。此包在画森林图时,最主要的是2个部分,一个是文字部分,即图中红框框住的部分,另一部分就是中间的森林图部分,其余的都是细节修改问题,只要足够耐心,就一定能调整到自己满意。

forest plot

接下来将详细介绍使用forestplot包画森林图(非meta分析森林图)。

以后还会介绍其他绘制森林图的方法。


  • 前言

  • 构造数据

  • 基本森林图

  • 细节调整

    • 加横线和竖线

    • 控制横坐标标签

    • 增加标题,调整各组件大小

  • 有亚组的森林图


前言

一整个森林图可以看成一个个单元格组成的,和你的数据格式一模一样,如果没有数据的地方用NA填充即可。

文字部分和森林图部分的数据可以放在一起,也可以分开准备,文字部分你可以自由添加各种内容,只要格式正确就可以画出来。

文字部分如果是用csv准备的,记得把单元格格式设置为文本,方便设置各种缩进。

一个最基本的森林图只要提供以下4个参数即可完成:

forestplot(
  tabletext = xxx,
  lower = aaa,
  upper = bbb,
  mean = ccc,
)

构造数据

下面介绍一个简单的例子,文字部分和森林图部分是分开的。

# 这个包竟然支持管道符!但其实我觉得不实用
library(forestplot)
## 载入需要的程辑包:grid
## 载入需要的程辑包:magrittr
## 载入需要的程辑包:checkmate

# 构造森林图部分的数据,需要最大值最小值和均值3列,需要是数据框格式
df <- data.frame(
  mean  = c(NANA0.5780.1650.2460.7000.3480.1391.017NA0.531), 
  lower = c(NANA0.3720.0180.0720.3330.0830.0160.365NA0.386),
  upper = c(NANA0.8981.5170.8331.4741.4551.2092.831NA0.731)
  )

df
##     mean lower upper
## 1     NA    NA    NA
## 2     NA    NA    NA
## 3  0.578 0.372 0.898
## 4  0.165 0.018 1.517
## 5  0.246 0.072 0.833
## 6  0.700 0.333 1.474
## 7  0.348 0.083 1.455
## 8  0.139 0.016 1.209
## 9  1.017 0.365 2.831
## 10    NA    NA    NA
## 11 0.531 0.386 0.731
# 构造文字部分的数据,需要矩阵格式
# 使用  \n  换行
tabletext <- cbind(
  c("""Study""Auckland""Block""Doran""Gamsu""Morrison""Papageorgiou""Tauesch"NA"Summary"),
  c("Deaths\ntest""(steroid)""36""1""4""14""3""1""8"NANA),
  c("Deaths\njust show""(placebo)""60""5""11""20""7""7""10"NANA),
  c("""OR""0.58""0.16""0.25""0.70""0.35""0.14""1.02"NA"0.53")
  )

tabletext
##       [,1]           [,2]           [,3]                [,4]  
##  [1,] ""             "Deaths\ntest" "Deaths\njust show" ""    
##  [2,] "Study"        "(steroid)"    "(placebo)"         "OR"  
##  [3,] "Auckland"     "36"           "60"                "0.58"
##  [4,] "Block"        "1"            "5"                 "0.16"
##  [5,] "Doran"        "4"            "11"                "0.25"
##  [6,] "Gamsu"        "14"           "20"                "0.70"
##  [7,] "Morrison"     "3"            "7"                 "0.35"
##  [8,] "Papageorgiou" "1"            "7"                 "0.14"
##  [9,] "Tauesch"      "8"            "10"                "1.02"
## [10,] NA             NA             NA                  NA    
## [11,] "Summary"      NA             NA                  "0.53"

OK,基本的数据就都准备好了,接下来就是画图。

数就是图,图就是数!

基本森林图

一个基本的森林图:

# 画图
forestplot(labeltext = tabletext, 
             lower = df$lower,
             upper = df$upper,
             mean = df$mean)

一个最基本的森林图就画好了,接下来就是各种细节的调整!

细节调整

先简单调整一下:

forestplot(labeltext = tabletext, 
           lower = df$lower,
           upper = df$upper,
           mean = df$mean,
           
           # 这个参数设置每一行的文字部分是否加粗,一行一个逻辑值表示是否加粗,构成一个向量,
           is.summary = c(rep(TRUE2), rep(FALSE8), TRUE),
           
           # 加横线,默认加3条,类似三线表,可以自由控制添加位置
           hrzl_lines = gpar(col = "#444444"),
           
           clip = c(0.12.5), # 控制箭头
           xlog = TRUE# 横坐标是否转换,可以看到竖线变成1的位置了,也可以通过zero=1设置
           
           # fpColors控制森林图部分的各组件颜色
           col = fpColors(box = "royalblue"# 正方形颜色
                          lines = "red"# 误差线颜色
                          summary = "black"# 汇总标志颜色
                          zero = "yellow" # 0(1)竖线的颜色
                          )
           )
unnamed-chunk-5-139606198

加横线和竖线

修改横线的位置和粗细,以达到一种层次感,不过需要多次调整才能达到自己想要的效果。

forestplot(labeltext = tabletext, 
           lower = df$lower,
           upper = df$upper,
           mean = df$mean,
           
           # 这个参数设置每一行的文字部分是否加粗,一行一个逻辑值表示是否加粗,构成一个向量,
           is.summary = c(rep(TRUE2), rep(FALSE8), TRUE),
           
           # 加横线,控制位置,第一行文字上面序号是1,下面序号是2,第2行文字下面序号是3,以此类推
           # column参数控制横线出现在哪几列
           hrzl_lines = list("1" = gpar(lwd = 2),
                             "3" = gpar(lwd = 2), 
                             "4" = gpar(lwd = 60, lineend="butt",col = "#99999922"),
                             "8" = gpar(lwd = 60, lineend="butt",col = "#99999922"),
                             "11" = gpar(lwd = 2, columns = 1:4)
                             )
           )
unnamed-chunk-6-139606198

加竖线,误差线两头也变成竖线:

forestplot(labeltext = tabletext, 
           lower = df$lower,
           upper = df$upper,
           mean = df$mean,
           
           # 这个参数设置每一行的文字部分是否加粗,一行一个逻辑值表示是否加粗,构成一个向量,
           is.summary = c(rep(TRUE2), rep(FALSE8), TRUE),
           
           vertices = TRUE# 误差线末尾加竖线
           
           # 加竖线,可以直接用TRUE
           grid = structure(c(0.5,11.5), 
                              gp = gpar(lty = 2, col = "#CCCCFF")), 
           )
unnamed-chunk-7-139606198

控制横坐标标签

forestplot(labeltext = tabletext, 
           lower = df$lower,
           upper = df$upper,
           mean = df$mean,
           
           # 这个参数设置每一行的文字部分是否加粗,一行一个逻辑值表示是否加粗,构成一个向量,
           is.summary = c(rep(TRUE2), rep(FALSE8), TRUE),
           
           xticks = c(0.1,0.5,1,1.5,2)
           )
unnamed-chunk-8-139606198

再稍加调整,就可以变成下面这个样子:

unnamed-chunk-9-139606198

有亚组的森林图也是一样的套路:

000016

增加标题,调整各组件大小

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存