将文本与R中可变大小的绘图对齐

时间:2014-08-29 09:51:36

标签: r plot png

我很擅长使用R的力量来创建图形输出。

我在metafor-package中使用forest() - 函数来创建我的元分析的Forest图。我使用循环生成几个图,然后通过png()保存它们。

for (i in 1:ncol(df)-2)){
  dat <- escalc(measure="COR", ri=ri, ni=ni, data=df) # Calcultes Effect Size
  res_re <- rma.uni(yi, vi, data=dat, method="DL", slab=paste(author)) # Output of meta-analysis

  png(filename=path, width=8.27, height=11.69, units ="in", res = 210)
  forest(res_re, showweight = T, addfit= T, cex = .9) 
  text(-1.6, 18, "Author(s) (Year)", pos=4)     
  text( 1.6, 18, "Correlation [95% CI]", pos=2)
  dev.off()
}

如果绘图的大小相等,则效果很好。然而,循环的每次迭代在森林图中集成了不同数量的研究。因此,文本元素不在正确的位置,并且许多研究的森林情节看起来有点奇怪。我有两个问题:

  1. 如何调整&#34;作者(年)&#34;和&#34;相关[95%CI]&#34;自动改变森林地块的大小,使标题高于森林表的上线?
  2. 如何缩放森林图的大小,使得所有图的文本元素的宽度和大小相同,并且对于每个额外的研究,只添加一个新行(更改高度)?
  3. 每个森林地块应如下所示:

    enter image description here

2 个答案:

答案 0 :(得分:1)

以下是您需要做的工作:

  1. 我会在图表中修复xlim,以便有一个固定的位置来放置“作者(年)”和“相关[95%CI]”标题。生成森林图后,请查看par()$usr[1:2]。使用这些值作为起点来调整xlim,使其适合您的所有绘图。然后对text()的两次调用使用这两个值。

  2. 每个图中都有k行。标题应该高出两行。因此,请使用text(<first xlim value>, res_re$k+2, "Author(s) (Year)", pos=4)text(<second xlim value>, res_re$k+2, "Correlation [95% CI]", pos=2)

  3. cex中的text()设置为您在调用forest()时指定的相同值。

  4. 最后一部分很棘手。您已修复cex,因此文本元素的大小在各个图表中应相同。但是如果有更多的研究,那么k行会被塞进更小的空间,因此它们会变得更少分离。如果我理解正确,您希望通过调整绘图的实际高度来保持行之间的间距相等。从本质上讲,这需要在调用height png()时使k成为height。对于每个额外的研究,需要将额外的数量添加到height=<some factor> + res_re$k * <some factor>,以便行间距保持不变,因此类似于k。但作为?par函数的高度增加也可能是非线性的。做到这一点需要花费大量的尝试和错误。可能有一种巧妙的方法可以通过编程方式确定(挖掘?strheightheight)。

  5. 因此,让其他人更容易进入,问题的最后部分归结为:我如何调整绘图设备的plot(1:10)值,以便行之间的绝对间距在plot(1:20)和{{1}}保持平等?这本身就是一个有趣的问题,所以我将把它作为一个单独的问题发布。

答案 1 :(得分:1)

ad 4。:在Wolfgangs的问题(Constant Absolute Spacing of Row in R Plots)中,您将找到如何根据其中的行数制作绘图高度。

对于forest(),它会有所不同,因为此函数会在内部修改par("mar") - 值。

但是,如果将边距设置为零,则只需在yaxs="i" - 函数中包含属性forest(),以便y轴将针对数据范围进行分段,没有其他的。需要将设备配置为高度(length(ma$yi)+4.5)*fact*res,其中fact为英寸/行(见下文),res为像素/英寸(分辨率)。

4.5取决于您是否在您的元分析模型中留下addfit=Tintercept=T(在这种情况下forest()在内部设置ylim <- c(-1.5, k + 3))。否则,您必须使用2.5(而不是ylim <- c(0.5, k + 3))。

如果您想使用边距,您可以执行以下操作(我在识别出一些错误后编辑了以下部分):

res <- 'your desired resolution' # pixels per inch
fact <- par("mai")[1]/par("mar")[1] # calculate inches per line
### this following part is copied from inside the forest()-function.
# forest() modifies the margin internally in the same way.
par.mar <- par("mar")
par.mar.adj <- par.mar - c(0, 3, 1, 1)
par.mar.adj[par.mar.adj < 0] <- 0
###
ylim <- c(-1.5, length(ma$yi)+3) # see above
ylim.abs <- abs(ylim[1])+abs(ylim[2])-length(ma$yi) # calculate absolute distance of ylim-argument
pixel.bottom <- (par.mar.adj[1])*fact*res # calculate pixels to add to bottom and top based on the margin that is internally used by forest().
pixel.top <- (par.mar.adj[3])*fact*res
png(filename='path', 
    width='something meaningful', 
    height=((length(ma$yi)+ylim.abs)*fact*res) + pixel.bottom + pixel.top, 
    res=res)
par(mar=par.mar) # make sure that inside the new device the margins you want to define are actually used.
forest(res_re, showweight = T, addfit= T, cex = .9, yaxs="i")
...
dev.off()