You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ggplot线段按delta值像scale_color_gradient2那样渐变着色?

问题描述

我有一个名为test_data的数据框,包含recent(当年数值)、before(前一年数值)以及两者的差值delta。在ggplot绘图中,点已经通过scale_color_gradient2按delta值实现了渐变着色,线段用于连接点与对角线(虚线),但目前只能将负delta的线段设为统一红色、正delta的线段设为统一绿色,无法体现delta的具体数值差异。请问能否让线段也像点一样,根据delta值通过scale_color_gradient2实现渐变着色?

可复现代码:

library(ggplot2)
library(dplyr)

test_data<-structure(list(recent = c(65.2997185753145, 59.7196309660111,
                                     69.6283618162288, 72.8567667757411, 75.5042106908949, 65.9349599258225, 
                                     63.821946931775, 84.5492780693781, 70.1954593423904, 68.7330477506608, 
                                     74.7016955531504, 71.0329793728603, 90.8076584032142, 72.1556242719194),
                          before = c(68.1971224074475, 53.6815581922758, 67.3141074572482,
                                     70.8701488937935, 73.9713609414785, 63.2296191743796, 56.6943338152896, 
                                     81.7035240884654, 77.3175553964688, 69.7366705789213, 78.2019304405689, 
                                     71.6072916545225, 86.8455685297511, 75.7745946931338),
                          delta = c(-2.89740383213299, 6.03807277373529, 2.31425435898061, 
                                    1.98661788194759, 1.5328497494164, 2.7053407514429, 7.1276131164854, 
                                    2.8457539809127, -7.1220960540784, -1.0036228282605, -3.5002348874185, 
                                    -0.574312281662188, 3.96208987346309, -3.6189704212144)),
                      
                     row.names = c(NA,-14L),
                     class = "data.frame")

test_data<-test_data%>%
  mutate(x1_neg=case_when(delta<0 ~ before),
         y1_neg=case_when(delta<0 ~ recent),
         x2_neg=case_when(delta<0 ~ recent),
         y2_neg=case_when(delta<0 ~ recent))%>%
  mutate(x1_pos=case_when(delta>0 ~ before),
         y1_pos=case_when(delta>0 ~ recent),
         x2_pos=case_when(delta>0 ~ before),
         y2_pos=case_when(delta>0 ~ before))


plt<-ggplot(test_data, aes(x=before,y=recent))+
  geom_abline(slope=1,linetype = "dashed")+
  geom_segment(aes(x = x1_neg, y = y1_neg, xend = x2_neg, yend = y2_neg),
               colour="#E24C3B",
               size=1.3)+
  geom_segment(aes(x = x1_pos, y = y1_pos, xend = x2_pos, yend = y2_pos),
               colour="#ADCA1E",
               size=1.3)+
  geom_point(aes(color=delta),size=3)+
  scale_color_gradient2(high = "#ADCA1E",mid="#6ECFF6",low = "#E24C3B")+
  theme(plot.background = element_rect(fill = "#FFFFFF"),
        panel.background = element_rect(fill = "#FFFFFF"),
        axis.line = element_line(colour = "black"),
        panel.grid = element_line(colour = "#D2D0CF"),
        legend.justification = "bottom")+
  ylab("recent")+
  xlab("before")+
  coord_fixed()

x11(5,5)

plt

当前效果:点按delta值渐变着色,但线段仅按正负显示统一的红/绿色,无法体现delta的数值差异。

解决方案

可以通过以下修改实现线段的渐变着色:

  1. 无需拆分正负线段的单独列,直接在geom_segment中动态计算线段的终点(即对角线上的对应点)
  2. 将geom_segment的color映射到delta,共享和点一样的颜色渐变尺度

修改后的完整代码:

library(ggplot2)
library(dplyr)

test_data<-structure(list(recent = c(65.2997185753145, 59.7196309660111,
                                     69.6283618162288, 72.8567667757411, 75.5042106908949, 65.9349599258225, 
                                     63.821946931775, 84.5492780693781, 70.1954593423904, 68.7330477506608, 
                                     74.7016955531504, 71.0329793728603, 90.8076584032142, 72.1556242719194),
                          before = c(68.1971224074475, 53.6815581922758, 67.3141074572482,
                                     70.8701488937935, 73.9713609414785, 63.2296191743796, 56.6943338152896, 
                                     81.7035240884654, 77.3175553964688, 69.7366705789213, 78.2019304405689, 
                                     71.6072916545225, 86.8455685297511, 75.7745946931338),
                          delta = c(-2.89740383213299, 6.03807277373529, 2.31425435898061, 
                                    1.98661788194759, 1.5328497494164, 2.7053407514429, 7.1276131164854, 
                                    2.8457539809127, -7.1220960540784, -1.0036228282605, -3.5002348874185, 
                                    -0.574312281662188, 3.96208987346309, -3.6189704212144)),
                      
                     row.names = c(NA,-14L),
                     class = "data.frame")

plt<-ggplot(test_data, aes(x=before,y=recent))+
  geom_abline(slope=1,linetype = "dashed")+
  # 动态设置线段终点,并映射color到delta
  geom_segment(
    aes(
      xend = ifelse(delta < 0, recent, before),
      yend = ifelse(delta < 0, recent, before),
      color = delta
    ),
    size=1.3
  )+
  geom_point(aes(color=delta),size=3)+
  scale_color_gradient2(high = "#ADCA1E",mid="#6ECFF6",low = "#E24C3B")+
  theme(plot.background = element_rect(fill = "#FFFFFF"),
        panel.background = element_rect(fill = "#FFFFFF"),
        axis.line = element_line(colour = "black"),
        panel.grid = element_line(colour = "#D2D0CF"),
        legend.justification = "bottom")+
  ylab("recent")+
  xlab("before")+
  coord_fixed()

x11(5,5)

plt
代码说明
  • 去掉了原代码中用于拆分正负线段的x1_neg、y1_neg等辅助列,改用ifelse在geom_segment中直接计算线段终点:
    • 当delta < 0时,线段终点为(recent, recent)(对角线上的点),对应原代码中的负delta线段
    • 当delta > 0时,线段终点为(before, before)(对角线上的点),对应原代码中的正delta线段
  • 将geom_segment的color参数放入aes()中并映射到delta,这样线段会和点使用同一个scale_color_gradient2尺度,实现渐变着色
  • 保留了原有的主题、坐标轴、颜色渐变设置,确保整体风格一致

内容的提问来源于stack exchange,提问作者michel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:13:10