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

求助:使用ggplot绘制跨6am-次日6am的多事件时间序列堆叠条形图

问题:创建跨日夜的事件时长堆叠条形图

需要生成堆叠条形图,展示每日3个事件的持续时长:

  • X轴为日期
  • Y轴时间范围设定为当日6:00至次日6:00
  • 用堆叠形式区分三个事件的时长

提供的数据如下:

TS <- data.frame(Date = c("01/07/1985", "02/07/1985", "03/07/1985", 
"04/07/1985", "05/07/1985", "06/07/1985", "07/07/1985", "08/07/1985", 
"09/07/1985", "10/07/1985", "11/07/1985", "12/07/1985", "13/07/1985", 
"14/07/1985", "15/07/1985", "16/07/1985", "17/07/1985", "18/07/1985", 
"19/07/1985", "20/07/1985", "21/07/1985"), Event1_start = c("05:46", 
"05:45", "05:45", "05:44", "05:44", "05:43", "05:43", "05:42", 
"05:47", "05:47", "05:46", "05:46", "05:45", "05:45", "05:44", 
"05:44", "05:43", "05:43", "05:42", "05:47", "05:47"), Event1_end = c("18:33", 
"18:33", "18:33", "18:33", "18:33", "18:33", "18:32", "18:32", 
"18:33", "18:33", "18:33", "18:33", "18:33", "18:33", "18:33", 
"18:33", "18:33", "18:32", "18:32", "18:33", "18:33"), Event2_start = c("19:08", 
"19:59", "20:52", "21:49", "22:48", "23:50", "00:52", "04:39", 
"05:39", "06:39", "07:39", "08:39", "09:39", "10:39", "11:39", 
"12:39", "13:39", "14:39", "15:39", "16:39", "17:29"), Event2_end = c("07:27", 
"08:12", "09:00", "09:52", "10:49", "11:49", "12:51", "17:17", 
"18:17", "19:17", "20:17", "21:17", "22:17", "23:17", "00:17", 
"01:17", "02:17", "03:17", "04:17", "05:17", "06:00"), Event3_start = c("18:33", 
"18:33", "18:33", "18:33", "18:33", "18:33", "18:32", "18:32", 
"18:33", "18:33", "18:33", "18:33", "18:33", "18:33", "18:33", 
"18:33", "18:33", "18:33", "18:33", "18:33", "18:33"), Event3_end = c("19:08", 
"19:59", "20:52", "21:49", "22:48", "23:50", "00:52", "01:52", 
"05:47", "05:46", "05:46", "05:45", "05:45", "05:44", "05:44", 
"05:43", "05:43", "05:42", "05:42", "05:42", "05:42"))

之前尝试的代码无法正常运行:

L1<- TS %>% 
  gather(variable, value, 2:7) %>% mutate (variable = factor(variable, levels = c("Event1_start","Event1_end","Event2_start","Event2_end","Event3_start","Event3_end"))) %>%
  ggplot(aes(x = Date, y = value, fill = variable)) + scale_y_continuous(breaks = c(6,12,18,0,6)) +
  geom_bar(stat = "identity", width = 0.95) + scale_fill_manual(values = c("#c7e6ff","black","#f5eea6"), labels = c("Event1","Event2", "Event3"))

解决方案

1. 数据预处理:转换时间为数值并计算时长

首先需要把时间字符串转换为小时数值(如05:46转为5+46/60≈5.77),同时处理跨天的情况(结束时间在次日的,数值加24)。然后计算每个事件的有效时长(只统计当日6:00到次日6:00范围内的部分)。

library(tidyverse)

# 定义时间转小时的函数
time_to_hour <- function(time_str) {
  hms::parse_hm(time_str) %>% 
    period_to_seconds() %>% 
    divide_by(3600)
}

# 处理数据,计算每个事件的时长(限定在6:00-次日6:00即6-30小时)
processed_data <- TS %>%
  mutate(
    # 转换所有时间为小时数值
    across(ends_with(c("_start", "_end")), time_to_hour),
    # 处理跨天的结束时间(加24)
    Event2_end = ifelse(Event2_end < Event2_start, Event2_end + 24, Event2_end),
    Event3_end = ifelse(Event3_end < Event3_start, Event3_end + 24, Event3_end),
    # 计算每个事件在6-30小时范围内的时长
    Event1_duration = pmax(0, pmin(Event1_end, 30) - pmax(Event1_start, 6)),
    Event2_duration = pmax(0, pmin(Event2_end, 30) - pmax(Event2_start, 6)),
    Event3_duration = pmax(0, pmin(Event3_end, 30) - pmax(Event3_start, 6))
  ) %>%
  # 保留需要的列并转为长格式
  select(Date, Event1_duration, Event2_duration, Event3_duration) %>%
  pivot_longer(cols = -Date, names_to = "Event", values_to = "Duration") %>%
  mutate(Event = str_remove(Event, "_duration"))

2. 绘制堆叠条形图

使用geom_col(适合已知数值的条形图),设置Y轴范围为6到30,将刻度标签转换为时间格式(30对应次日6:00):

ggplot(processed_data, aes(x = Date, y = Duration, fill = Event)) +
  geom_col(width = 0.95) +
  # 设置Y轴:范围6-30,刻度对应时间
  scale_y_continuous(
    limits = c(6, 30),
    breaks = c(6, 12, 18, 24, 30),
    labels = c("6:00", "12:00", "18:00", "24:00", "次日6:00")
  ) +
  # 设置填充颜色
  scale_fill_manual(
    values = c("#c7e6ff", "#f5eea6", "#ffcccc"),
    labels = c("Event1", "Event2", "Event3")
  ) +
  # 调整主题和标签
  labs(
    x = "日期",
    y = "时间",
    fill = "事件"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

关键说明

  • 原代码的问题:直接用字符串格式的时间作为Y轴数值,ggplot无法识别;gather的方式没有正确计算事件时长,而是把起止时间都作为了条形的高度。
  • 跨天处理:将次日的时间数值加24,统一到6-30的范围内,方便Y轴展示。
  • 有效时长计算:只统计每个事件落在当日6:00到次日6:00之间的部分,避免超出范围的时长被计入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:55:05