初识森林图(Forest plot),依稀记得是大学时候Meta分析课程。后来阅读SCI后发现,越来越多论文中用森林图来取代多因素回归做结果展示,包括主效应、交互作用、分层分析等,展现形式也愈发多样化。正巧最近论文修回需要用到一些高阶段位森林图,那这期笔者就打算盘它了,将常见original article森林图套路分享如下。友情提示,本章图片较多请耐心阅读。
多因素结果的森林图与meta分析森林图形态近似,最大区别是没有文献合并效应量。多因素森林图在平面直角坐标系中,以一条垂直于X轴的无效线(通常坐标X=1[对应OR、RR、HR等分类型effect size]或0[对应RD、AD、β等连续型effect size])为中心,用若干条平行于X轴的线段,来表示每个变量的效应量大小及其95%可信区间。简而言之,就是Effect size 图形化。
人狠话不多,直接上套路。
窈窕淑女,君子好逑。掌握本章节介绍的forestplot、forestploter、ggforestplot、以及ggplot2,小伙伴们就拥有了再进一步拥抱高水平论文的可能性。小伙伴们可以阅读后自行DIY各杂志的主题色。
1. forestplot包
此包是较成熟且较早期的包,折腾后实现功能有限,不过重在便捷。
library('ggplot2')
setwd("D:/聂个人文件/我的公众号/森林图")
#-------① 经典款 带空格 森林图绘制,forest_model2.xlsx
#------- 1.forestplot包,仅亚组
library(forestplot)
library(readxl)
library(haven)
forest <- read_excel("forest_model2.xlsx",sheet = "subgroup")
#subgps缩进
subgps <- c(3,4,7,8,11,12,15,16,19,20,23,24,25,26)
forest$Variable[subgps] <- paste(" ",forest$Variable[subgps])
attach(forest)
labeltext <- as.matrix(forest[,1:2])
#设定字体
windowsFonts(myFont1 = windowsFont("Times New Roman"))
forestplot(labeltext,
mean = OR, #分类effect size
lower = LowerCI,
upper = UpperCI,
zero = 1.0, lwd.zero = 2, # 参考线X=1,粗2
xlab = "←Low risk High risk →", #x标签
xticks = c(0,1,2,3),
lwd.xaxis = 2,
boxsize = 0.5, #设置中心大小
lty.ci = 1, lwd.ci = 2, #设置区间估计线的"solid",粗细
col=fpColors(box='#6495ED',summary="#8B008B",lines = '#98C9F6',zero = '#000000'),
#颜色从左至右分别点估计方形,汇总值,区间估计线'black',参考线 橙色#FFDD00
ci.vertices = TRUE,
ci.vertices.height = 0.2,
align = "l",
is.summary= c(T,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,F),
#每一行是否是汇总值,粗体, all时会变紫色
txt_gp = fpTxtGp(label = gpar(cex = 1.15, fontfamily="myFont1"),
ticks = gpar(cex = 1.20),
xlab = gpar(cex = 1.45)),
grid= T, #在x轴对应的单位间隔上做垂直的虚线参考线
graphwidth = unit(6,"cm"), #调节95%可信区间作图的宽度
graph.pos = 3 ) #设置森林图的位置,此处设置为3,则出现在第3列
#------- 2.forestplot包,all+ 亚组
pacman::p_load(forestplot,readxl,haven)
forest <- read_excel("forest_model2.xlsx",sheet = "allsub")
#subgps缩进
subgps <- c(1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,27,28)
forest$Variable[subgps] <- paste(" ",forest$Variable[subgps])
attach(forest)
#文本展示前2列
labeltext <- as.matrix(forest[,1:2])
#设定字体
windowsFonts(myFont1 = windowsFont("Times New Roman"))
forestplot(labeltext,
mean = OR, #分类effect size
lower = LowerCI,
upper = UpperCI,
zero = 1.0, lwd.zero = 2, # 参考线X=1,粗2
xlab = "←Low risk High risk →", #x标签
xticks = c(0,1,2,3),
clip=c(0,3),#设置 CI显示的上下限,超过变箭头,适用于异常OR HR
lwd.xaxis = 2, #x垂直线粗细
boxsize = 0.5, #设置中心大小
lineheight = unit(6,'mm'),#设置图形中的行距
colgap = unit(2,'mm'),#设置图形中的列间距
lty.ci = 1, lwd.ci = 2, #设置区间估计线的"solid",粗细
col=fpColors(box='#6495ED',summary="#8B008B",lines = '#98C9F6',zero = '#000000'),
#颜色从左至右分别点估计方形,汇总值,区间估计线'black',参考线 橙色#FFDD00
ci.vertices = TRUE,
ci.vertices.height = 0.3, #CI端天线高度
align = "l",
is.summary= c(T,T,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,F),
#每一行是否是汇总值,其实仅表现粗体
txt_gp = fpTxtGp(label = gpar(cex = 1.2, fontfamily="myFont1"),
ticks = gpar(cex = 1.2),
xlab = gpar(cex = 1.2)),
grid= F, #在x轴对应的单位间隔上做垂直的虚线参考线
graphwidth = unit(6,"cm"), #调节95%可信区间作图的宽度
graph.pos = 3 ) #设置森林图的位置,此处设置为3,则出现在第3列
#------- 3.forestplot包,all+ 亚组+多列
pacman::p_load(forestplot,readxl,haven)
forest <- read_excel("forest_model2.xlsx",sheet = "casen")
#subgps缩进
subgps <- c(1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,27,28)
forest$Variable[subgps] <- paste(" ",forest$Variable[subgps])
attach(forest)
#文本展示前3列
labeltext <- as.matrix(forest[,1:3])
#设定字体
windowsFonts(myFont1 = windowsFont("Times New Roman"))
forestplot(labeltext,
mean = OR, #分类effect size
lower = LowerCI,
upper = UpperCI,
zero = 1.0, lwd.zero = 2, # 参考线X=1,粗2
xlab = "←Low risk High risk →", #x标签
xticks = c(0,1,2,3),
clip=c(0,3),#设置 CI显示的上下限,超过变箭头,适用于异常OR HR
lwd.xaxis = 2, #x垂直线粗细
boxsize = 0.5, #设置中心大小
lineheight = unit(6,'mm'),#设置图形中的行距
colgap = unit(2,'mm'),#设置图形中的列间距
lty.ci = 1, lwd.ci = 2, #设置区间估计线的"solid",粗细
col=fpColors(box='#6495ED',summary="#FF0000",lines = '#98C9F6',zero = '#000000'),
#颜色从左至右分别点估计方形,汇总值,区间估计线'black',参考线 橙色#FFDD00
ci.vertices = TRUE,
ci.vertices.height = 0.3, #CI端天线高度
align = "l",
is.summary= c(T,T,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,T,F,F,F,F),
#每一行是否是汇总值,其实仅表现粗体
txt_gp = fpTxtGp(label = gpar(cex = 1.2, fontfamily="myFont1"),
ticks = gpar(cex = 1.2),
xlab = gpar(cex = 1.2)),
grid= F, #在x轴对应的单位间隔上做垂直的虚线参考线
graphwidth = unit(6,"cm"), #调节95%可信区间作图的宽度
graph.pos = 3 ) #设置森林图的位置,此处设置为3,则出现在第3列
#------- 4.forestplot包,all+ 亚组+多列+ 无空格
pacman::p_load(forestplot,readxl,haven)
forest <- read_excel("forest_model2.xlsx",sheet = "noblank")
#subgps缩进
subgps <- c(4,5,7,8,10,11,13,14,16,17,19,20,21,22)
forest$Variable[subgps] <- paste(" ",forest$Variable[subgps])
attach(forest)
#文本展示前3列
labeltext <- as.matrix(forest[,1:3])
#设定字体
windowsFonts(myFont1 = windowsFont("Times New Roman"))
forestplot(labeltext,
mean = OR, #分类effect size
lower = LowerCI,
upper = UpperCI,
zero = 1.0, lwd.zero = 2, # 参考线X=1,粗2
xlab = "←Low risk High risk →", #x标签
xticks = c(0,1,2,3),
clip=c(0,3),#设置 CI显示的上下限,超过变箭头,适用于异常OR HR
lwd.xaxis = 2, #x垂直线粗细
boxsize = 0.5, #设置中心大小
lineheight = unit(6,'mm'),#设置图形中的行距,默认6mm
colgap = unit(2,'mm'),#设置图形中的列间距
lty.ci = 1, lwd.ci = 2, #设置区间估计线的"solid",粗细
col=fpColors(box='#6495ED',summary="#FF0000",lines = '#98C9F6',zero = '#000000'),
#颜色从左至右分别点估计方形,汇总值,区间估计线'black',参考线 橙色#FFDD00
ci.vertices = TRUE,
ci.vertices.height = 0.3, #CI端天线高度
align = "l",
#区别在summary,加粗合并
is.summary= c(T,T,T,F,F,T,F,F,T,F,F,T,F,F,T,F,F,T,F,F,F,F),
#每一行是否是汇总值,其实仅表现粗体
txt_gp = fpTxtGp(label = gpar(cex = 1.2, fontfamily="myFont1"),
ticks = gpar(cex = 1.2),
xlab = gpar(cex = 1.2)),
grid= F, #在x轴对应的单位间隔上做垂直的虚线参考线
graphwidth = unit(6,"cm"), #调节95%可信区间作图的宽度
graph.pos = 3 ) #设置森林图的位置,此处设置为3,则出现在第3列
2. forestploter包
笔者将珍藏级主题放出,感兴趣的小伙伴自行重现,才能学的深刻。
#------- 5 forestploter包绘制,casen_name数据,无空格,有空行会出现NA,
# install.packages("devtools")
# devtools::install_github("adayim/forestploter")
pacman::p_load(forestploter,readxl,haven)
forest<- read_excel("forest_model2.xlsx",sheet = "casen_name")
#第二种缩进方法,更智能
forest$Subgroups <- ifelse(is.na(forest$"Event/patients"),
forest$Subgroups,
paste0(" ", forest$Subgroups))
#再创建一列空列,用来后面存放森林图的图形部分,长度20
forest$` ` <- paste(rep(" ", 20), collapse = " ")
#本段自动 OR95%CI 拼接
# forest$`OR (95% CI) AUTO` <- ifelse(is.na(forest$OR), "",sprintf("%.2f (%.2f to %.2f)",forest$OR, forest$LowerCI, forest$UpperCI))
#这里要注意,保留前3列信息+空白列!
# 注意,NA 需要转换为空白!.
forest$"Event/patients" <- ifelse(is.na(forest$"Event/patients"), "", forest$"Event/patients")
forest$"OR (95%Cl)" <- ifelse(is.na(forest$"OR (95%Cl)"), "", forest$"OR (95%Cl)")
plot1 <- forest(forest[, c(1:3,7)],
est = forest$OR,
lower = forest$LowerCI,
upper = forest$UpperCI,
ci_column = 4,
# sizes=forest$OR, #等比例放大方框,不美观
# is_summary=c(TRUE,rep(FALSE, nrow(forest)-1)), #第一行汇总
# is_summary=c(rep(FALSE, nrow(forest)-1),TRUE), #最后一行汇总
ref_line = 1, #参考线x=1
arrow_lab = c("Low risk", "High risk"),
xlim = c(0, 3),ticks_at = c(0, 1, 2, 3)#设置X范围,超范围带箭头
)
plot1
3. ggplot2包
全部自定义,后期PDF转PPT后需要手动编辑对齐。
4. ggforestplot包
如果risk很多>20个,需要一起展示,那请毫不犹豫的用吧。
森林图R包很多很多,不光有forestploter、forestplot、ggforestplot,其实还有forplo、survminer::ggforest()函数等偏门的包。本章并未详细介绍meta的森林图,请小伙伴一切按论文需求,选择最优图形。如果有不会R的小伙伴,请关注下期更加友好的Excel篇。
参考文献:
原创不易,转载请说明来自本公众号。