【问题标题】:Constant Absolute Spacing of Row in R PlotsR图中行的恒定绝对间距
【发布时间】:2015-01-30 01:36:31
【问题描述】:

R 中,如何调整绘图设备的height 值(例如windows()png()),以使点之间的绝对间距保持不变?这是一个例子来说明我的意思:

n <- 10
windows(width=4, height=4)
par(xpd=NA)
plot(1:n)
abline(h=1:10)

n <- 20
windows(width=4, height=6)
par(xpd=NA)
plot(1:n)
abline(h=1:20)

我希望每个绘图中的点/线之间的距离完全相同(我使用了par(xpd=NA),因此很容易将图形彼此相邻放置,并且如果线条对齐则更好看)。显然,height 需要是n 的函数。当然,人们可以尝试通过反复试验来找到n 的某些功能,以实现这一目标。但也许有一种巧妙的方法可以通过编程方式实现这一目标。

我的问题与此类似:set ggplot plots to have same x-axis width and same space between dot plot rows。但是这个问题使用ggplot2,而我的问题是基本图形。

【问题讨论】:

  • 我无法弄清楚需要什么。链接到的问题是询问“y 值”是离散的图形的绘图区域的高度。您正在询问数字/连续 y 变量。您只是想在基本图形plot 中找到“ylim”参数吗?
  • 感谢您的评论。我试图澄清一下我的问题。现在清楚了吗?
  • 这里的真正目标是什么?您是否愿意放弃自动放置在 x 和 y 限制之外的额外空间?
  • 如果我生成多个不同行数的图表,我希望点对齐,这将使图表之间的比较更容易。你指的是哪个空间?在 x 和 y 限制之外添加的 4%? (即,使用默认的par(yaxs="r")?)是的,可以将其更改为par(yaxs="i"),如果这样会使事情变得更容易。

标签: r plot


【解决方案1】:

这里似乎有两件事在起作用。

  1. R 如何处理轴的分割?
  2. 边距对这些规则有哪些影响?

首先我们需要找出没有边距会发生什么:

adjLineSpace <- function(nLine, baseHeight=32){
  # get reproducible device
  png(paste("nLine=", nLine, ".png", sep=""), width=baseHeight*nLine, heigh=baseHeight*nLine, res=100)
  # control margins
  par(mar=c(0,0,0,0))
  # open plot with axis that do not interact with data to find "optimal range of axes"
  plot(0:nLine, pch=NA_integer_, xlim=c(0, nLine), ylim=c(0, nLine), yaxs="i", xaxs="i")
  abline(h=1:nLine)
  # include text for visualisation
  text(0:nLine, 0:nLine, labels=0:nLine)
  text(c(1:4), 0.5, par("usr")[1:4], pos=4)
  text(c(5), c(0.5), paste("pin: ", par("pin")[1], ", ", par("pin")[2], sep=""), pos=4)
  text(c(5), c(1.5), paste("fin: ", par("fin")[1], ", ", par("fin")[2], sep=""), pos=4)
  text(c(5), c(2.5), paste("din: ", par("din")[1], ", ", par("din")[2], sep=""), pos=4)
  dev.off()
}
# examples
adjLineSpace(10)
adjLineSpace(20)

找到问题后,我感觉自己像个初学者,好久没看到了:一个需要从0开始数,否则不会有10或20或n“行”,而是9 , 19 或 n-1。


但由于几乎在任何情况下都需要边距,我们还需要找出边距如何与之交互:

# introduce new attributes to adjust margins, make it possible to deal with width and height seperately and be able to controll resolution
adjLineSpace <- function(nLine, basePHeight=32, basePWidth=32, marHeight=c(0, 0), marWidth=c(0, 0), res=100){
  pMai <- round(par("mai"),2); pMar <- round(par("mar"),2)
  pixelLeft <- marWidth[1]*pMai[2]/pMar[2]*res       # adjust left
  pixelRight <- marWidth[2]*pMai[4]/pMar[4]*res      # adjust right
  pixelBottom <- marHeight[1]*pMai[1]/pMar[1]*res    # adjust bottom
  pixelTop <- marHeight[2]*pMai[3]/pMar[3]*res       # adjust top
  # reproducible device: we first need to find out how many inches one row covers, multiply that by our resolution and the number of 'lines' we want to use in our margin
  png(
    paste("nLine=", nLine, ".png", sep=""), 
    width=basePWidth*nLine + pixelLeft + pixelRight, 
    heigh=basePHeight*nLine + pixelBottom + pixelTop, 
    res=res
  )
  # set margins
  par(mar=c(marHeight[1], marWidth[1], marHeight[2], marWidth[2]))
  # this is the key to it all! Set range of plot area (in pixels) as above, only transformed to inches (divided by resolution in ppi=points/pixels per inch)
  par(pin=c(basePWidth*nLine/res, basePHeight*nLine/res))
  plot(0:nLine, pch=NA_integer_, xlim=c(0, nLine), ylim=c(0, nLine), yaxs="i", xaxs="i", bg="white")
  abline(h=1:nLine)
  # include text for visualisation of values
  text(0:nLine, 0:nLine, labels=0:nLine)
  text(c(1:4), 0.5, par("usr")[1:4], pos=4)
  text(c(5), c(0.5), paste("din: ", par("din")[1], ", ", par("din")[2], sep=""), pos=4)
  text(c(5), c(1.5), paste("fin: ", par("fin")[1], ", ", par("fin")[2], sep=""), pos=4)
  text(c(5), c(2.5), paste("pin: ", par("pin")[1], ", ", par("pin")[2], sep=""), pos=4)
  text(c(.5), c(9.5), paste("mar: ", pMar[1], ", ", pMar[2], ", ", pMar[3], ", ", pMar[4], sep=""), pos=4)
  text(c(.5), c(8.5), paste("mai: ", pMai[1], ", ", pMai[2], ", ", pMai[3], ", ", pMai[4], sep=""), pos=4)
  text(c(.5), c(7.5), paste("mai(nch)/mar(ow): ", round(pMai[1]/pMar[1],2), ", ", round(pMai[2]/pMar[2],2), ", ", round(pMai[3]/pMar[3],2), ", ", round(pMai[4]/pMar[4],2), sep=""), pos=4)
  dev.off()
}
# examples without margins still work
adjLineSpace(10, basePHeight=32, basePWidth=32, marHeight=c(0, 0), marWidth=c(0, 0))
adjLineSpace(20, 32, 32, c(0, 0), c(0, 0))
# with margins as well!
adjLineSpace(10, 32, 32, c(4, 0), c(4, 0))
adjLineSpace(20, 32, 32, c(4, 0), c(4, 0))

有关设备区域的说明,请参阅 https://www.stat.auckland.ac.nz/~paul/RGraphics/rgraphics.html(作者 Paul Murrell)。 不幸的是,我还不能发布图片,否则我也会在此处添加一些示例。

实际上我也来自这个帖子:Align text to a plot with variable size in R,我很想看到这个包含在 metafor 的 forest() 函数中。我会给你发私信,Wolfgang。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多