R语言geom_line:为分组数据折线图添加数值标签
给ggplot折线图(日期维度qty总和)添加数值标签
我用ggplot制作了包含柱状图(geom_col)和折线图(geom_line)的组合图形,已成功在柱状图上方显示qty字段的标签,但希望给折线图(展示每个date变量对应的qty总和)的顶部也添加数值标签。以下是我的代码:
sample <- data.frame(service_type = c("A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C"), qty = c(38,185,87,29,12,133,2,14,31,2,9,59,60,43,137,135,31,159,15,32,1), year_week = c("2022 - CW02","2022 - CW02","2022 - CW02","2022 - CW03","2022 - CW03","2022 - CW03","2022 - CW04","2022 - CW04","2022 - CW04","2022 - CW05","2022 - CW05","2022 - CW05","2022 - CW06","2022 - CW06","2022 - CW06","2022 - CW07","2022 - CW07","2022 - CW07","2022 - CW08","2022 - CW08","2022 - CW08"), xlabel2 = c("Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22") ) sample <- sample %>% mutate(date = as.Date(paste0(year_week, 1), "%Y - CW%U%u")) ggplot(sample ) + aes(x = date, y = qty, fill = service_type) + geom_col(position = "dodge") + geom_line(aes(group = 1), stat = "summary", fun = sum, linetype = "dashed", size = 1, color = '#FF507B') + geom_text(aes(label=qty), position=position_dodge(7 * 0.9), vjust = 0)+ scale_fill_manual(values = c(A = "#FFC000", B = "#92D050", C = "#AE5AFF"))+ scale_x_date( date_labels = "%Y - CW%U", date_breaks = "1 week", sec.axis = dup_axis( breaks = as.Date(paste0("15-", unique(sample$xlabel2)), "%d-%b-%y"), labels = \(x) format(x, "%b-%y") ) ) + theme_minimal() + theme(legend.position = "left", axis.text.x.bottom = element_text(angle=90, hjust=1, vjust = 0.5), axis.title = element_blank(), legend.title = element_blank(), panel.grid.minor.x = element_blank())
实现方案
方案1:直接用stat="summary"生成标签
因为折线图是通过stat="summary"计算每周qty总和,所以添加标签时可以复用相同的统计逻辑,直接在现有代码中新增一行geom_text:
ggplot(sample ) + aes(x = date, y = qty, fill = service_type) + geom_col(position = "dodge") + geom_line(aes(group = 1), stat = "summary", fun = sum, linetype = "dashed", size = 1, color = '#FF507B') + # 柱状图标签 geom_text(aes(label=qty), position=position_dodge(7 * 0.9), vjust = 0)+ # 新增:折线图总和标签 geom_text(aes(group = 1), stat = "summary", fun = sum, aes(label = after_stat(y)), color = '#FF507B', vjust = -1, size = 4) + scale_fill_manual(values = c(A = "#FFC000", B = "#92D050", C = "#AE5AFF"))+ scale_x_date( date_labels = "%Y - CW%U", date_breaks = "1 week", sec.axis = dup_axis( breaks = as.Date(paste0("15-", unique(sample$xlabel2)), "%d-%b-%y"), labels = \(x) format(x, "%b-%y") ) ) + theme_minimal() + theme(legend.position = "left", axis.text.x.bottom = element_text(angle=90, hjust=1, vjust = 0.5), axis.title = element_blank(), legend.title = element_blank(), panel.grid.minor.x = element_blank())
关键说明:
stat="summary", fun=sum:和折线图逻辑一致,计算每周qty总和aes(label = after_stat(y)):用统计后得到的总和值作为标签文本vjust = -1:让标签显示在折线点上方,避免和柱状图重叠color = '#FF507B':和折线颜色统一,提升视觉一致性
方案2:提前计算汇总数据(逻辑更清晰)
如果不想重复调用统计逻辑,可以先提前计算每周的qty总和,再单独绘制折线和标签:
# 预计算每周qty总和 sample_sum <- sample %>% group_by(date) %>% summarise(total_qty = sum(qty, na.rm = TRUE)) %>% ungroup() ggplot(sample ) + aes(x = date, y = qty, fill = service_type) + geom_col(position = "dodge") + # 使用预计算数据绘制折线 geom_line(data = sample_sum, aes(x = date, y = total_qty, group = 1), linetype = "dashed", size = 1, color = '#FF507B') + # 柱状图标签 geom_text(aes(label=qty), position=position_dodge(7 * 0.9), vjust = 0)+ # 使用预计算数据添加标签 geom_text(data = sample_sum, aes(x = date, y = total_qty, label = total_qty), color = '#FF507B', vjust = -1, size = 4) + scale_fill_manual(values = c(A = "#FFC000", B = "#92D050", C = "#AE5AFF"))+ scale_x_date( date_labels = "%Y - CW%U", date_breaks = "1 week", sec.axis = dup_axis( breaks = as.Date(paste0("15-", unique(sample$xlabel2)), "%d-%b-%y"), labels = \(x) format(x, "%b-%y") ) ) + theme_minimal() + theme(legend.position = "left", axis.text.x.bottom = element_text(angle=90, hjust=1, vjust = 0.5), axis.title = element_blank(), legend.title = element_blank(), panel.grid.minor.x = element_blank())
关键说明:
- 提前计算汇总数据让代码逻辑更直观,也方便后续对总和数据做额外处理
- 折线和标签都复用
sample_sum数据,避免重复统计计算
内容的提问来源于stack exchange,提问作者romina
相关产品推荐
相关产品推荐

