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

如何在ggplot中设置Y轴时间范围为19:00至07:00并修正平滑线

问题:调整ggplot Y轴时间范围(19:00-次日07:00)并生成合理平滑线

之前我提问过ggplot中Y轴使用小时格式的问题,现在需要将Y轴时间范围设置为19:00至次日07:00,且从19:00开始显示——所有distress变量的时间都落在这个区间内。当前图表Y轴是00:00:00到23:59:00,生成的平滑线处于下午时段,完全不符合逻辑。以下是我使用的代码和两位参与者的示例数据,求问如何设置指定Y轴时间范围并得到符合逻辑的平滑线?

原代码

#Convert to hours format (do it after removing missings because it makes issues with missing values)
data_clean$distress_time <- as_hms(paste0(data_clean$distress, ':00'))

#Create plot:
lines<-ggplot(data = data_clean, aes(x=survey,y=distress_time, group=id, color=id))+
  facet_wrap(~PP_rec)+
  geom_line()+
  xlab("Survey")+ylab("Distress")+
  theme_bw()
lines

#a smoother for the overall group
lines_smooth <- lines + geom_smooth(aes(group = 1), se=FALSE, colour="black", size=1)
lines_smooth

#adjust plot:
smooth_lines2 <- lines_smooth + 
  labs(x = "Survey", y = "Distress", color = "id") +
  scale_y_time(limits = as.hms(c('00:00:00', '23:59:00')), breaks = hms(hours = seq(0, 23.99, 1))) +
  scale_x_continuous(breaks = seq(0, 16, 2)) +
  theme(text = element_text(size = 10))
smooth_lines2

示例数据

structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L), levels = c("400", "401", "402", "403", "404", "405", "406", "407", "408", "409", "411", "412", "413", "414", "415", "550", "551", "552", "553", "554", "555", "558", "559", "560", "561", "563", "565", "566", 
"567", "568", "569", "570", "571", "572", "573", "574", "575", 
"576", "577", "578", "580", "590", "591"), class = "factor"), 
distress = c("23:45", "23:30", "23:30", "23:45", "23:30", 
    "22:30", "23:30", "21:30", "23:45", "22:45", "0:00", "1:00", 
    "6:15", "0:00", "1:00", "0:00", "2:00", "2:00", "2:00", "1:45"
    ), survey = c(1, 4, 6, 9, 11, 1, 3, 5, 8, 11, 1, 4, 7, 9, 
    12, 1, 4, 7, 10, 12)))

注:PP_rec用于区分事件发生的前后时段


解决方案

核心问题是hms类型的时间是线性的0-23小时区间,直接设置19:00到07:00的范围会因为07<19导致ggplot无法识别跨天的连续区间,进而导致平滑线计算逻辑错误。我们可以将时间转换为以19:00为起点的偏移小时数,把跨天区间转换成连续的0-12小时数值轴,再自定义轴标签还原时间格式。

步骤1:数据预处理

library(tidyverse)
library(hms)

# 加载示例数据并补充PP_rec列(原数据缺失,用于测试)
data_clean <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L), levels = c("400", "401", "402", "403", "404", "405", "406", "407", "408", "409", "411", "412", "413", "414", "415", "550", "551", "552", "553", "554", "555", "558", "559", "560", "561", "563", "565", "566", 
"567", "568", "569", "570", "571", "572", "573", "574", "575", 
"576", "577", "578", "580", "590", "591"), class = "factor"), 
distress = c("23:45", "23:30", "23:30", "23:45", "23:30", 
    "22:30", "23:30", "21:30", "23:45", "22:45", "0:00", "1:00", 
    "6:15", "0:00", "1:00", "0:00", "2:00", "2:00", "2:00", "1:45"
    ), survey = c(1, 4, 6, 9, 11, 1, 3, 5, 8, 11, 1, 4, 7, 9, 
    12, 1, 4, 7, 10, 12)), row.names = c(NA, -20L), class = "data.frame")

data_clean$PP_rec <- sample(c("事件前", "事件后"), nrow(data_clean), replace = TRUE)

# 转换时间为19:00起的偏移小时数
data_clean <- data_clean %>%
  mutate(
    distress_hms = as_hms(paste0(distress, ":00")),
    # 计算与19:00的时间差,负数则加24小时(对应次日时间)
    distress_offset = as.numeric(difftime(distress_hms, as_hms("19:00:00"), units = "hours")),
    distress_offset = ifelse(distress_offset < 0, distress_offset + 24, distress_offset)
  )

步骤2:绘制图表并自定义Y轴

# 定义Y轴刻度和对应时间标签
y_breaks <- seq(0, 12, 1)
y_labels <- c(
  "19:00", "20:00", "21:00", "22:00", "23:00", 
  "00:00", "01:00", "02:00", "03:00", "04:00", 
  "05:00", "06:00", "07:00"
)

# 生成最终图表
smooth_lines_final <- ggplot(data = data_clean, aes(x = survey, y = distress_offset, group = id, color = id)) +
  facet_wrap(~PP_rec) +
  geom_line() +
  geom_smooth(aes(group = 1), se = FALSE, colour = "black", size = 1) +
  labs(x = "Survey", y = "Distress", color = "id") +
  scale_y_continuous(
    limits = c(0, 12),
    breaks = y_breaks,
    labels = y_labels
  ) +
  scale_x_continuous(breaks = seq(0, 16, 2)) +
  theme_bw() +
  theme(text = element_text(size = 10))

smooth_lines_final

效果说明

  • 转换后的distress_offset是连续数值:19:00对应0,23:00对应4,00:00对应5,07:00对应12,完美适配跨天区间的逻辑顺序。
  • 平滑线基于连续的数值轴计算,结果符合数据的时间分布逻辑。
  • Y轴标签手动替换为对应时间,视觉效果和直接使用时间轴一致。

内容的提问来源于stack exchange,提问作者o.y_80

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:29:59