【问题标题】:How do you draw a line across a multiple-figure environment in R?你如何在 R 中的多图形环境中画一条线?
【发布时间】:2012-04-02 23:02:31
【问题描述】:

举个很简单的例子,mfrow=c(1,3);每个图都是不同的直方图;我将如何绘制一条跨越所有 3 个数字的水平线(类似于abline(h=10))? (也就是说,甚至它们之间的边距。)显然,我可以为每个图形添加一个 abline,但这不是我想要的。我可以想到一个非常复杂的方法来做到这一点,真的只有一个数字,并使用polygon 等在其中绘制每个“数字”。这太荒谬了。有没有简单的方法可以做到这一点?

【问题讨论】:

  • par(mfrow=c(1,3)); barplot(VADeaths); from <- grconvertX(par('usr')[1], 'user', 'ndc'); barplot(VADeaths); barplot(VADeaths); to <- grconvertX(par('usr')[2], 'user', 'ndc'); segments(grconvertX(from, 'ndc'), 50, grconvertX(to, 'ndc'), xpd = NA)

标签: r graph


【解决方案1】:

正如@joran 所说,grid 图形系统可以更灵活地控制单个设备上多个绘图的排列。

这里,我先用grconvertY()查询y轴上高度为50的位置以“标准化设备坐标”为单位。 (即作为绘图设备总高度的比例,0=底部,1=顶部)。然后我使用 grid 函数来:(1)推送一个填充设备的viewport; (2) 在grconvertY() 返回的高度绘制一条线。

## Create three example plots
par(mfrow=c(1,3))
barplot(VADeaths, border = "dark blue") 
barplot(VADeaths, border = "yellow") 
barplot(VADeaths, border = "green") 

## From third plot, get the "normalized device coordinates" of 
## a point at a height of 50 on the y-axis.
(Y <- grconvertY(50, "user", "ndc"))
# [1] 0.314248

## Add the horizontal line using grid
library(grid)
pushViewport(viewport())
grid.lines(x = c(0,1), y = Y, gp = gpar(col = "red"))
popViewport()

编辑:@joran 询问如何绘制一条从第一个图的 y 轴延伸到第三个图的最后一个条形边缘的线。这里有几个选择:

library(grid)
library(gridBase)
par(mfrow=c(1,3))

# barplot #1
barplot(VADeaths, border = "dark blue") 
X1 <- grconvertX(0, "user", "ndc")
# barplot #2
barplot(VADeaths, border = "yellow") 
# barplot #3
m <- barplot(VADeaths, border = "green") 
X2 <- grconvertX(tail(m, 1) + 0.5, "user", "ndc") # default width of bars = 1
Y <- grconvertY(50, "user", "ndc")

## Horizontal line
pushViewport(viewport())
grid.lines(x = c(X1, X2), y = Y, gp = gpar(col = "red"))
popViewport()

最后,这是一个几乎等效的、更普遍有用的方法。它使用了 @mdsumner 的答案中链接到的文章中 Paul Murrell 演示的函数 grid.move.to()grid.line.to()

library(grid)
library(gridBase)
par(mfrow=c(1,3))

barplot(VADeaths); vps1 <- do.call(vpStack, baseViewports())
barplot(VADeaths) 
barplot(VADeaths); vps3 <- do.call(vpStack, baseViewports())

pushViewport(vps1)
Y <- convertY(unit(50,"native"), "npc")
popViewport(3)

grid.move.to(x = unit(0, "npc"), y = Y, vp = vps1)
grid.line.to(x = unit(1, "npc"), y = Y, vp = vps3, 
             gp = gpar(col = "red"))

【讨论】:

  • +1 不错!您是否知道一种按摩单位/坐标/剪裁的方法,使线条从最左边的 y 轴延伸到绿条的右边缘?
  • 我确实有一个想法,如果可行,我会添加它。现在,我要在太阳落山前修剪草坪……
  • 谢谢,这真的很有帮助!感谢您愿意在我的帐户上推迟割草 ;-)
  • @joran -- 好的,我添加了一些想法。第一个可能看起来更好,但不能很好地概括,即使是与并列(而不是堆叠)条形图的条形图。第二个在绘图区域的 RHS 上终止线(而不是在最后一个条的 RHS),但对于任何类型的基本 R 图,它的功能都类似。
  • @joran -- 我想我现在已经找到了一种相对干净且通用的方法来添加您所询问的那种行。如果您有兴趣,请查看第三个(最近编辑的)代码块。
【解决方案2】:

这是我能做的最好的事情,而不用更深思熟虑:

par(mfrow = c(1,3),xpd = NA)

for (i in 1:3){
    x <- rnorm(200,i)
    hist(x)
    if (i == 1) segments(par("usr")[1],10,30,10)
}

我不确定如何确保线路在正确的位置结束而不进行修补。在每个区域中绘制一个段可以解决这个问题,但会引入正确排列高度的问题。但这至少是一个很好的起点。

我猜这在 grid 图形中更容易,但我必须做一些研究来验证。

【讨论】:

    【解决方案3】:

    Paul Murrell 的这篇文章展示了使用 grid 图形在两个不同的坐标系之间绘制线条,在这种情况下,线条的端点在两个单独的子图的原始空间中指定:

    保罗·穆雷尔。网格图形包。 R 新闻,2(2):14-19,2002 年 6 月

    在 PDF 文章的第 17 页:

    http://cran.r-project.org/doc/Rnews/Rnews_2002-2.pdf

    【讨论】:

    • 是的,感谢您提供的出色链接。我刚刚在我的答案中添加了第三个代码块,它使用了 Murrell 文章中演示的几个函数(grid.move.to()grid.line.to())。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 2012-04-20
    • 1970-01-01
    • 2023-03-30
    • 2015-03-17
    • 2021-07-05
    相关资源
    最近更新 更多