如何在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]
错误原因分析
- Date类型直接做数值减法错误:Date类型本质是从1970-01-01开始的天数计数,你用
Date-7.5*60*6(即2700)会直接减去2700天,导致日期跳到2015年,完全偏离需求。 - 仅调整时间未提取日期分组:
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
相关产品推荐
相关产品推荐

