R语言中如何在绘图区域外添加小提琴图或箱线图?
在R中绘制超出绘图区域的小提琴图和箱线图
问题原因
vioplot和boxplot这类高级绘图函数的内部底层绘图调用(如polygon()、segments())并没有正确继承你传入的xpd=NA参数,导致即使在函数中指定该参数,也无法让元素超出绘图区域显示。
解决办法
1. 箱线图的快速修复
直接通过全局par()设置xpd=NA,再调用boxplot(),之后恢复原有参数即可:
# 保存原有par设置 old_par <- par(xpd = NA) # 添加箱线图 boxplot(dat, add = TRUE, frame.plot = FALSE) # 恢复原有设置 par(old_par)
2. 小提琴图的解决方案
由于vioplot函数内部的polygon调用未处理xpd参数,我们可以手动提取小提琴图的坐标数据,再用底层函数绘制并指定xpd=NA:
步骤1:获取小提琴图的坐标数据
调用vioplot()时设置plot=FALSE,只计算坐标不绘图:
vp <- vioplot(dat, plot = FALSE)
返回的vp列表包含每个小提琴的关键坐标:
$lx/$rx:每个小提琴的左/右边界x坐标$lwdat/$uwdat:对应左/右边界的y值$center:每个小提琴的中心x位置$med:中位数y值$hwidth:中位数线的宽度
步骤2:手动绘制小提琴图
利用polygon()和segments()绘制,同时指定xpd=NA:
old_par <- par(xpd = NA) for(i in seq_along(dat)){ # 绘制小提琴的填充区域 polygon(c(vp$lx[[i]], rev(vp$rx[[i]])), c(vp$lwdat[[i]], rev(vp$uwdat[[i]])), col = "gray80", border = "black", xpd = NA) # 绘制中位数线 segments(vp$center[i] - vp$hwidth[i]/2, vp$med[i], vp$center[i] + vp$hwidth[i]/2, vp$med[i], lwd = 1.5, xpd = NA) } par(old_par)
完整验证代码
library(vioplot) # 生成数据 dat <- replicate(10, rnorm(20), simplify = FALSE) # 创建绘图区域(仅显示y=-10到-2) plot.new() par(oma = c(3,3,3,3)) plot.window(xlim = c(1, 10), ylim = c(-10, -2)) axis(1) axis(2) # 绘制箱线图(修复后) old_par <- par(xpd = NA) boxplot(dat, add = TRUE, frame.plot = FALSE) # 绘制小提琴图(手动绘制) vp <- vioplot(dat, plot = FALSE) for(i in seq_along(dat)){ polygon(c(vp$lx[[i]], rev(vp$rx[[i]])), c(vp$lwdat[[i]], rev(vp$uwdat[[i]])), col = "gray80", border = "black", xpd = NA) segments(vp$center[i] - vp$hwidth[i]/2, vp$med[i], vp$center[i] + vp$hwidth[i]/2, vp$med[i], lwd = 1.5, xpd = NA) } par(old_par) # 验证中位数点显示 points(1:10, sapply(dat, median), xpd = NA, pch = 16, col = "red")
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

