如何用R的lubridate包从大数据集单列提取起止日期?
用data.table实现按ID提取起止日期的两种结果
嘿,我明白你要做什么了——针对每个唯一ID提取对应的起始和结束日期,还要两种输出格式对吧?用data.table来处理这个简直是拿手好戏,毕竟它处理分组操作效率超高,尤其适合你这种几万行的大数据集。咱们一步步来:
第一步:先处理日期格式
首先得把你的BST列从字符型转换成日期时间(或日期)类型,这样才能正确计算最小/最大值:
library(data.table) # 你的示例数据 myID <- c(1,1,1,1,1,1,2,2,2,2,2,2) BST <- c("2017-06-01 00:00:01", "2017-06-01 00:00:02", "2017-06-02 00:00:01", "2017-06-02 00:00:02", "2017-06-03 00:00:01", "2017-06-03 00:00:02", "2017-06-01 00:00:01", "2017-06-01 00:00:02", "2017-06-03 00:00:01", "2017-06-03 00:00:02", "2017-06-05 00:00:01", "2017-06-05 00:00:02") V3 <- c("a", "a", "a", "a", "a", "a", "b", "b", "b","b", "b", "b") dt1 <- data.table(myID, BST, V3) # 转换BST为日期时间类型(如果只需要日期部分,也可以用as.Date) dt1[, BST := as.POSIXct(BST)]
结果1:每个ID一行的汇总表
用data.table的分组操作,按myID分组后,提取每组的最小(起始)和最大(结束)日期,同时保留V3的唯一值(假设每个ID的V3是一致的):
summary_dt <- dt1[, .( StartDate = min(BST), EndDate = max(BST), V3 = first(V3) # 取每组第一个V3值,因为每个ID的V3相同 ), by = myID] # 如果需要只保留日期部分(去掉时间),可以转成Date类型 summary_dt[, c("StartDate", "EndDate") := .(as.Date(StartDate), as.Date(EndDate))]
执行后你会得到每个ID一行的汇总,和你期望的第一种结果完全匹配。
结果2:保留所有原行并添加起止日期列
用data.table的:=操作符原地添加新列,按myID分组后,给每一行分配该组的起始和结束日期:
dt1[, `:=`( StartDate = min(BST), EndDate = max(BST) ), by = myID] # 同样如果需要只保留日期部分: dt1[, c("StartDate", "EndDate") := .(as.Date(StartDate), as.Date(EndDate))]
这样处理后,原表的每一行都会带上对应ID的起止日期,和你想要的第二种结果一致,而且:=是原地修改,效率极高,适合处理大型数据集。
补充说明
- 如果你用的是
data.frame而不是data.table,其实逻辑类似,用dplyr的话就是group_by(myID) %>% summarise()(对应结果1)和group_by(myID) %>% mutate()(对应结果2),但data.table在处理超大数据时速度会更快。 - 确保你的日期格式正确,如果
as.POSIXct转换失败,可以指定format参数,比如as.POSIXct(BST, format = "%Y-%m-%d %H:%M:%S")。
内容的提问来源于stack exchange,提问作者mikeLdub
相关产品推荐
相关产品推荐

