基于24小时时间框架为R数据集分配Bin分组的方法求助
解决R语言中基于事件起止时间的Bin分组问题
我来帮你搞定这个分组需求!先明确下咱们的规则:
- 事件起止都在同一个自然日 → 归到该日对应的Bin
- 事件跨天(结束时间在次日及以后)→ 归到结束日期对应的Bin
- Bin编号从最早的日期开始,按先后顺序排1、2、…n
下面是一步步的实现方法:
1. 先把时间列转成可操作的日期时间类型
你当前的startTime和endTime是字符型,R没法直接识别日期,所以第一步要转成POSIXct类型:
test$startTime <- as.POSIXct(test$startTime) test$endTime <- as.POSIXct(test$endTime)
2. 确定每个事件对应的分组日期
根据规则,我们要判断事件是否跨天:
- 起止日期相同 → 用开始日期当分组日期
- 起止日期不同 → 用结束日期当分组日期
用as.Date()提取日期部分,再用ifelse()做判断:
test$group_date <- ifelse(as.Date(test$startTime) == as.Date(test$endTime), as.Date(test$startTime), as.Date(test$endTime))
3. 把分组日期转成连续的Bin编号
现在要把不同的日期映射成从1开始的编号,用factor()配合as.integer()就能轻松实现,而且会自动按日期顺序排序:
test$Bin <- as.integer(factor(test$group_date, levels = unique(sort(test$group_date))))
完整代码&验证
把所有步骤整合起来,运行后就能得到你想要的结果:
# 原始数据 test <- data.frame("Event" = c("A", "B", "C","D","E"), "startTime" = c("2017-08-01 00:37:27", "2017-08-01 00:44:32", "2017-08-01 23:30:00","2017-08-01 23:55:47", "2017-08-02 01:00:00" ), "endTime" = c("2017-08-01 20:13:13", "2017-08-01 21:30:45", "2017-08-02 09:00:00","2017-08-01 23:56:47", "2017-08-02 04:18:38"), "Bin" = c(1,1,2,1,2)) # 转换时间类型 test$startTime <- as.POSIXct(test$startTime) test$endTime <- as.POSIXct(test$endTime) # 确定分组日期 test$group_date <- ifelse(as.Date(test$startTime) == as.Date(test$endTime), as.Date(test$startTime), as.Date(test$endTime)) # 生成Bin编号 test$Bin <- as.integer(factor(test$group_date, levels = unique(sort(test$group_date)))) # 查看结果 print(test)
运行后输出的Bin列和你预期的完全一致:
Event startTime endTime Bin group_date 1 A 2017-08-01 00:37:27 2017-08-01 20:13:13 1 2017-08-01 2 B 2017-08-01 00:44:32 2017-08-01 21:30:45 1 2017-08-01 3 C 2017-08-01 23:30:00 2017-08-02 09:00:00 2 2017-08-02 4 D 2017-08-01 23:55:47 2017-08-01 23:56:47 1 2017-08-01 5 E 2017-08-02 01:00:00 2017-08-02 04:18:38 2 2017-08-02
进阶:用dplyr简化代码
如果你习惯用dplyr的链式操作,代码会更简洁,处理大数据集也更顺手:
library(dplyr) test <- test %>% mutate(across(c(startTime, endTime), as.POSIXct), group_date = if_else(as.Date(startTime) == as.Date(endTime), as.Date(startTime), as.Date(endTime)), Bin = as.integer(factor(group_date, levels = unique(sort(group_date)))))
内容的提问来源于stack exchange,提问作者TuD
相关产品推荐
相关产品推荐

