循环生成学生成绩条形图遇错误,需添加条形顶部百分比标签
解决你的条形图错误并添加百分比标签
让我们一步步搞定你的问题:
1. 错误原因分析
你遇到的Columnnmust be length 43 or one, not 42错误,核心问题出在原代码生成匿名标签的逻辑上:当处理43行全量数据时,生成的匿名标签列长度和数据集行数不匹配。原代码里sample(seq_len(n()), size = n())的写法,在全量数据场景下会意外生成少一行的标签,导致mutate操作时列长度不一致。
2. 修正后的完整代码
我重新梳理了代码逻辑,既修复了长度错误,又添加了百分比标签,还优化了成绩对比的合理性(只显示同年级学生成绩):
library(tidyverse) library(cowplot) # 你的样本数据(替换成43行全量数据即可直接运行) names <- c("Jackson", "Smith", "Johnson", "Richards", "Matthews", "Redmond", "Phillips") scores <- c(.99, .65, .73, .89, .88, .92, .87) level <- c(10,11,10,11,11,11,11) grades <- tibble(names, scores, level) # 为每个学生生成个性化的成绩对比图 student_plots <- grades %>% split(.$names) %>% map(function(student) { # 获取当前学生的基础信息 current_name <- student$names[1] current_level <- student$level[1] # 只保留同年级的学生数据(让对比更有意义) level_data <- grades %>% filter(level == current_level) # 为非当前学生生成随机且唯一的匿名标签 non_current_count <- nrow(level_data) - 1 anonymous_labels <- paste0("#", seq_len(non_current_count)) %>% sample() # 构建绘图数据集:替换匿名学生名字,确保当前学生排在最前 plot_data <- level_data %>% mutate( display_name = ifelse(names == current_name, current_name, anonymous_labels), display_name = factor(display_name, levels = c(current_name, anonymous_labels)) ) # 绘制条形图并添加百分比标签 ggplot(plot_data, aes(x = display_name, y = scores, fill = scores)) + geom_col() + # 在条形顶部添加百分比标签 geom_text( aes(label = scales::percent(scores)), vjust = -0.5, # 把标签放在条形上方避免被遮挡 size = 3.5 # 调整标签大小适配图表 ) + ggtitle("Test Scores by Level - February 2018", subtitle = paste("Level", current_level)) + theme(axis.text.x = element_text(angle = 45, hjust = 1)) # 旋转x轴标签避免重叠 }) # 示例:绘制前4个学生的对比图 plot_grid(plotlist = student_plots[1:4])
3. 关键优化说明
- 修复长度错误:先过滤同年级数据,再根据非当前学生的数量生成对应长度的匿名标签,确保标签数量和数据行数完全匹配。
- 添加百分比标签:用
geom_text()结合scales::percent()把小数分数转成百分比格式,通过vjust参数调整标签到条形顶部。 - 逻辑优化:只展示同年级学生成绩,让对比更贴合实际需求,同时减少不必要的数据处理量。
- 可读性提升:旋转x轴标签避免名字重叠,让图表更易读。
内容的提问来源于stack exchange,提问作者regents
相关产品推荐
相关产品推荐

