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

如何在ggplot的geom_segment对话注视方向图中视觉分隔相邻线段?

问题描述

我用geom_segment绘制对话中的注视方向图,但线段颜色相近时,很难区分一段线段的结束和另一段的起始。请问怎么插入分割类视觉元素(比如矩形或竖线),让不同线段的分隔效果更直观?

原绘图代码

library(ggnewscale)
ggplot(data = df1, 
       aes(x = start, xend = end,
           y = MM_by, yend = MM_by,               
           color = MM_annotation)) +
  geom_segment(size = 4) +
  scale_y_discrete(name = NULL, limits = rev) +        
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1) +

scale_colour_manual(values = c("*" = "white",    
                               "A" = "yellow",    
                               "B" = "lawngreen",
                               "C" = "cyan"),   
                    # 重命名图例标题:
                    name = "Gaze to")

数据集

df1 <- structure(list(Line = c(569L, 569L, 569L, 569L, 569L, 569L, 569L, 
569L, 569L, 569L, 570L, 570L, 570L, 570L, 571L, 571L, 571L, 573L, 
573L, 573L, 573L, 573L, 573L), Speaker = c("ID01.C", "ID01.C", 
"ID01.C", "ID01.C", "ID01.C", "ID01.C", "ID01.C", "ID01.C", "ID01.C", 
"ID01.C", NA, NA, NA, NA, "ID01.C", "ID01.C", "ID01.C", "ID01.A", 
"ID01.A", "ID01.A", "ID01.A", "ID01.A", "ID01.A"), Timestamp = c("00:12:02.300 - 00:12:04.113", 
"00:12:02.300 - 00:12:04.113", "00:12:02.300 - 00:12:04.113", 
"00:12:02.300 - 00:12:04.113", "00:12:02.300 - 00:12:04.113", 
"00:12:02.300 - 00:12:04.113", "00:12:02.300 - 00:12:04.113", 
"00:12:02.300 - 00:12:04.113", "00:12:02.300 - 00:12:04.113", 
"00:12:02.300 - 00:12:04.113", "00:12:04.113 - 00:12:04.667", 
"00:12:04.113 - 00:12:04.667", "00:12:04.113 - 00:12:04.667", 
"00:12:04.113 - 00:12:04.667", "00:12:04.667 - 00:12:05.737", 
"00:12:04.667 - 00:12:05.737", "00:12:04.667 - 00:12:05.737", 
"00:12:05.777 - 00:12:08.395", "00:12:05.777 - 00:12:08.395", 
"00:12:05.777 - 00:12:08.395", "00:12:05.777 - 00:12:08.395", 
"00:12:05.777 - 00:12:08.395", "00:12:05.777 - 00:12:08.395"), 
    Utterance = c("[what's] a !mountain! for you:", "[what's] a !mountain! for you:", 
    "[what's] a !mountain! for you:", "[what's] a !mountain! for you:", 
    "[what's] a !mountain! for you:", "[what's] a !mountain! for you:", 
    "[what's] a !mountain! for you:", "[what's] a !mountain! for you:", 
    "[what's] a !mountain! for you:", "[what's] a !mountain! for you:", 
    "(0.554)", "(0.554)", "(0.554)", "(0.554)", "((v: laughs))=", 
    "((v: laughs))=", "((v: laughs))=", "=I don't know the (Schauinsland) is a small mount[ain]", 
    "=I don't know the (Schauinsland) is a small mount[ain]", 
    "=I don't know the (Schauinsland) is a small mount[ain]", 
    "=I don't know the (Schauinsland) is a small mount[ain]", 
    "=I don't know the (Schauinsland) is a small mount[ain]", 
    "=I don't know the (Schauinsland) is a small mount[ain]"), 
    File = c("F01", "F01", "F01", "F01", "F01", "F01", "F01", 
    "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", 
    "F01", "F01", "F01", "F01", "F01", "F01", "F01"), Starttime_ms = c(722300L, 
    722300L, 722300L, 722300L, 722300L, 722300L, 722300L, 722300L, 
    722300L, 722300L, 724113L, 724113L, 724113L, 724113L, 724667L, 
    724667L, 724667L, 725777L, 725777L, 725777L, 725777L, 725777L, 
    725777L), Endtime_ms = c(724113, 724113, 724113, 724113, 
    724113, 724113, 724113, 724113, 724113, 724113, 724667, 724667, 
    724667, 724667, 725737, 725737, 725737, 728395, 728395, 728395, 
    728395, 728395, 728395), UttEnd = c(1813, 1813, 1813, 1813, 
    1813, 1813, 1813, 1813, 1813, 1813, 2367, 2367, 2367, 2367, 
    3437, 3437, 3437, 6055, 6055, 6055, 6055, 6055, 6055), UttStart = c(0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1813, 1813, 1813, 1813, 2367, 
    2367, 2367, 3437, 3437, 3437, 3437, 3437, 3437), MM_by = c("A", 
    "A", "A", "A", "B", "B", "B", "B", "B", "C", "A", "A", "B", 
    "C", "A", "B", "C", "A", "A", "B", "B", "C", "C"), MM = c("aoi", 
    "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", 
    "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", "aoi", 
    "aoi", "aoi", "aoi", "aoi"), MM_annotation = c("*", "B", 
    "*", "C", "A", "*", "C", "*", "A", "A", "C", "*", "A", "A", 
    "*", "A", "A", "*", "C", "A", "*", "A", "*"), dur = c(400L, 
    467L, 66L, 887L, 693L, 247L, 473L, 147L, 260L, 1820L, 353L, 
    207L, 567L, 567L, 1060L, 1060L, 1060L, 1000L, 1620L, 306L, 
    2314L, 2300L, 320L), end = c(400, 867, 933, 1820, 693, 940, 
    1413, 1560, 1820, 1820, 2166, 2373, 2380, 2380, 3427, 3427, 
    3427, 4437, 6057, 3743, 6057, 5737, 6057), start = c(0, 400, 
    867, 933, 0, 693, 940, 1413, 1560, 0, 1813, 2166, 1813, 1813, 
    2367, 2367, 2367, 3437, 4437, 3437, 3743, 3437, 5737)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -23L))

解决方案

方法1:添加竖线分隔线段

提取每个线段的起止节点,用geom_vline绘制细竖线作为分隔,能清晰区分相邻线段:

library(dplyr)

# 提取每个分组内的分割点(排除首尾端点)
split_points <- df1 %>%
  group_by(Utterance, MM_by) %>%
  summarise(x = unique(c(start, end)), .groups = "drop") %>%
  filter(x != min(x, na.rm = TRUE) & x != max(x, na.rm = TRUE))

# 修改绘图代码,加入竖线分隔
ggplot(data = df1, 
       aes(x = start, xend = end,
           y = MM_by, yend = MM_by,               
           color = MM_annotation)) +
  geom_segment(size = 4) +
  # 添加黑色细竖线作为分隔
  geom_vline(data = split_points, aes(xintercept = x), 
             color = "black", linewidth = 0.5) +
  scale_y_discrete(name = NULL, limits = rev) +        
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1) +
  scale_colour_manual(values = c("*" = "white",    
                                 "A" = "yellow",    
                                 "B" = "lawngreen",
                                 "C" = "cyan"),   
                      name = "Gaze to")

方法2:添加矩形背景区分线段

给每个线段添加浅色矩形背景,通过色块边界自然区分相邻线段:

# 生成矩形背景数据,扩展y轴范围避免遮挡线段
rect_data <- df1 %>%
  mutate(y_min = as.numeric(factor(MM_by)) - 0.4,
         y_max = as.numeric(factor(MM_by)) + 0.4)

ggplot(data = df1, 
       aes(x = start, xend = end,
           y = MM_by, yend = MM_by,               
           color = MM_annotation)) +
  # 先绘制浅色矩形背景
  geom_rect(data = rect_data, aes(xmin = start, xmax = end, ymin = y_min, ymax = y_max),
            fill = "gray90", color = NA, inherit.aes = FALSE) +
  geom_segment(size = 4) +
  scale_y_discrete(name = NULL, limits = rev) +        
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1) +
  scale_colour_manual(values = c("*" = "white",    
                                 "A" = "yellow",    
                                 "B" = "lawngreen",
                                 "C" = "cyan"),   
                      name = "Gaze to")

方法3:调整线段间隙

给每个线段的起止点微调,让相邻线段间出现微小空白间隙,无需额外元素即可区分:

ggplot(data = df1 %>% mutate(start = start + 5, end = end - 5), 
       aes(x = start, xend = end,
           y = MM_by, yend = MM_by,               
           color = MM_annotation)) +
  geom_segment(size = 4) +
  scale_y_discrete(name = NULL, limits = rev) +        
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1) +
  scale_colour_manual(values = c("*" = "white",    
                                 "A" = "yellow",    
                                 "B" = "lawngreen",
                                 "C" = "cyan"),   
                      name = "Gaze to")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:32:01