R语言:基于多组START-END时间区间生成分钟级时间序列
如何基于多行时间区间生成按1分钟递增的时间序列?
当然可以!用R里的日期时间处理工具包就能轻松实现这个需求,我给你一步步拆解操作:
第一步:加载所需工具包
我们需要用到lubridate(处理日期时间格式)、dplyr(数据清洗与操作)和tidyr(展开列表数据),如果没安装的话先装一下:
install.packages(c("lubridate", "dplyr", "tidyr")) library(lubridate) library(dplyr) library(tidyr)
第二步:预处理原始数据
你的原始数据里的START和END是字符类型,得先转成R能识别的日期时间格式(POSIXct),这里用lubridate的mdy_hm()函数,刚好匹配你“月/日/年 时:分”的格式:
# 你的原始数据 x <- data.frame(START = c("3/28/2018 9:30", "3/28/2018 9:40"), END = c("3/28/2018 9:35", "3/28/2018 9:42")) # 转换日期时间格式 x_clean <- x %>% mutate( START = mdy_hm(START), END = mdy_hm(END) )
第三步:生成每分钟时间序列并展开
用rowwise()让每一行单独处理,然后用seq()生成从START到END的每分钟序列,最后用unnest()把列表列展开成多行:
# 生成目标数据框 result <- x_clean %>% rowwise() %>% # 为每一行生成每分钟的时间序列,存为列表列 mutate(LOG_START_DT = list(seq(START, END, by = "1 min"))) %>% # 展开列表列 unnest(LOG_START_DT) %>% # 重命名列名匹配你的需求 rename(LOG_END_DT = END) %>% # 调整列顺序 select(LOG_START_DT, LOG_END_DT) # 可选:把日期时间转成你想要的字符串格式(去掉时区显示) result <- result %>% mutate( LOG_START_DT = format(LOG_START_DT, "%m/%d/%Y %H:%M"), LOG_END_DT = format(LOG_END_DT, "%m/%d/%Y %H:%M") ) # 查看结果 print(result)
运行后你会得到这样的结果:
LOG_START_DT LOG_END_DT <chr> <chr> 1 03/28/2018 09:30 03/28/2018 09:35 2 03/28/2018 09:31 03/28/2018 09:35 3 03/28/2018 09:32 03/28/2018 09:35 4 03/28/2018 09:33 03/28/2018 09:35 5 03/28/2018 09:34 03/28/2018 09:35 6 03/28/2018 09:35 03/28/2018 09:35 7 03/28/2018 09:40 03/28/2018 09:42 8 03/28/2018 09:41 03/28/2018 09:42 9 03/28/2018 09:42 03/28/2018 09:42
另一种高效方法(用purrr)
如果你的数据量很大,用purrr的map2()函数会更高效,不需要逐行处理:
library(purrr) result <- x_clean %>% mutate( # 为每对START/END生成时间序列 LOG_START_DT = map2(START, END, ~seq(.x, .y, by = "1 min")), # 把END重复对应次数,和序列匹配 LOG_END_DT = map2(START, END, ~rep(.y, length(seq(.x, .y, by = "1 min")))) ) %>% # 展开两个列表列 unnest(c(LOG_START_DT, LOG_END_DT)) %>% select(LOG_START_DT, LOG_END_DT)
这个方法和上面的结果完全一致,只是实现逻辑不同,适合大数据场景。
内容的提问来源于stack exchange,提问作者PVic
相关产品推荐
相关产品推荐

