如何在ggplot双轴图中分离形状与颜色的重叠图例?
解决方案
要解决图例重叠的问题,核心是将数据整理为长格式,让每个观测值对应明确的变量类型(rh/t)和所属传感器,这样就能在ggplot的美学映射中分别绑定shape(变量类型)和color(传感器),从而生成两个独立的图例。
步骤1:整理数据
使用tidyr::pivot_longer将宽格式数据转换为长格式,同时整合对应的传感器信息:
library(tidyverse) scale <- 2 weather_long <- weather %>% pivot_longer( cols = c(t, rh), names_to = "variable", values_to = "value" ) %>% # 匹配每个变量对应的传感器 mutate( sensor = case_when( variable == "t" ~ sensor_t, variable == "rh" ~ sensor_rh ), # 对t值进行缩放适配左轴 scaled_value = ifelse(variable == "t", value * scale, value) )
步骤2:绘制双轴散点图
基于整理后的长格式数据绘图,将shape映射到variable,color映射到sensor,并分别设置图例:
ggplot(weather_long, aes(x = time)) + geom_point(aes(y = scaled_value, shape = variable, color = sensor), size = 3) + # 设置形状图例 scale_shape_manual( name = "Variable", values = c("rh" = 1, "t" = 3), guide = guide_legend(title.position = "top", title.hjust = 0.5) ) + # 设置颜色图例 scale_color_manual( name = "Sensor", values = c("A" = "red", "B" = "blue", "C" = "green"), guide = guide_legend(title.position = "top", title.hjust = 0.5) ) + # 设置双轴 scale_y_continuous( name = "rh(%)", sec.axis = sec_axis(~./scale, name = "t(°C)") ) + labs(x = "Time") + theme(legend.position = "bottom", legend.box = "horizontal")
原代码问题说明
- 原代码中
color分别映射了sensor_rh和sensor_t两个独立变量,ggplot会将它们视为同一个color美学的冲突输入,导致图例合并重叠。 shape没有绑定到数据中的变量,只是手动给两个geom_point指定形状,无法生成与数据关联的独立图例。
整理成长格式后,每个点的变量类型和传感器信息一一对应,美学映射逻辑清晰,自然能生成两个独立且正确的图例。
内容的提问来源于stack exchange,提问作者T.Becker
相关产品推荐
相关产品推荐

