使用geom_segment()为每个因子绘制y均值水平线时遇美学长度错误
问题排查与解决:geom_segment绘制均值水平线报错
错误原因
报错核心是ggplot全局美学映射与geom_segment的数据源不匹配:
- 你在
ggplot()全局设置了aes(x=d, y=y, color=z),其中y=y会被geom_segment继承; geom_segment使用的means数据仅2行,而全局绑定的原df有20行,导致y的长度不一致,触发"Aesthetics must be either length 1 or the same as the data (2): y"错误。
修复方案
将全局的y=y映射移到geom_point内部,避免geom_segment继承冲突的美学映射,其余逻辑保持不变。
完整修复代码
library(tidyverse) library(ggnewscale) # data df <- structure(list(d = c(1L, 1L, 0L, 0L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 1L, 1L), y = c(6, 5, 4, 4, 5, 3, 4, 6, 6, 6, 4, 6, 5, 5, 5, 4, 4, 4, 6, 6), z = c(1L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -20L)) # group means means <- df %>% group_by(d) %>% summarize(y = mean(y)) %>% mutate(d = factor(d)) %>% mutate(x = case_when( d==0 ~ 0.5, TRUE ~ 1.5 )) %>% mutate(xend = case_when( d==0 ~ 1.5, TRUE ~ 2.5 )) %>% mutate(yend = y) # plot df %>% mutate(z = factor(z), d = factor(d) ) %>% ggplot(aes(x=d, color=z)) + # 移除全局y映射 geom_point(aes(y=y), # 把y映射移到geom_point内部 position = position_jitter(seed = 42), alpha = 0.7) + scale_color_manual(values = c("black", "#CC0200")) + new_scale_colour() + geom_segment(data = means, aes(x = x, y = y, xend = xend, yend = yend, colour = d)) + scale_color_manual(values = c("#e69138", "#1f9ac9")) + guides(color = "none")
说明
修改后,geom_segment只会使用自身数据源means中的y值(2行均值),不会与原df的y值(20行)冲突,可顺利绘制每个x因子对应的均值水平线段。
内容的提问来源于stack exchange,提问作者Eric Green
相关产品推荐
相关产品推荐

