如何让geom_bar在仅含单个因子水平与NA时维持条形宽度一致?
解决ggplot2中单个因子水平+NA时条形宽度异常的问题
问题根源
当数据仅包含单个非NA因子水平和NA值时,geom_bar会自动放大有数据的条形宽度以填充坐标轴空间——尽管scale_x_discrete(drop=FALSE)保留了所有因子水平,但空水平未被分配足够的空间,导致视觉上宽度不一致。而当存在多个非NA水平或无NA时,ggplot会为每个水平均等分配空间,条形宽度正常。
解决方案
以下两种方法均可让示例4的条形宽度与示例3保持一致,同时保留NA对应的条形:
方法1:预统计所有水平的计数(推荐)
先统计包括空因子水平和NA在内的所有类别的数量,用geom_col绘制,确保每个水平都被分配均等空间:
# 示例4修正代码 mwe <- data.frame(x = rep(10,100)) mwe[c(5,10,50), "x"] = NA mwe$cat <- cut(mwe$x, breaks = c(0, 3,7,19, 200, 400), include.lowest = TRUE) # 统计所有因子水平(含空水平)和NA的计数 count_data <- dplyr::count(mwe, cat, .drop = FALSE) %>% dplyr::bind_rows(dplyr::tibble(cat = NA, n = sum(is.na(mwe$cat)))) %>% dplyr::distinct() ggplot(count_data, aes(x = cat, y = n)) + geom_col() + scale_x_discrete(drop = FALSE)
方法2:固定条形宽度并明确x轴范围
手动设置geom_bar的宽度,同时在scale_x_discrete中指定所有预期的x轴类别(含NA),强制每个条形宽度统一:
# 示例4修正代码 mwe <- data.frame(x = rep(10,100)) mwe[c(5,10,50), "x"] = NA mwe$cat <- cut(mwe$x, breaks = c(0, 3,7,19, 200, 400), include.lowest = TRUE) # 定义所有需要显示的x轴类别:因子水平 + NA all_x_levels <- c(levels(mwe$cat), NA) ggplot(mwe, aes(cat)) + geom_bar(width = 0.8) + # 固定为默认宽度 scale_x_discrete(drop = FALSE, limits = all_x_levels)
内容的提问来源于stack exchange,提问作者3RK
相关产品推荐
相关产品推荐

