ggplot2中geom_segments尺寸不同导致图例重叠的解决方法
解决ggplot2中不同size线段图例重叠的问题
问题根源
你的代码中为不同国家分别调用了多组geom_segment,且size是作为固定参数而非美学映射(aes)传入的,这导致ggplot会将所有线段的图例元素叠加显示,最终出现不同尺寸的虚线/点线重叠的问题。
两种解决方案
方案1:通过override.aes修正图例(无需重构数据)
直接在图例设置中强制指定每个国家对应的线条尺寸,同时合并颜色和线型图例,避免重叠:
dataframe = data.frame(country = c("Burundi", "Kenya"), rate1 = c(10, 3), threshold1 = c(180, 72.2), rate2 = c(25, 20), threshold2 = c(242, 144), rate3 = c(30,30)) xstart_limit <- 0 xend_limit <- 10000 linetypes <- c("dotted", "dashed") my_colors <- c("blue","red") sizes <- c(1, 0.6) # 对应Burundi和Kenya的线条尺寸 pit_comparison2 <- ggplot() + # 保留原有geom_segment代码 geom_segment(aes(x = xstart_limit, y = rate1, xend = threshold1, yend = rate1, colour = country, linetype = country), size = 0.6, data = dataframe[dataframe$country == "Kenya",]) + geom_segment(aes(x = threshold1, y = rate1, xend = threshold1, yend = rate2, colour = country, linetype = country), size = 0.6, data = dataframe[dataframe$country == "Kenya",]) + geom_segment(aes(x = threshold1, y = rate2, xend = threshold2, yend = rate2, colour = country, linetype = country), size = 0.6, data = dataframe[dataframe$country == "Kenya",]) + geom_segment(aes(x = threshold2, y = rate2, xend = threshold2, yend = rate3, colour = country, linetype = country), size = 0.6, data = dataframe[dataframe$country == "Kenya",]) + geom_segment(aes(x = threshold2, y = rate3, xend = xend_limit, yend = rate3, colour = country, linetype = country), size = 0.6, data = dataframe[dataframe$country == "Kenya",]) + geom_segment(aes(x = xstart_limit, y = rate1, xend = threshold1, yend = rate1, colour = country, linetype = country), size = 1, data = dataframe[dataframe$country == "Burundi",]) + geom_segment(aes(x = threshold1, y = rate1, xend = threshold1, yend = rate2, colour = country, linetype = country), size = 1, data = dataframe[dataframe$country == "Burundi",]) + geom_segment(aes(x = threshold1, y = rate2, xend = threshold2, yend = rate2, colour = country, linetype = country), size = 1, data = dataframe[dataframe$country == "Burundi",]) + geom_segment(aes(x = threshold2, y = rate2, xend = threshold2, yend = rate3, colour = country, linetype = country), size = 1, data = dataframe[dataframe$country == "Burundi",]) + geom_segment(aes(x = threshold2, y = rate3, xend = xend_limit, yend = rate3, colour = country, linetype = country), size = 1, data = dataframe[dataframe$country == "Burundi",]) + scale_linetype_manual(values = linetypes, breaks=c("Burundi", "Kenya")) + scale_color_manual(values = my_colors, breaks=c("Burundi", "Kenya")) + # 关键:强制指定图例中每个项的尺寸,合并图例避免重叠 guides( colour = guide_legend(override.aes = list(size = sizes)), linetype = guide_legend(override.aes = list(size = sizes)) ) pit_comparison2
方案2:重构数据(更简洁易维护)
将所有线段的起点、终点整理成长格式数据框,把size映射到美学属性中,让ggplot自动生成正确的图例:
library(tidyr) library(dplyr) dataframe = data.frame(country = c("Burundi", "Kenya"), rate1 = c(10, 3), threshold1 = c(180, 72.2), rate2 = c(25, 20), threshold2 = c(242, 144), rate3 = c(30,30)) xstart_limit <- 0 xend_limit <- 10000 linetypes <- c("dotted", "dashed") my_colors <- c("blue","red") # 重构数据:拆分每个国家的所有线段为单独行 seg_data <- dataframe %>% rowwise() %>% summarise( country = country, x = c(xstart_limit, threshold1, threshold1, threshold2, threshold2), y = c(rate1, rate1, rate2, rate2, rate3), xend = c(threshold1, threshold1, threshold2, threshold2, xend_limit), yend = c(rate1, rate2, rate2, rate3, rate3), .groups = "drop" ) %>% mutate(size = ifelse(country == "Burundi", 1, 0.6)) # 绘制图形,size作为美学映射 pit_comparison3 <- ggplot(seg_data) + geom_segment(aes(x = x, y = y, xend = xend, yend = yend, colour = country, linetype = country, size = country)) + scale_linetype_manual(values = linetypes) + scale_color_manual(values = my_colors) + scale_size_manual(values = c("Burundi" = 1, "Kenya" = 0.6)) + # 合并所有图例为一个,更整洁 guides(color = guide_legend(), linetype = guide_legend(), size = guide_legend()) + theme(legend.box = "vertical") pit_comparison3
内容的提问来源于stack exchange,提问作者Antoine D
相关产品推荐
相关产品推荐

