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

如何在ggplot中重新排序并过滤夜间时段的时间格式数据?

问题

我拥有每晚21:00:00至次日5:59:59的录音数据,需制作以时间为x轴的柱状图。当前用ggplot生成的图表x轴按00:00:00至23:59:59排序,中间存在06:00:00-20:59:59的空白区域。需求是仅展示有数据的时段,将x轴调整为从21:00:00到06:00:00的夜间顺序。注:数据中的date字段为转换为dttm格式时的虚拟日期,实际录制时间跨数月的每晚。

数据样例:

> head(songs)
  Selection Begin.Time..s. End.Time..s.                       file       date
1         1      0.0959375    0.4159375  Baldy-20240823_030000.WAV 2024-08-23
2         1      0.4799375    1.1199375  Baldy-20240825_030000.WAV 2024-08-25
3         2      1.1839375    1.5999375  Baldy-20240823_030000.WAV 2024-08-23
4         1      1.7599375    2.3359375 Quarry-20240905_030000.WAV 2024-09-05
5         3      2.1439375    2.8479375  Baldy-20240823_030000.WAV 2024-08-23
6         2      2.7199375    3.3919375  Baldy-20240825_030000.WAV 2024-08-25
  Occupancy review overlap   songs clock                time
1       0.5      t               t 21:00 2025-04-17 21:00:00
2      0.45      t               t 21:00 2025-04-17 21:00:00
3    0.7692      t               t 21:00 2025-04-17 21:00:00
4       0.5        overlap overlap 21:00 2025-04-17 21:00:00
5    0.6818        overlap overlap 21:00 2025-04-17 21:00:00
6    0.7619        overlap overlap 21:00 2025-04-17 21:00:00
> tail(songs)
       Selection Begin.Time..s. End.Time..s.                       file
205490       432       32394.59     32395.01 Quarry-20240907_030000.WAV
205491       671       32395.23     32395.78  Baldy-20240902_030000.WAV
205492       672       32396.42     32396.96  Baldy-20240902_030000.WAV
205493       673       32397.70     32398.27  Baldy-20240902_030000.WAV
205494       433       32397.73     32398.11 Quarry-20240907_030000.WAV
205495       674       32399.17     32399.62  Baldy-20240902_030000.WAV
             date Occupancy review overlap songs clock                time
205490 2024-09-07    0.5385      t             t 05:59 2025-04-17 05:59:00
205491 2024-09-02    0.8235      t             t 05:59 2025-04-17 05:59:00
205492 2024-09-02    0.8824      t             t 05:59 2025-04-17 05:59:00
205493 2024-09-02    0.7778      t             t 05:59 2025-04-17 05:59:00
205494 2024-09-07    0.5833      t             t 05:59 2025-04-17 05:59:00
205495 2024-09-02    0.9286      t             t 05:59 2025-04-17 05:59:00

当前使用代码:

library(ggplot2)

ostf1 = ggplot(songs,aes(x=time,fill=songs)) + geom_bar() + theme_classic() +
  labs(x="Time", y="Count") + 
  theme(legend.title = element_blank()) + 
  scale_fill_hue(labels = c("Overlapping", "Single")) +  
  scale_y_continuous(breaks=seq(0,10000,by=100), expand = c(0,0)) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) +
  scale_x_datetime(date_breaks = "1 hours", date_labels = "%H:%M", expand = c(0,0))

生成的图表x轴按自然时间排序,中间存在大空白,如何调整以实现需求?

解决方案

核心思路是让x轴按照自定义的夜间时间顺序排列,避免展示无数据的时段,提供两种可行方案:

方案1:使用有序因子(推荐,简单直接)

利用数据中已有的clock字段,将其转换为有序因子,指定排序为21:00到次日06:00的顺序,ggplot会自动按该顺序渲染x轴,不会出现空白。

  1. 生成自定义排序的时间标签列表
# 按夜间顺序生成时间标签(21:00到次日05:00)
time_order <- c(paste0(21:23, ":00"), paste0(0:5, ":00"))
  1. 将clock字段转换为有序因子
    如果clock包含非整点时间(如05:59),先统一为整点格式再转换:
# 统一clock为小时级格式(如05:59转为05:00)
songs$clock_hour <- format(strptime(songs$clock, "%H:%M"), "%H:00")
# 转换为有序因子,指定排序
songs$clock_ordered <- factor(songs$clock_hour, levels = time_order, ordered = TRUE)
  1. 修改ggplot代码
    替换x轴为有序因子,调整x轴刻度设置:
library(ggplot2)

ostf1 = ggplot(songs,aes(x=clock_ordered, fill=songs)) + 
  geom_bar() + 
  theme_classic() +
  labs(x="Time", y="Count") + 
  theme(legend.title = element_blank()) + 
  scale_fill_hue(labels = c("Overlapping", "Single")) +  
  scale_y_continuous(breaks=seq(0,10000,by=100), expand = c(0,0)) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) +
  scale_x_discrete(expand = c(0,0)) # 移除x轴两端空白

方案2:调整datetime数值(保留连续时间类型)

如果需要保留x轴的连续时间属性,可将次日00:00-05:59的时间加上24小时,让其数值大于21:00-23:00,再修改x轴标签为原时间格式:

  1. 加载lubridate包处理时间(若未安装先运行install.packages("lubridate"))
library(lubridate)
# 调整时间:次日时间加24小时
songs$time_adjusted <- ifelse(hour(songs$time) < 6, songs$time + hours(24), songs$time)
  1. 修改ggplot代码
    使用调整后的时间字段,自定义x轴标签:
library(ggplot2)

ostf1 = ggplot(songs,aes(x=time_adjusted, fill=songs)) + 
  geom_bar() + 
  theme_classic() +
  labs(x="Time", y="Count") + 
  theme(legend.title = element_blank()) + 
  scale_fill_hue(labels = c("Overlapping", "Single")) +  
  scale_y_continuous(breaks=seq(0,10000,by=100), expand = c(0,0)) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) +
  scale_x_datetime(
    breaks = seq(min(songs$time_adjusted), max(songs$time_adjusted), by = "1 hour"),
    labels = function(x) format(x, "%H:%M"), # 显示原时间格式
    expand = c(0,0)
  )

两种方案都能实现需求,方案1操作更简单,适合按小时分组的场景;方案2保留了时间的连续性,适合需要更精细时间刻度的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:42:32