如何在同一面板生成三个带内嵌小图且宽度不同的R基础绘图?
解决方案:修复layout与自定义内嵌绘图函数的兼容性问题
方法一:手动维护layout面板状态
问题根源在于自定义函数中par(fig=..., new=TRUE)会破坏layout的面板计数状态。通过保存并恢复layout的当前面板索引,可避免布局混乱:
plotfun <- function() { colfunc <- colorRampPalette(c("red", "blue")) # 绘制主图,此时layout定位到当前面板 plot(1:20, 1:20, pch=19, cex=2, col=colfunc(20)) # 保存当前layout的面板索引状态 current_layout <- par("mfg") # 保存全局par设置 op <- par(no.readonly = TRUE) # 绘制内嵌小图 fig. <- c(grconvertX(c(.1, 5), from="user", to="ndc"), grconvertY(c(8, 19), from="user", to="ndc")) par(fig=fig., mar=c(1, 1, 1, 1), new=TRUE) plot.window(c(0, 1), c(0, 1)) rasterImage(as.raster(matrix(colfunc(20), ncol=1)), 0, 0, 1, 1) lbsq <- seq.int(0, 1, l=5) axis(4, at=lbsq, pos=0, labels=FALSE, col=0, col.ticks=1, tck=-.1) mtext(lbsq, 4, .5, at=lbsq, las=2, cex=.6) mtext('foo', 3, 0, cex=.6, adj=.5, font=2) # 恢复全局par设置 par(op) # 手动恢复layout面板索引,确保后续layout能正确切换面板 par(mfg = current_layout) }
调用代码保持不变:
op <- par(no.readonly=TRUE) layout(matrix(1:3, nrow=1), widths=c(.8,1.1,.8)) plotfun() plotfun() plotfun() par(op)
方法二:使用嵌套layout实现内嵌图
放弃par(fig=new=TRUE)的方式,改用嵌套layout定义主图与内嵌小图的位置关系,更符合layout的原生逻辑:
plotfun <- function() { colfunc <- colorRampPalette(c("red", "blue")) # 定义嵌套布局矩阵:主图占大部分区域,内嵌小图占右上角 layout_mat <- matrix(c(1,2,1,1), nrow=2, ncol=2, byrow=TRUE) # 设置布局的宽高比例,内嵌图占比更小 layout(layout_mat, widths=c(4,1), heights=c(1,4)) # 先绘制内嵌小图(按layout矩阵索引顺序) par(mar=c(1,1,1,1)) plot.window(c(0,1), c(0,1)) rasterImage(as.raster(matrix(colfunc(20), ncol=1)), 0,0,1,1) lbsq <- seq.int(0,1,l=5) axis(4, at=lbsq, pos=0, labels=FALSE, col=0, col.ticks=1, tck=-.1) mtext(lbsq,4,.5,at=lbsq,las=2,cex=.6) mtext('foo',3,0,cex=.6,adj=.5,font=2) # 绘制主图 par(mar=c(5,4,4,2)+.1) plot(1:20,1:20,pch=19,cex=2,col=colfunc(20)) # 退出嵌套layout,回到上层布局上下文 layout(1) }
调用代码同样保持不变,即可实现不同宽度面板的正常布局。
内容的提问来源于stack exchange,提问作者jay.sf
相关产品推荐
相关产品推荐

