Shiny app中ggplot分面后geom_vline未按年份显示分组均值线问题
问题根源
你当前代码的问题在于:variab和variab2是从完整数据集(未按年份过滤)中提取的变量,所以mean(variab2, na.rm=T)计算的是两年数据的总均值,而非对应年份的分组均值。哪怕你在geom_vline的data参数里过滤了年份,xintercept引用的还是全局的总均值,导致所有分面都显示同一根线。
解决方案:提前计算分年份的分组均值
正确的做法是先按年份和分组计算好均值,生成一个专门的均值数据框,再传给geom_vline,让ggplot自动根据分面的Year匹配对应年份的均值。
修改后的代码如下:
output$vargraph <- renderPlot({ # 筛选Group B数据(指定学校)并保留选中的年份 dattest2 <- dattotal %>% filter(SchoolName == input$school, Year %in% c(input$Year2, input$Year1)) # 定义目标变量名称 varb <- as.name(input$Variable) # -------- 核心改动:提前计算分年份的分组均值 -------- # 计算Group A(整体)的分年份均值 mean_a <- dattotal %>% filter(Year %in% c(input$Year2, input$Year1)) %>% group_by(Year) %>% summarise(mean_val = mean(!!varb, na.rm = TRUE)) %>% mutate(group = "A") # 计算Group B(指定学校)的分年份均值 mean_b <- dattest2 %>% group_by(Year) %>% summarise(mean_val = mean(!!varb, na.rm = TRUE)) %>% mutate(group = "B") # 合并两个分组的均值数据 mean_data <- bind_rows(mean_a, mean_b) # 绘制直方图 + 均值竖线 ggplot(dattest2, aes(!!varb)) + geom_histogram(binwidth = .5, colour = "green", linewidth = 2, fill = "white") + theme_bw() + scale_x_continuous( name = paste(input$Variable, "Score"), breaks = seq(0, 5, .25), labels = seq(0, 5, .25) ) + labs(y = "Frequency") + facet_wrap(~Year) + # 使用提前计算好的均值数据框,按分组匹配颜色 geom_vline( data = mean_data %>% filter(group == "B"), aes(xintercept = mean_val), colour = "purple", linewidth = 2 ) + geom_vline( data = mean_data %>% filter(group == "A"), aes(xintercept = mean_val), colour = "yellow", linewidth = 2 ) })
关键改动说明
- 用
group_by(Year) %>% summarise()分别计算两个分组的分年份均值,确保每个年份的均值都是对应子集的结果。 - 合并均值数据后,通过
filter(group == "A"/"B")分别传给对应的geom_vline,ggplot会自动根据分面的Year字段匹配对应年份的均值,避免手动重复写多个geom_vline。 - 直接用
input$Variable转换为符号,替代原代码中提取列的冗余操作,代码更简洁。
内容的提问来源于stack exchange,提问作者ajhoff28
相关产品推荐
相关产品推荐

