ggplot2中geom_dotplot处理小数数值分组不准确问题如何解决
解决ggplot2 geom_dotplot数值错误合并分组的方案
问题根因
geom_dotplot默认采用自动计算的分箱宽度对y轴数值做分组归箱,当不同数值的差值小于自动分箱宽度时,就会被归入同一个分箱,出现不同值对齐、同值错位的异常排布,和观察到的四舍五入效果一致。
可落地的解决方案
- 方案1:手动设置匹配数据精度的
binwidth参数
这是成本最低的修复方案,只要将分箱宽度设置为小于等于数据中最小的数值间隔,就能保证每个不同数值单独分箱。
修改后示例1代码:
data("diamonds") dia=diamonds[1:30,] dia[order(dia$depth, decreasing = TRUE), ] ggplot(dia, aes(y=depth, x="")) + geom_boxplot() + # 新增binwidth参数,匹配depth精度0.1 geom_dotplot(aes(fill=factor(color)), binaxis='y', stackdir='center', dotsize=0.5, stackgroups = TRUE, binwidth = 0.1)
修改后示例2代码:
abb=c(1,1.5,1.5,1.5,2,2,2,2.5,3.5,5,5,5.5,5.5) bcc=c("Lyon", "Lyon", "Bordeaux", "Bordeaux", "Chambéry", "Lyon", "Lyon", "Nantes", "Nantes", "Lyon", "Lyon", "Rennes", "Lyon") Fil=data.frame(abb,bcc) ggplot(Fil, aes(y=abb, x="")) + geom_boxplot() + # 新增binwidth参数,匹配abb精度0.5 geom_dotplot(aes(fill=factor(bcc)), binaxis='y', stackdir='center', dotsize=0.5, stackgroups = TRUE, binwidth = 0.5) + scale_fill_manual(values = c("#FF8000", "#FF0033","#80FF00","#FFFF00", "#000000"))
- 方案2:离散化y轴数值,强制不同值单独占位
如果数据数值间隔不统一,手动设置binwidth容易出错,可以将y轴数值转为按实际值排序的因子,强制每个不同数值单独占一个y轴位置,再通过y轴刻度标签还原数值展示效果。
示例代码(以示例2为例):
# 先对y轴数值做离散化处理,按实际值排序 Fil$abb_factor <- factor(Fil$abb, levels = sort(unique(Fil$abb))) ggplot(Fil, aes(y=abb_factor, x="")) + # 箱线图适配因子轴,转成数值计算 geom_boxplot(aes(y = as.numeric(abb_factor))) + geom_dotplot(aes(fill=factor(bcc)), binaxis='y', stackdir='center', dotsize=0.5, stackgroups = TRUE, binwidth = 1) + scale_fill_manual(values = c("#FF8000", "#FF0033","#80FF00","#FFFF00", "#000000")) + # 还原y轴数值标签 scale_y_discrete(labels = ~as.numeric(.x), name = "abb")
- 方案3:换用
geom_beeswarm实现精准点排布
如果不需要严格使用dotplot的堆叠逻辑,可以安装ggbeeswarm包使用geom_beeswarm,该函数默认按实际数值排布点,不会做自动归箱,适配需求:
# 安装包命令:install.packages("ggbeeswarm") library(ggbeeswarm) ggplot(Fil, aes(y=abb, x="")) + geom_boxplot() + geom_beeswarm(aes(fill=factor(bcc)), cex = 2, pch = 21) + scale_fill_manual(values = c("#FF8000", "#FF0033","#80FF00","#FFFF00", "#000000"))
内容的提问来源于stack exchange,提问作者Patrick Parts
相关产品推荐
相关产品推荐

