【问题标题】:Align text to a plot with variable size in R将文本与R中可变大小的图对齐
【发布时间】:2014-10-23 07:41:15
【问题描述】:

我对使用 R 的强大功能创建图形输出非常陌生。

我使用 metafor 包中的 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. 如何将“作者(年份)”和“相关性 [95%CI]”自动与森林图的大小变化对齐,以使标题位于森林表的上线之上?
  2. 如何缩放森林图的大小,以使所有图的文本元素的宽度和大小都相同,并且对于每个额外的研究,只需添加一个新行(改变高度)?李>

每个森林图应如下所示:

【问题讨论】:

  • 你想只在metfor包中这样做还是其他解决方案也可以接受?
  • metafor 会很好,但如果您有其他解决方案。请告诉我
  • 如果你在这里发布 dput(df) 的输出,测试代码会更容易。

标签: r plot png


【解决方案1】:

以下是您必须执行的操作:

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

  2. 每个图中都有k 行。标题应该在上面两行。所以,使用text(&lt;first xlim value&gt;, res_re$k+2, "Author(s) (Year)", pos=4)text(&lt;second xlim value&gt;, res_re$k+2, "Correlation [95% CI]", pos=2)

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

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

所以让其他人更容易插话,你问题的最后一部分归结为:我如何调整绘图设备的height值,以便@中的行之间的绝对间距987654342@ 和 plot(1:20) 保持相等?这本身就是一个有趣的问题,所以我将把它作为一个单独的问题发布。

【讨论】:

    【解决方案2】:

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

    对于forest(),它的工作方式会有所不同,因为此函数在内部修改了par("mar")-values。

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

    4.5 取决于您是否在元分析模型中留下了 addfit=Tintercept=T(在这种情况下,forest() 内部设置了 ylim &lt;- c(-1.5, k + 3))。否则你必须使用2.5(而不是ylim &lt;- 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 2011-03-07
      • 1970-01-01
      • 2021-06-17
      • 1970-01-01
      相关资源
      最近更新 更多