ggplot2绘图如何为无数据的因子水平保留空白占位
问题说明
在基于iris数据集的测试中,构建三水平因子变量fct_x后,过滤掉了Species == "virginica" & fct_x == "C"的所有观测,绘图时无法让ggplot2为virginica物种下的C水平留出空白占位。
此前查阅到的scale_fill_discrete(drop = FALSE)方案经测试无效,另一类通过添加超出轴限的假数据占位的方案,因需要手动设置y轴范围,无法适配根据传入数据自动确定轴范围的自动绘图脚本需求,无法使用。
初始测试代码如下:
require(dplyr) require(ggplot2) iris %>% mutate(fct_x = factor(x = sample(x = c("A", "B", "C"), size = nrow(.), replace = TRUE), levels = c("A", "B", "C"))) %>% filter(!(Species == "virginica" & fct_x == "C")) %>% ggplot(aes(x = Species, y = Sepal.Length, fill = fct_x)) + geom_boxplot() + scale_fill_discrete(drop = FALSE)
初始绘图效果:
解决方案
仅设置fill标度的drop = FALSE只能保证图例不丢失空因子水平,无法控制分组闪避时的x轴位置分配。核心修改是为箱线图的闪避位置参数设置preserve = "single",即可在不伪造数据、不手动设置轴限的前提下,为空组保留等宽占位,完全适配自动绘图场景。
修改后可正常生成空位的代码如下:
require(dplyr) require(ggplot2) iris %>% mutate(fct_x = factor(x = sample(x = c("A", "B", "C"), size = nrow(.), replace = TRUE), levels = c("A", "B", "C"))) %>% filter(!(Species == "virginica" & fct_x == "C")) %>% ggplot(aes(x = Species, y = Sepal.Length, fill = fct_x)) + geom_boxplot(position = position_dodge(preserve = "single")) + scale_fill_discrete(drop = FALSE) + scale_x_discrete(drop = FALSE)
关键参数说明:
position_dodge(preserve = "single"):强制分组闪避时,为每个fill对应的因子水平保留与有数据组完全一致的宽度占位,不会因为某组无观测就将该位置空间分配给同一x类别下的其他分组- 两处
drop = FALSE参数:分别保证x轴类别、fill图例不会自动剔除无观测的因子水平
该方案下y轴范围完全由实际传入的数据自动计算,无需手动设置轴限。
内容的提问来源于stack exchange,提问作者Wencheng Lau-Medrano
相关产品推荐
相关产品推荐

