如何从 metafor 包进一步格式化 R 中的森林图?

How to further format forest Plots in R, from the metafor package?

我是 R 的新手,一直在努力正确格式化我创建的森林图。

当我在 R 中单击 "zoom" 选项以在新 window 中打开图表时,它看起来是这样的:

Forest Plot Currently

我的主要目标是让森林图尽可能紧凑,即发布 quality/style。我目前在我的情节中有太多白色 space。我认为这与我乱用 par() 函数有关,现在不知道如何恢复为默认值。

#Metafor library
library(metafor)

#ReadXL library to import excel sheet
library(readxl)

#Name the data sheet from the excel file
ACDF<- read_excel("outpatient_ACDF_meta_analysis.xlsx")

#View the data sheet with view(ACDF)

par(mar=c(20,1,1,1))

#This below measures with risk ratios. If you want to measure odds ratios, use argument measure=OR
returnop <- escalc(measure="OR", ai=op_return_OR, bi=op_no_return_OR, ci=ip_return_OR, di=ip_no_return_OR, data=ACDF)

#Generate a Random Effects Model
REmodel<-rma(yi=yi, vi=vi, data=returnop, slab=paste(Author, Year, sep=", "), method="REML")

#Generate a forest plot of the data
forest(REmodel, xlim=c(-17, 6),
       ilab=cbind(ACDF$op_return_OR, ACDF$op_no_return_OR, ACDF$ip_return_OR, ACDF$ip_no_return_OR),
       ilab.xpos=c(-9.5,-8,-6,-4.5), cex=.75, ylim=c(-1, 27),
       psize=1)

### add column headings to the plot
text(c(-9.5,-8,-6,-4.5), 26, c("Return+", "Return-", "Return+", "Return-"))
text(c(-8.75,-5.25),     27, c("Outpatient", "Inpatient"))
text(-16,                26, "Study",     pos=4)
text(6,                  26, "Log Odds Ratio [95% CI]", pos=2)

我不是 100% 知道如何以其他方式提供我的数据,但我使用 dput 函数提供如下。为 N/As 道歉,仍在充实未来的数据。

structure(list(Study = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA), Author = c("Stieber", "Villavicencio", 
"Lied", "Liu", "Garringer", "Joseffer", "Trahan", "Lied", "Sheperd", 
"Talley", "Martin", "McGirt", "Adamson", "Fu", "Arshi", "Khanna", 
"McClelland", "Purger", "McLellend2", NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Year = c(2005, 2007, 
2007, 2009, 2010, 2010, 2011, 2012, 2012, 2013, 2015, 2015, 2016, 
2017, 2017, 2017, 2017, 2017, 2017, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA), op_return_OR = c(NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, 1, 3, 2, 16, 257, 7, NA, 5, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), op_no_return_OR = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
596, 769, 992, 4581, 958, 1749, NA, 3120, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_return_OR = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 8, 9, 2, 257, 2034, 12, NA, 
200, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA), ip_no_return_OR = c(NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 589, 641, 482, 16171, 8930, 1744, NA, 46312, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), op_death = c(NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, 1, NA, 
1, 0, NA, 2, NA, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA), op_no_death = c(NA, NA, NA, 45, NA, 
NA, NA, NA, NA, NA, 596, NA, 993, 4597, NA, 1754, NA, 3125, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), ip_death = c(NA, NA, NA, 0, NA, NA, NA, NA, NA, NA, 0, NA, 
0, 42, NA, 2, NA, 20, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA), ip_no_death = c(NA, NA, NA, 64, 
NA, NA, NA, NA, NA, NA, 597, NA, 484, 16386, NA, 1754, NA, 46492, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
2979.79797979798), op_thrombo = c(NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 0, NA, NA, 8, 20, 4, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_thrombo = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 597, NA, NA, 4589, 1195, 
1752, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA), ip_thrombo = c(NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 2, NA, NA, 67, 150, 4, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_thrombo = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 595, NA, NA, 16361, 10814, 
1752, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA), op_stroke = c(NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 0, NA, NA, 2, 12, 0, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_stroke = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 597, NA, NA, 4595, 1203, 
1756, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA), ip_stroke = c(NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 2, NA, NA, 14, 132, 0, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_stroke = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 595, NA, NA, 16414, 10832, 
1756, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA), op_dysphagia = c(NA, NA, NA, 0, NA, NA, 
NA, NA, NA, NA, NA, NA, 11, NA, NA, NA, NA, 2, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_dysphagia = c(NA, 
NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, 618, NA, NA, NA, 
NA, 49, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA), ip_dysphagia = c(NA, NA, NA, 1, NA, NA, NA, NA, 
NA, NA, NA, NA, 1, NA, NA, NA, NA, 59, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_dysphagia = c(NA, 
NA, NA, 63, NA, NA, NA, NA, NA, NA, NA, NA, 273, NA, NA, NA, 
NA, 2917, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA), op_hematoma = c(NA, NA, NA, 0, NA, NA, NA, NA, 
NA, NA, NA, NA, 1, NA, NA, NA, 1, 4, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), op_no_hematoma = c(NA, 
NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, 629, NA, NA, NA, 
2015, 47, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA), ip_hematoma = c(NA, NA, NA, 1, NA, NA, NA, NA, 
NA, NA, NA, NA, 1, NA, NA, NA, 273, 65, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ip_no_hematoma = c(NA, 
NA, NA, 63, NA, NA, NA, NA, NA, NA, NA, NA, 273, NA, NA, NA, 
7791, 1713, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA)), .Names = c("Study", "Author", "Year", "op_return_OR", 
"op_no_return_OR", "ip_return_OR", "ip_no_return_OR", "op_death", 
"op_no_death", "ip_death", "ip_no_death", "op_thrombo", "op_no_thrombo", 
"ip_thrombo", "ip_no_thrombo", "op_stroke", "op_no_stroke", "ip_stroke", 
"ip_no_stroke", "op_dysphagia", "op_no_dysphagia", "ip_dysphagia", 
"ip_no_dysphagia", "op_hematoma", "op_no_hematoma", "ip_hematoma", 
"ip_no_hematoma"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-35L))

我觉得 par 选项没问题。我更改了 ylim 选项并修改了一些 header 文本的 y 位置和大小,如下所示:

#Generate a forest plot of the data
forest(REmodel, xlim=c(-17, 6),
       ylim=c(-1, 10),
       ilab=cbind(ACDF$op_return_OR, ACDF$op_no_return_OR, ACDF$ip_return_OR, 
       ACDF$ip_no_return_OR),
       ilab.xpos=c(-9.5,-8,-6,-4.5), cex=.75,
       psize=1)

### add column headings to the plot
text(c(-9.5,-8,-6,-4.5), 8.5, c("Return+", "Return-", "Return+", "Return-"), 
cex = 0.65)
text(c(-8.75,-5.25),     9.5, c("Outpatient", "Inpatient"))
text(-17,                8.5, "Study",     pos=4)
text(6,                  8.5, "Log Odds Ratio [95% CI]", pos=2)

这给出了以下情节: