如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

huangapple go评论64阅读模式
英文:

How to put multiple plots with inner plots in a M x N layout without messing up the par()s?

问题

我在一个图中创建了另一个图。

(我在这里简单使用curve(),但这也适用于plot()。)

curve(exp(x), 0, 1, col=4)
.op <- par(
  fig=c(grconvertX(c(.05, .4), to='ndc'),
        grconvertY(c(2, 2.75), to='ndc')),
  mar=c(1, 1, 1, 1),
  new=TRUE
)
curve(sin(x), 0, 2*pi)
par(.op)

通过for循环重复这个基本上是有效的。但是,当我尝试使用2x2的layout时,图形分散在四个不同的图中,而不是显示在一个图中。

layout(matrix(1:4, 2, 2))
for (i in 1:4) {
  curve(exp(x), 0, 1, col=4)
  .op <- par(
    fig=c(grconvertX(c(.05, .3), to='ndc'),
          grconvertY(c(2, 2.75), to='ndc')),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
}

由于某种原因,内部的par破坏了外部的par。我还尝试了op <- par(mfrow=); ... par(op)而不是layout,但结果相同。

如何修复这个问题?

英文:

I make a plot within a plot.

(I use curve() here for simplicity, but this also refers to plot().)

curve(exp(x), 0, 1, col=4)
.op &lt;- par(
  fig=c(grconvertX(c(.05, .4), to=&#39;ndc&#39;),
        grconvertY(c(2, 2.75), to=&#39;ndc&#39;)),
  mar=c(1, 1, 1, 1),
  new=TRUE
)
curve(sin(x), 0, 2*pi)
par(.op)

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

Repeating this in a for loop basically works well. However, when I try use a 2x2 layout, the figures are spread over four different plots instead of being shown on one.

layout(matrix(1:4, 2, 2))
for (i in 1:4) {
  curve(exp(x), 0, 1, col=4)
  .op &lt;- par(
    fig=c(grconvertX(c(.05, .3), to=&#39;ndc&#39;),
          grconvertY(c(2, 2.75), to=&#39;ndc&#39;)),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
}

For some reason the inner par messes up the outer one. I also tried to op &lt;- par(mfrow=); ... par(op) instead of layout, but with same result.

How can I fix that?

答案1

得分: 5

尝试使用 screen 替代。

split.screen(c(2,2))
for (i in 1:4) {
  screen(i)
  curve(exp(x), 0, 1, col=4)
  title(paste("i=",i))

  .op <- par(
    fig=c(grconvertX(c(.05, .3), to='ndc'),
          grconvertY(c(2, 2.75), to='ndc')),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
}

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

英文:

Try using screen instead.

split.screen(c(2,2))
for (i in 1:4) {
  screen(i)
  curve(exp(x), 0, 1, col=4)
  title(paste(&quot;i=&quot;,i))

  .op &lt;- par(
    fig=c(grconvertX(c(.05, .3), to=&#39;ndc&#39;),
          grconvertY(c(2, 2.75), to=&#39;ndc&#39;)),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
}

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

答案2

得分: 2

如果你想继续使用 layout(某种程度上),你可以首先创建一系列空白图形,以找到布局区域的坐标。然后,不再依赖于 layout,你可以再次使用 par(fig=...) 来定义它们,这将允许你绘制内部图形而不会弄乱事情。

layout(matrix(1:4, 2, 2))
# 存储布局区域的坐标
figs <- sapply(1:4, \(i) {
  frame()
  par('fig')
})
# 覆盖空白图形
par(new=T)

for (i in 1:4) {
  
  # 将图形区域设置为当前布局窗口
  par(fig = figs[, i])
  
  curve(exp(x), 0, 1, col=4)
  .op <- par(
    fig=c(grconvertX(c(.05, .3), to='ndc'),
          grconvertY(c(2, 2.75), to='ndc')),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
  par(new=T)
}

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

英文:

If you want to stick to using layout (sort of), you can first create a series of empty plots to find the coordinates for the layout regions. Then, not relying on layout anymore, you can define them again with par(fig=...) which will allow you to draw the inner plots without things getting messed up.

layout(matrix(1:4, 2, 2))
# store coordinates of layout regions
figs &lt;- sapply(1:4, \(i) {
  frame()
  par(&#39;fig&#39;)
})
# to overwrite the empty plots
par(new=T)

for (i in 1:4) {
  
  # set figure region to the current layout window
  par(fig = figs[, i])
  
  curve(exp(x), 0, 1, col=4)
  .op &lt;- par(
    fig=c(grconvertX(c(.05, .3), to=&#39;ndc&#39;),
          grconvertY(c(2, 2.75), to=&#39;ndc&#39;)),
    mar=c(1, 1, 1, 1),
    new=TRUE
  )
  curve(sin(x), 0, 2*pi)
  par(.op)
  par(new=T)
}

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

答案3

得分: 2

以下是您要翻译的内容:

"Here's how I combined the insights from the two answers in a function plot_fun(). From @Edward I take split.screen, and from @Robert Hacken the fact that curve (or plot respectively) produces margins relative to the font size that we may manipulate using cex."

"这是我如何将两个答案的见解结合到一个名为 plot_fun() 的函数中。从@Edward那里,我使用了 split.screen,而从@Robert Hacken那里,我了解到 curve(或者 plot)会相对于字体大小产生边距,我们可以使用 cex 进行操作。"

plot_fun <- function(spl, .cex = 3, iadj = 0) {
  scr <- split.screen(spl)
  for (i in scr) {
    screen(i)
    par(mar = c(5, 6, 4, 3) + 0.1)
    curve(exp(x), 0, 1, col = 4, cex.axis = .cex, cex.lab = .cex)
    .op <- par(
      fig = c(grconvertX(c(0.1, 0.4), to = 'ndc'),
              grconvertY(c(2 + iadj, 2.75), to = 'ndc')),
      mar = c(1, 1, 1, 1),
      cex = .cex * 0.1,
      new = TRUE
    )
    curve(sin(x), 0, 2 * pi, cex.axis = .cex * 3)
    par(.op)
  }
  close.screen(all.screens = TRUE)
}

f <- 4  ## appears to work fine with the two versions below

pdf("tmp/p1.pdf", 16 * f, 9 * f)
plot_fun(spl = c(6, 7))
dev.off()

"如果我们希望在出版或其他方面获得更清晰的坐标轴刻度标签,我们仍然可以使用 curve(., axes=FALSE) 并使用 axis()mtext() 进行调整,但这已经可以在不费力的情况下得到令人满意的分析结果。"

"如果您的设备在设置过程中出现问题并且产生奇怪的结果,可以使用 graphics.off()close.screen(all.screens=TRUE) 来重置设备。"

英文:

Here's how I combined the insights from the two answers in a function plot_fun(). From @Edward I take split.screen, and from @Robert Hacken the fact that curve (or plot respectively) produces margins relative to the font size that we may manipulate using cex.

plot_fun &lt;- \(spl, .cex=3, iadj=0) {
  scr &lt;- split.screen(spl)
  for (i in scr) {
    screen(i)
    par(mar=c(5, 6, 4, 3) + .1)
    curve(exp(x), 0, 1, col=4, cex.axis=.cex, cex.lab=.cex)
    .op &lt;- par(
      fig=c(grconvertX(c(.1, .4), to=&#39;ndc&#39;),
            grconvertY(c(2 + iadj, 2.75), to=&#39;ndc&#39;)),
      mar=c(1, 1, 1, 1),
      cex=.cex*.1,
      new=TRUE
    )
    curve(sin(x), 0, 2*pi, cex.axis=.cex*3)
    par(.op)
  }
  close.screen(all.screens=TRUE)
}
    

f &lt;- 4  ## appears to work fine with the two versions below

pdf(&quot;tmp/p1.pdf&quot;, 16*f, 9*f)
plot_fun(spl=c(6, 7))
dev.off()

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

pdf(&quot;tmp/p1.pdf&quot;, 16*f, 9*f)
plot_fun(spl=c(2, 3), iadj=.2)
dev.off()

如何在不破坏par()设置的情况下,将多个内部图形放入M x N布局中?

If we wish cleaner tick labels on the axes for publishing or so, we may still use curve(., axes=FALSE) and mess around with axis() and mtext(), but this already gives an acceptable result for analyses without great effort.

If your device gets messed up during setup and gives weird results, use graphics.off() and close.screen(all.screens=TRUE) to reset the device.

huangapple
  • 本文由 发表于 2023年7月13日 17:29:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76677877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定