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

如何为ggplot2各Utterance分面独立设置颜色刻度范围?

问题描述

我有Utterance中音节的dur(时长)数据,想用ggplot2的geom_tile绘制。当前实现的问题是颜色刻度基于整个数据框的音节时长最大值设定,我想要每个Utterance的颜色刻度范围统一——不管某个Utterance有多少音节,它里面最短和最长的音节,要和其他Utterance里的最短、最长音节对应相同的颜色色调。

当前代码:

library(ggplot2)
df %>%
  ggplot(aes(x = start + dur/2, y = MM, width = dur, height = 0.3, fill = rank)) +
  geom_tile(size = 0.65, color = "white") +
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1)+
  labs(fill = "SyllDur")

数据结构:

df <- structure(list(Utterance = structure(c(1L, 4L, 4L, 1L, 4L, 1L, 
1L, 4L, 1L, 4L, 4L, 1L, 4L, 4L, 4L, 4L, 4L, 4L), levels = c("C: [what's] a !mountain! for you:", 
"NA: (0.554)", "C: ((v: laughs))=", "A: =I don't know the (Schauinsland) is a small mount[ain]"
), class = "factor"), MM = c("syll", "syll", "syll", "syll", 
"syll", "syll", "syll", "syll", "syll", "syll", "syll", "syll", 
"syll", "syll", "syll", "syll", "syll", "syll"), start = c(407, 
3967, 4827, 1147, 3682, 577, 847, 4697, 0, 4317, 3807, 1340, 
5287, 4457, 3437, 4037, 4917, 5517), dur = c(170L, 70L, 90L, 
193L, 125L, 270L, 300L, 130L, 407L, 140L, 160L, 480L, 230L, 240L, 
245L, 280L, 370L, 538L), rank = c(1, 1, 2, 2, 3, 3, 4, 4, 5, 
5, 6, 6, 7, 8, 9, 10, 11, 12)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -18L))
解决方案

核心思路是按每个Utterance分组,对dur进行归一化处理,让每个组内的dur都映射到[0,1]区间,这样所有Utterance的颜色刻度就能统一:最短音节对应颜色标尺的最小值,最长对应最大值。

具体实现代码

library(ggplot2)
library(dplyr)

# 对每个Utterance的时长做组内归一化
df_normalized <- df %>%
  group_by(Utterance) %>%
  mutate(norm_dur = (dur - min(dur)) / (max(dur) - min(dur))) %>%
  ungroup()

# 绘制图形
df_normalized %>%
  ggplot(aes(x = start + dur/2, y = MM, width = dur, height = 0.3, fill = norm_dur)) +
  geom_tile(size = 0.65, color = "white") +
  facet_wrap(~ Utterance, scales = "free_x", ncol = 1) +
  # 自定义颜色渐变,可选将归一化值转回原始时长刻度
  scale_fill_gradient(
    name = "SyllDur",
    low = "#f7fbff",
    high = "#08306b",
    labels = function(x) {
      # 用全局时长极值生成刻度标签,让图例更直观
      global_min <- min(df$dur)
      global_max <- max(df$dur)
      round(x * (global_max - global_min) + global_min)
    }
  ) +
  labs(x = "Time", y = "Syllable")

代码说明

  • norm_dur = (dur - min(dur)) / (max(dur) - min(dur)):把每个Utterance内的时长转换为0到1之间的数值,0对应组内最短时长,1对应组内最长时长,保证所有组的颜色映射基准一致
  • scale_fill_gradient():自定义颜色渐变风格,通过labels参数将归一化数值转回原始时长刻度,避免图例显示0-1的抽象范围
  • 保留scales = "free_x",确保每个Utterance的时间轴范围独立显示,不互相干扰

如果不需要原始时长的刻度标签,直接使用norm_dur作为fill的映射变量即可,图例会显示0-1范围,同样能满足颜色统一的需求。

内容的提问来源于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.26 00:14:52