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

如何在ggplot的geom_density_ridges中按ID分组可视化堆叠密度曲线?

如何在密度脊线图中按分组堆叠填充颜色?

我已经绘制了展示一周每日时间模式的密度脊线图,想要在每天的曲线内按ID列(取值如True/False或A/B)分组,用两种颜色堆叠显示,明确区分不同组对峰值的贡献,但设置color = ID, fill = ID无效,请问该怎么实现?

现有代码:

ggplot(aes(x = weekdaytime, y = weekday, fill = weekday, group = weekday, height = ..count..)) +
 geom_density_ridges_gradient(stat = "density", scale = 2, rel_min_height = 0.01, bw = 300 ) +
 scale_fill_viridis(name = "", option = "C") +
 scale_x_datetime(date_breaks = "2 hour", date_labels = "%H", 
                  limits = as.POSIXct(strptime(c(paste(Sys.Date(), "00:00", sep=" "),
                                                 paste(Sys.Date(), "24:00", sep=" ")), 
                                               format = "%Y-%m-%d %H:%M"))) +
 scale_y_discrete(limits=c("Monday", "Tuesday", "Wednesday", "Thursday", 
                           "Friday", "Saturday", "Sunday"))+
 theme(
   legend.position="none",
   panel.spacing = unit(0.1, "lines"),
   panel.grid.major = element_line(colour = "grey"),
   panel.grid.minor = element_line(colour = "grey"),
   
   panel.background = element_blank(),
   strip.text.x = element_text(size = 7)
 )  

解决方案

geom_density_ridges_gradient本身不支持堆叠填充逻辑,要实现分组堆叠的密度脊线,需要先手动计算各组密度并累加,再用支持堆叠的图层绘制:

1. 预处理数据:计算分组密度并累加

先按weekday和ID分组计算密度,统一x轴范围保证数据对齐,再对每个时间点的密度值按分组累加,得到堆叠的高度:

library(dplyr)
library(purrr)
library(ggplot2)
library(ggridges)

# 假设你的数据集名为df,包含weekdaytime、weekday、ID三列
dens_data <- df %>%
  group_by(weekday, ID) %>%
  nest() %>%
  # 计算密度,统一x轴的起止范围和断点数量
  mutate(
    dens = map(data, ~density(
      as.numeric(.x$weekdaytime),
      from = as.numeric(as.POSIXct(paste(Sys.Date(), "00:00"))),
      to = as.numeric(as.POSIXct(paste(Sys.Date(), "24:00"))),
      n = 1000,
      bw = 300 # 和原代码保持一致的带宽
    )),
    # 提取密度的x(时间)和y(密度值)并转换格式
    dens_df = map(dens, ~tibble(
      x = as.POSIXct(.x$x, origin = "1970-01-01"),
      y = .x$y
    ))
  ) %>%
  select(-data, -dens) %>%
  unnest(dens_df) %>%
  ungroup() %>%
  # 按星期和时间点,对密度值按ID分组累加,得到堆叠高度
  group_by(weekday, x) %>%
  arrange(ID) # 控制堆叠顺序,可根据需求调整
  mutate(cum_y = cumsum(y)) %>%
  ungroup()

2. 绘制堆叠密度脊线图

用geom_ridgeline图层,基于预处理好的累加密度值绘制堆叠效果,填充色绑定ID:

ggplot(dens_data, aes(x = x, y = weekday, group = interaction(weekday, ID), height = cum_y, fill = ID)) +
  geom_ridgeline(scale = 2, rel_min_height = 0.01, alpha = 0.7) +
  # 自定义两种分组颜色,可替换为你需要的配色
  scale_fill_manual(values = c("#2c3e50", "#e74c3c")) +
  scale_x_datetime(
    date_breaks = "2 hour", 
    date_labels = "%H", 
    limits = as.POSIXct(strptime(c(paste(Sys.Date(), "00:00"), paste(Sys.Date(), "24:00")), format = "%Y-%m-%d %H:%M"))
  ) +
  scale_y_discrete(limits = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")) +
  theme(
    panel.spacing = unit(0.1, "lines"),
    panel.grid.major = element_line(colour = "grey"),
    panel.grid.minor = element_line(colour = "grey"),
    panel.background = element_blank(),
    strip.text.x = element_text(size = 7)
  )

关键说明

  • 必须手动计算密度:geom_density_ridges_gradient的内置统计只会计算整体密度,无法按分组拆分并堆叠,因此需要提前处理数据。
  • 统一密度参数:计算密度时的from、to、n参数必须一致,确保不同组的时间点完全对齐,否则累加会出错。
  • 分组交互:interaction(weekday, ID)确保每个星期的每个分组都生成独立的脊线,避免图层重叠混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:40:35