R语言绘制Beeswarm图出现异常空白间隙问题排查
问题描述
我用R语言遍历数据分组,为每个分组绘制Beeswarm图并合并成一张图,代码如下:
# 构建颜色映射函数 color.By.Category <- function(x) { if (x == "Polydrug") { return("red") } else if (x == "Opioid") { return("blue") } else if (x == "Cocaine") { return("green") } else if (x == "Gabapentin") { return("orange") } else if (x == "Meth") { return("blue") } else if (x == "Benzo") { return("pink") } else { return("black") } } # 设置画布布局:5行1列,第一行放图例 par(mfrow=c(5,1), mar=c(0,10,0,0), oma=c(10,0,5,2), bg="black") # 绘制图例 drug.categories <- unique(death.data.2$drug) colr <- sapply(drug.categories, color.By.Category) xleg <- seq(-10,110, by=23) beeswarm(xleg, pwcol=colr, horizontal = TRUE, pch=15, method="center", cex=1, xlim=c(-10,110), ylim=c(-10,4)) text(x=xleg, y=.5, labels=toupper(drug.categories), col="white", pos=4, cex=1.1) # 按种族分组绘制蜂群图 races <- unique(death.data.2$race) for (i in 1:length(races)) { # 筛选当前种族的数据 current <- death.data.2[death.data.2$race == races[i],] # 绘制蜂群图 beeswarm(current$age, pwcol=current$color, pch=15, method="center", cex=1, horizontal=TRUE, ylim=c(-10,10), xlim=c(0,100), axes=FALSE) # 添加种族标签 mtext(races[i], side = 2, las=1, col="white", cex=.9) } # 添加X轴 x <- seq(0, 100, 5) axis(side = 1, labels = x, at=x, col="black", col.ticks = "white") mtext(x, side = 1, outer=FALSE, at=x, line=.8, col="white", cex=.8) mtext("Age", side=1, at=x[1], outer=FALSE, col="white", line=2, adj=0.05, padj=.5, cex=.8) # 添加标题 mtext("Overdose Deaths by Substance Type", side=3, outer=TRUE, line=1, cex=1.5, col="white")
生成的图里有奇怪的空白间隙(无数据显示的空白区域),看起来像绘图渲染的伪影,这是什么原因?
原因分析与解决办法
核心原因:beeswarm的center排列算法导致
你用了method="center"参数,这个算法会把相同数值的点严格居中对齐。如果某个年龄的点数量少,相邻年龄的点数量多,算法为了保持居中,会在稀疏点和密集点之间留出额外空间,就形成了视觉上的空白间隙——这不是渲染伪影,是算法特性导致的。
其他影响因素
ylim设置过大:每个蜂群图的ylim=c(-10,10)范围太大,实际蜂群只需要很小的纵向空间,过大的范围会让点的分布看起来更分散,放大了间隙的视觉效果。- 数据本身的分布:如果某个种族的年龄数据本身就存在连续缺失的区间(比如某个年龄段完全没有死亡案例),也会出现真实的空白,但从图来看更偏向算法导致的间隙。
解决办法
- 更换排列算法:把
method="center"换成method="swarm"或method="hex",这两种算法会更紧凑地排列点,减少不必要的间隙:beeswarm(current$age, pwcol=current$color, pch=15, method="swarm", # 替换为swarm或hex cex=1, horizontal=TRUE, ylim=c(0,2), # 缩小纵向范围到合理值 xlim=c(0,100), axes=FALSE) - 缩小
ylim范围:根据实际点的分布设置纵向范围,比如ylim=c(0,2),让点的排列更紧凑,弱化间隙的视觉感受。 - 检查数据分布:用
table(current$age)查看每个种族的年龄分布,确认是否是真实的数据缺失;如果是算法导致的,直接用前两种方法调整即可。
内容的提问来源于stack exchange,提问作者DiamondJoe12
相关产品推荐
相关产品推荐

