在Meta分析中森林图比较常见,其主要是是以统计指标和统计分析方法为基础,用数值运算结果绘制出的图型。它在平面直角坐标系中,以一条垂直的无效线(横坐标刻度为1或0)为中心,用平行于横轴的多条线段描述了每个被纳入研究的效应量和可信区间,用一个棱形(或其它图形)描述了多个研究合并的效应量及可信区间。它非常简单和直观地描述了Meta分析的统计结果,是Meta分析中最常用的结果表达形式。
森林图的类型主要包括以下两种:
1. 二值变量的森林图
当研究对象为二值变量(如发生与不发生)时,采用RR和OR作为统计学指标。
RR(risk ratio,危险比率)=发生某一事件的人数/观察的总人数。
OR(odds ratio,比值比)=发生某一事件的人数/未发生某事件的人数。
2. 连续性变量的森林图
分析指标是连续变量,也称数值变量,可选择加权均数差(WMD)或标准化均数差(SMD)为合并统计量。
加权均数差(weighted mean difference)是对每个研究的均数进行加权处理。
大样本研究,由于效应估计值更为准确,权重较大;
小样本研究,由于估计值不够准确,权重较小。
标准化均数差(standardise mean difference)在每一试验中以不同的测量单位对同一结局描述时,需要进行标准化处理。
森林图中横短线与中线相交表示无统计学意义;横线在左侧说明结局弱于竖线结局;在右侧说明强于竖线结局。最后以菱形所在位置得到总体的评价结果。
以上就是森林图的理论知识。接下来我们介绍其是如何在R语言中实现的。
首先我们需要导入R包forestplot。具体的安装载入不再赘述。
下面我们看下其主要的函数forestplot。

其中主要的参数:
tabletext:主要是以矩阵或者list形式将数据导入函数,最好以矩阵,因为数据一般都是矩阵的。
Mean,lower,uper一般会以list形式直接一次性导入,当然如果数据是一个一个向量还是分开的方便。
is.summary主要的功能是让表格的每一行字体出现差异,从而区分表头。其值主要用TRUE/FALSE进行差异化分配。
Graph.pos主要是定位森林图所在的位置。通过数字来确定为第几列。
hrzl_lines以list形式设置表中线的类型以及长度。Eg:“3”=gar(lwd=1,columns=1:4,col=’red’)意思就是宽度为1,线段延伸至第四列。Col指的颜色。
clip主要x轴的最大最小值。
Col指的其中横线以及点的颜色。eg:col=fpcolors(box=’royblue’,line=’darkblue’, summary=’royblue’, hrz_lines=’red’)设置其中这些部分的的颜色。
txt_gap主要是设置表格中文本的字体
最后我们看两个样例程序:
library(forestplot)# Cochrane data from the 'rmeta'-packagecochrane_from_rmeta <- structure(list( mean =c(NA, NA, 0.578, 0.165, 0.246, 0.700, 0.348, 0.139, 1.017, NA, 0.531), lower =c(NA, NA, 0.372, 0.018, 0.072, 0.333, 0.083, 0.016, 0.365, NA, 0.386), upper =c(NA, NA, 0.898, 1.517, 0.833, 1.474, 1.455, 1.209, 2.831, NA, 0.731)), .Names =c("mean", "lower", "upper"), row.names =c(NA, -11L), class ="data.frame") tabletext<-cbind( c("", "Study", "Auckland", "Block", "Doran", "Gamsu", "Morrison", "Papageorgiou", "Tauesch", NA, "Summary"), c("Deaths", "(steroid)", "36", "1", "4", "14", "3", "1", "8", NA, NA), c("Deaths", "(placebo)", "60", "5", "11", "20", "7", "7", "10", NA, NA), c("", "OR", "0.58", "0.16", "0.25", "0.70", "0.35", "0.14", "1.02", NA, "0.53"))forestplot(tabletext,
graph.pos =4,
hrzl_lines =list("3"=gpar(lty=2),
"11" =gpar(lwd=1, columns=c(1:3,5), col ="#000044"),
"12" =gpar(lwd=1, lty=2, columns=c(1:3,5), col ="#000044")),
cochrane_from_rmeta,new_page =TRUE,
is.summary=c(TRUE,TRUE,rep(FALSE,8),TRUE),
clip=c(0.1,2.5),
xlog=TRUE,
col=fpColors(box="royalblue",line="darkblue",summary="royalblue",hrz_lines ="#444444"))

data(HRQoL)clrs <-fpColors(box="royalblue",line="darkblue", summary="royalblue")tabletext <- list(c(NA, rownames(HRQoL$Sweden)), append(list(expression(beta)), sprintf("%.2f", HRQoL$Sweden[,"coef"])))tabletext <-tabletext[,1]forestplot(tabletext, fn.ci_norm =c(fpDrawNormalCI, fpDrawCircleCI), boxsize = .25, # We set the box size to better visualize the type line.margin = .1, # We need to add this to avoid crowding mean =cbind(HRQoL$Sweden[, "coef"], HRQoL$Denmark[, "coef"]), lower =cbind(HRQoL$Sweden[, "lower"], HRQoL$Denmark[, "lower"]), upper =cbind(HRQoL$Sweden[, "upper"], HRQoL$Denmark[, "upper"]), clip =c(-.125, 0.075), col=fpColors(box=c("blue", "darkred")), xlab="EQ-5D index")
forestplot(tabletext, fn.ci_norm =c(fpDrawNormalCI, fpDrawCircleCI), boxsize = .25, # We set the box size to better visualize the type line.margin = .1, # We need to add this to avoid crowding mean =cbind(HRQoL$Sweden[, "coef"], HRQoL$Denmark[, "coef"]), lower =cbind(HRQoL$Sweden[, "lower"], HRQoL$Denmark[, "lower"]), upper =cbind(HRQoL$Sweden[, "upper"], HRQoL$Denmark[, "upper"]), clip =c(-.125, 0.075), lty.ci =c(1, 2), col=fpColors(box=c("blue", "darkred")), xlab="EQ-5D index")