在ggplot分面图中绘制多组重叠折线并添加图例
问题描述
我正在用ggplot创建图表,需要在每个分面中显示两条重叠折线(分别代表实际运行小时均值、计划运行小时均值),同时在右侧添加图例区分两类折线。尝试过相关方法,但因需处理的是不同列而非同一变量内的分组,未能成功解决问题。注:当前案例中两条折线近乎一致,但其他场景下差异显著,故寻求帮助。
参考数据
structure(list(month_yr = c("2022-01", "2022-01", "2022-02", "2022-02", "2022-03", "2022-03", "2022-04", "2022-04", "2022-05", "2022-05", "2022-06", "2022-06", "2022-07", "2022-07", "2022-08", "2022-08", "2022-09", "2022-09", "2022-10", "2022-10", "2022-11", "2022-11", "2022-12", "2022-12", "2023-01", "2023-01", "2023-02", "2023-02"), plant_name = c("plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s" ), avg_run_hours = c(15.0080608695652, 16.3453608247423, 14.7394112149533, 16.1025555555556, 14.9570175438596, 15.7327777777778, 17.0074257425743, 16.5604901960784, 16.989010989011, 16.3021296296296, 14.8100961538462, 15.8714516129032, 16.5552083333333, 15.3971568627451, 16.2258771929825, 14.2616279069767, 17.2556179775281, 14.3790350877193, 16.3594903846154, 15.5988617886179, 14.4050925925926, 15.9334920634921, 14.3455056179775, 16.6322935779817, 16.6958762886598, 17.1025714285714, 16.046875, 16.8408695652174), avg_sched_run_hours = c(15.0267043478261, 16.4351340206186, 15.0025140186916, 16.2041555555556, 14.8281578947368, 15.9119814814815, 17.1840099009901, 16.7646666666667, 17.0109340659341, 16.4446388888889, 14.7679615384615, 16.1768790322581, 16.3242083333333, 15.7033333333333, 16.343701754386, 14.5158139534884, 17.4342921348315, 14.5827280701754, 16.4562692307692, 15.4149105691057, 14.2729537037037, 16.1438253968254, 14.3073595505618, 16.7186330275229, 16.6436082474227, 17.0332952380952, 16.3137916666667, 16.9656739130435)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -28L), groups = structure(list( month_yr = c("2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06", "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12", "2023-01", "2023-02"), .rows = structure(list( 1:2, 3:4, 5:6, 7:8, 9:10, 11:12, 13:14, 15:16, 17:18, 19:20, 21:22, 23:24, 25:26, 27:28), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -14L), .drop = TRUE))
当前代码
hours_by_plant <- ggplot(so_run_hour_stats, aes(x=month_yr, y=avg_sched_run_hours, group=1)) + geom_point() + geom_line(color="red") + xlab("Month of Year") + ylab("Avg Run Hours") + ggtitle("Avg Plant Run Hours by Month from 01/2022 - 02/2023") + theme_classic() + facet_wrap(~plant_name) hours_by_plant <- hours_by_plant + theme(plot.title = element_text(hjust = 0.5))
解决方案
核心是将数据转换为长格式,因为ggplot的分组和图例功能更适配长数据结构。使用tidyr::pivot_longer把两个小时列合并为一个数值列,同时新增一列标记数据类型(实际/计划),之后通过颜色映射实现分组折线和图例。
完整代码
library(tidyverse) # 取消数据分组并转换为长格式 so_run_hour_stats_long <- so_run_hour_stats %>% ungroup() %>% pivot_longer( cols = c(avg_run_hours, avg_sched_run_hours), names_to = "hour_type", values_to = "avg_hours" ) %>% # 重命名类型标签,让图例更清晰 mutate(hour_type = case_when( hour_type == "avg_run_hours" ~ "实际运行小时均值", hour_type == "avg_sched_run_hours" ~ "计划运行小时均值" )) # 绘制图表 hours_by_plant <- ggplot(so_run_hour_stats_long, aes(x = month_yr, y = avg_hours, color = hour_type, group = hour_type)) + geom_point() + geom_line() + xlab("年月") + ylab("平均运行小时") + ggtitle("2022年1月-2023年2月各工厂平均运行小时趋势") + theme_classic() + facet_wrap(~plant_name) + # 调整标题居中,自定义颜色(可选) theme(plot.title = element_text(hjust = 0.5)) + scale_color_manual(values = c("实际运行小时均值" = "blue", "计划运行小时均值" = "red")) # 显示图表 print(hours_by_plant)
代码说明
- 数据转换:
pivot_longer将原数据的两个小时列整合,生成hour_type(数据类型)和avg_hours(数值)两列,让ggplot能通过hour_type进行分组。 - 映射设置:在
aes中指定color = hour_type和group = hour_type,ggplot会自动为不同类型生成不同颜色的折线,并创建对应的图例。 - 自定义优化:用
mutate修改类型标签为中文,scale_color_manual自定义折线颜色,提升图表可读性。
内容的提问来源于stack exchange,提问作者user3736739
相关产品推荐
相关产品推荐

