如何在 R 图中添加一个插图(子图)到“右上角”?

17

我想在一个图中添加一个插入区域,该区域的宽度和高度占绘图区域(即图表所在的区域)的25%。

我尝试了:

# datasets
d0 <- data.frame(x = rnorm(150, sd=5), y = rnorm(150, sd=5))
d0_inset <- data.frame(x = rnorm(1500, sd=5), y = rnorm(1500, sd=5))

# ranges
xlim <- range(d0$x)
ylim <- range(d0$y)

# plot
plot(d0)

# add inset
par(fig = c(.75, 1, .75, 1), mar=c(0,0,0,0), new=TRUE)
plot(d0_inset, col=2) # inset bottomright

这将插入绝对置于页面的右上角,并使用设备宽度的25%。我如何将其更改为图表所在区域的坐标和宽度?


也许可以尝试使用layout()(例如,这里)与xpd=TRUE相结合的方法来解决问题。 - Henrik
有一个命令可以告诉你绘图区域的尺寸。 - R_User
4个回答

15

您可以使用par("usr")获取图形的坐标限制,以用户坐标表示, 并使用grconvert[XY]将它们转换为标准化设备坐标(NDC,在0和1之间), 然后再将它们与par(fig=...)一起使用。

plot(d0)
u <- par("usr")
v <- c(
  grconvertX(u[1:2], "user", "ndc"),
  grconvertY(u[3:4], "user", "ndc")
)
v <- c( (v[1]+v[2])/2, v[2], (v[3]+v[4])/2, v[4] )
par( fig=v, new=TRUE, mar=c(0,0,0,0) )
plot(d0_inset, axes=FALSE, xlab="", ylab="")
box()

右上角的内嵌


3
不错的例子。我想指出,在第二个“par”命令之前,可以添加“rect(u[2], u[4], (u[1]+u[2])/2, (u[3]+u[4])/2, col="white")”来用白色填充插图区域(并绘制黑色边框,消除了“box”的需要)。 - Andy Barbour

10

请查看TeachingDemos软件包中的subplot函数。这可能会使您尝试的操作更容易。

以下是一个示例:

library(TeachingDemos)
d0 <- data.frame(x = rnorm(150, sd=5), y = rnorm(150, sd=5))
d0_inset <- data.frame(x = rnorm(1500, sd=5), y = rnorm(1500, sd=5))

plot(d0)
subplot( 
  plot(d0_inset, col=2, pch='.', mgp=c(1,0.4,0),
    xlab='', ylab='', cex.axis=0.5), 
  x=grconvertX(c(0.75,1), from='npc'),
  y=grconvertY(c(0,0.25), from='npc'),
  type='fig', pars=list( mar=c(1.5,1.5,0,0)+0.1) )

在此输入图片描述


1
即使使用subplot,控制插图大小仍然非常困难:由x、y、size、vadj和hadj定义的矩形将用作新绘图的绘图区域。任何刻度线、轴标签、主标题和子标题都将位于此矩形之外。 - R_User
1
@Sven,如果你将 type='fig' 而不是默认的 'plt',那么所有的标签、刻度等都会在指定的矩形内部。 - Greg Snow
1
@Sven,我在上面添加了一个使用subplot的示例。这假定您希望它出现在右下角(很容易更改为其他角落),并且您希望它占用1/4线性空间(1/16区域,也很容易更改)。 - Greg Snow
如果您使用split.screen()来拥有多个图形,似乎子图使用了所有图形的宽度/高度之和。因此,您需要在grconvertX()中调整坐标。 - R_User
1
@ivan866,实际上Hmisc中的函数是旧版本的副本,因此更喜欢TeachingDemos版本(更加更新,功能更强大)。 - Greg Snow
显示剩余6条评论

6

使用par("plt")来查找绘图区域的面积(似乎类似于文森特的答案)。奇怪的是:fig设置了插图的绘图区域大小。因此,如果显示轴,则插图的大小将大于您的25%。

# datasets
d0 <- data.frame(x = rnorm(150, sd=5), y = rnorm(150, sd=5))
d0_inset <- data.frame(x = rnorm(1500, sd=5), y = rnorm(1500, sd=5))

# ranges
xlim <- range(d0$x)
ylim <- range(d0$y)

# plot
plot(d0)

# calculate position of inset
plotdim <- par("plt")
xleft    = plotdim[2] - (plotdim[2] - plotdim[1]) * 0.25
xright   = plotdim[2]  #
ybottom  = plotdim[4] - (plotdim[4] - plotdim[3]) * 0.25  #
ytop     = plotdim[4]  #

# set position for inset
par(
  fig = c(xleft, xright, ybottom, ytop)
  , mar=c(0,0,0,0)
  , new=TRUE
  )

# add inset
plot(d0_inset, col=2) # inset bottomright

1
对我而言,oce库中的示例很有用: (更新,截至2022年8月,链接无法使用,但粘贴的示例应该可以使用)

http://finzi.psych.upenn.edu/library/oce/html/plotInset.html

看这个例子:
library(oce)

## power law in linear and log form
x <- 1:10
y <- x^2
plot(x, y, log='xy',type='l')
plotInset(3, 1, 10, 8,
          expr=plot(x,y,type='l',cex.axis=3/4,mgp=c(3/2,1/2,0)),
          mar=c(2.5,2.5,1,1))

## CTD data with location
data(ctd) 
plot(ctd, which="TS")
plotInset(29.9, 2.7, 31, 10,
          expr=plot(ctd, which='map',
          coastline="coastlineWorld",
          span=5000, mar=NULL, cex.axis=3/4))

1
链接已损坏;2022.08 - ivan866
@ivan866 谢谢你的注意。我已经放了一个通知。它不再起作用了,但我把它放在了我找到它的引用中。尽管如此,这个例子应该是可以工作的。 - Antoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接