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

如何在R的data.table中按7:30至次日7:29区间统计行数?

在R的data.table中按自定义24小时区间统计行数

需求与背景

需要按每日07:30:00至次日07:29:59的24小时区间,统计data.table的行数。
已知基础统计方法:

  • 若date为Date类型,DT[, .N, by=date]可按自然日(00:00-23:59)统计行数;
  • 若DateTime为POSIXct类型,DT[, .N, by=format(DateTime, "%F")]也可实现自然日统计。

用户尝试了将DateTime减去7.5小时(7.56060秒)的思路,但结果不符合预期,希望确认该思路是否可行并获取正确解法。

用户已尝试的代码及问题

library(dplyr)
library(data.table)
DT<-tibble(DateTime=c("2023-01-01 00:41:00", "2023-01-01 01:54:00", "2023-01-01 02:10:00", "2023-01-02 05:01:00", "2023-01-02 08:38:00", "2023-01-02 09:25:00", "2023-01-02 09:29:00", "2023-01-02 09:30:00", "2023-01-02 09:56:00"),
           Date=c("01.01.2023", "01.01.2023", "01.01.2023", "02.01.2023", "02.01.2023", "02.01.2023", "02.01.2023", "02.01.2023", "02.01.2023"),
           Time=c("00:41", "01:54", "02:10", "05:01", "08:38", "09:25", "09:29", "09:30", "09:56"))
setDT(DT)
DT[, ':='(DateTime=as.POSIXct(DateTime, "%F %T"),
          Date=as.Date(Date, "%d.%m.%Y"))]
# 自然日统计结果
DT[, .N, by=Date]
# 错误尝试:Date类型直接减数值,得到错误日期
DT[, .N, by=Date-7.5*60*6]
# 按原始DateTime分组,每个行单独一组
DT[, .N, by=DateTime]
# 仅调整时间但未按日期分组,结果还是每个行一组
DT[, .N, by=DateTime-7.5*60*60]

错误原因分析

  1. Date类型直接做数值减法错误:Date类型本质是从1970-01-01开始的天数计数,你用Date-7.5*60*6(即2700)会直接减去2700天,导致日期跳到2015年,完全偏离需求。
  2. 仅调整时间未提取日期分组:by=DateTime-7.5*60*60会保留完整的时间戳,每个调整后的时间戳仍唯一,因此每个组行数为1。

正确解法

你的核心思路(调整时间对齐自定义区间)是可行的,关键是调整时间后提取日期部分作为分组依据,以下是两种实现方式:

方法1:纯data.table实现(无需额外包)

将DateTime减去7.5小时(即7.5*3600秒),再用as.Date()提取调整后的日期作为分组键:

DT[, .N, by = .(custom_date = as.Date(DateTime - 7.5*3600))]

测试数据输出结果:

custom_date N
1:  2022-12-31 3
2:  2023-01-01 1
3:  2023-01-02 5

解释:

  • 2023-01-01 00:41:00减去7.5小时后为2022-12-31 17:11:00,属于2022-12-31对应的区间(2022-12-31 07:30:00至2023-01-01 07:29:59),3条数据归为一组;
  • 2023-01-02 05:01:00减去7.5小时后为2023-01-01 21:31:00,属于2023-01-01对应的区间;
  • 剩余5条数据(08:38及之后)调整后日期为2023-01-02,对应区间2023-01-02 07:30至2023-01-03 07:29。

方法2:结合lubridate包的floor_date函数

若习惯用lubridate的时间处理函数,可直接用floor_date()按自定义区间截断:

library(lubridate)
# 输出区间起始时间
DT[, .N, by = .(custom_interval = floor_date(DateTime, "day", offset = hours(7.5)))]
# 转成Date类型简化结果
DT[, .N, by = .(custom_date = as.Date(floor_date(DateTime, "day", offset = hours(7.5))))]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 02:38:08