如何避免geom_boxplot箱线图须长度随y轴缩放及异常值移除而收缩
在ggplot2中移除异常值并调整y轴时保持箱线图须长度不变的方法
在R语言ggplot2中,移除异常值并修改y轴刻度范围时,geom_boxplot()生成的箱线图须长度会意外收缩。以下是问题示例及解决方法:
问题示例说明
- 含异常值的完整数据箱线图:cyl=4组的上须延伸至mpg=45,cyl=8组的下须延伸至mpg=11。
- 移除异常值并缩小y轴范围后:通过
outlier.shape = NA隐藏异常值,再用scale_y_continuous(limits = c(0,45))调整y轴,此时cyl=4组上须缩短至mpg=34,cyl=8组下须缩短至mpg=13,不符合预期。
示例代码及效果
1. 绘制含异常值的完整数据箱线图
library(ggplot2) library(dplyr) # 加载mtcars数据集 data(mtcars) data <- mtcars %>% select(mpg,cyl) # 为指定分组添加异常值 outliers <- data.frame( mpg = c(45,50,55,45,50,55), cyl = c(4,4,4,8,8,8)) # 创建示例数据集 data <- rbind(data, outliers) # 绘制箱线图:cyl=4组上须在45 mpg,cyl=8组下须在11 mpg data %>% ggplot(aes(x = factor(cyl), y = mpg)) + geom_boxplot()

2. 移除异常值并调整y轴(须长度收缩的错误做法)
# 隐藏异常值并缩小y轴范围,须长度发生收缩 data %>% ggplot(aes(x = factor(cyl), y = mpg)) + geom_boxplot(outlier.shape = NA) + scale_y_continuous(breaks = seq(0,45,5), limits = c(0,45)) #> Warning: Removed 4 rows containing non-finite values (`stat_boxplot()`).

解决方法
方法1:用coord_cartesian()替代scale_y_continuous(limits)
scale_y_continuous(limits = ...)会过滤掉超出范围的数据,导致箱线图重新计算统计量;而coord_cartesian(ylim = ...)仅裁剪绘图视图,不会修改原始数据,统计量仍基于完整数据集计算:
# 隐藏异常值,用coord_cartesian裁剪y轴,保留原始须长度 data %>% ggplot(aes(x = factor(cyl), y = mpg)) + geom_boxplot(outlier.shape = NA) + coord_cartesian(ylim = c(0,45)) + scale_y_continuous(breaks = seq(0,45,5))
方法2:预先计算箱线图统计量
手动计算完整数据的箱线图统计量,再用stat = "identity"绘制,确保统计量不受y轴范围影响:
# 基于完整数据计算箱线图统计量 box_stats <- data %>% group_by(cyl) %>% summarize( ymin = quantile(mpg, 0.25) - 1.5*IQR(mpg), # 下须端点 lower = quantile(mpg, 0.25), # 下四分位数 middle = median(mpg), # 中位数 upper = quantile(mpg, 0.75), # 上四分位数 ymax = quantile(mpg, 0.75) + 1.5*IQR(mpg) # 上须端点 ) # 使用预计算的统计量绘制箱线图 box_stats %>% ggplot(aes(x = factor(cyl), ymin = ymin, lower = lower, middle = middle, upper = upper, ymax = ymax)) + geom_boxplot(stat = "identity", outlier.shape = NA) + scale_y_continuous(breaks = seq(0,45,5), limits = c(0,45))
内容的提问来源于stack exchange,提问作者tassones
相关产品推荐
相关产品推荐

