ggplot中如何对分组geom_line/geom_point排序后同图不分面绘制
问题根因
排序仅在第一个分组生效的核心原因是:原数据中的team列是全局行序号,没有在每个drafted_qbs分组内,按season_pts排序后重新生成组内位置索引。直接将全局team映射到坐标轴位置时,只有第一个分组的行序号刚好和排序后的位置匹配,其余分组的点位、连线顺序都会错位。
实现方案
无需使用分面功能,直接在数据预处理层完成分组排序、生成组内位置索引后再做绘图映射即可,核心步骤如下:
- 按
drafted_qbs字段拆分分组 - 每个分组内部按
season_pts做降序排序 - 为每个分组生成独立的组内排名序号,替代原全局
team列作为x轴位置映射变量 - 绘图时将
drafted_qbs映射为分组、颜色区分维度,保证不同分组的点线可识别,按新生成的组内排名连接线条、放置点位
可复现代码
library(ggplot2) library(dplyr) # 载入示例数据 df <- structure(list(team = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), season_pts = c(447.44, 381.62, 416.6, 367.96, 419.92, 490.78, 501.66, 458.56, 484.48, 458.36, 518, 495.7, 511.34, 499.68, 536.42, 522.92, 536.92, 518.46, 538.06, 525.96, 541.84, 523.26, 542.98, 527.4, 527), drafted_qbs = c(2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -25L)) # 分组排序并生成组内排名索引 df_plot <- df %>% group_by(drafted_qbs) %>% # 按赛季积分降序排列,积分越高排名越靠前,需要升序则去掉desc() arrange(desc(season_pts), .by_group = TRUE) %>% mutate(rank_in_group = row_number()) %>% ungroup() # 绘图,无分面 ggplot(df_plot, aes(x = rank_in_group, y = season_pts)) + geom_line(aes(group = drafted_qbs, color = factor(drafted_qbs)), linewidth = 1) + geom_point(aes(color = factor(drafted_qbs)), size = 3) + scale_x_continuous(breaks = 1:5, labels = paste0("第", 1:5, "名")) + labs(x = "分组内积分排名", y = "赛季总积分", color = "选中QB数量") + theme_bw()
效果说明
- 所有
drafted_qbs分组的点、线都会独立按season_pts排序,不会出现仅第一个分组排序正确的错位问题 - 不同分组通过颜色区分,全部元素绘制在同一张画布上,符合不使用分面的要求
- 原全局
team列不再参与位置映射,从根源上避免了全局行序号对分组排序的干扰
内容的提问来源于stack exchange,提问作者Jeff Henderson
相关产品推荐
相关产品推荐

