在R语言中如何为时间戳数据框匹配时间范围对应值
这是个很典型的每日时间范围匹配问题,尤其要注意处理跨天的时间段(比如15:10到次日02:29这种),我来给你一步步解决:
第一步:明确数据与问题核心
先确认你的两个数据框(贴出代码方便直接运行):
# 时间戳数据框 tdata_df <- data.frame(timestamp=seq(c(ISOdate(2018,4,20)), by = (60*229), length.out = 6)) # 时间范围数据框 time_range_df <- data.frame(start=c("08:30","11:35","15:10","05:00"), end=c("11:29","15:09","02:29","08:29"), value=c(1,2,3,4))
问题核心是:每个时间戳需要匹配每日循环重复的时间范围对应的value,其中部分范围跨天,不能用常规时间比较逻辑直接处理。
第二步:预处理时间数据
我们把所有时间转换成「当日从0点开始的分钟数」,这样能大幅简化范围判断逻辑:
library(dplyr) library(lubridate) # 简化时间处理操作 # 处理时间范围数据框:将start/end转为当日分钟数 time_range_df <- time_range_df %>% mutate( start_min = hour(hms(start)) * 60 + minute(hms(start)), end_min = hour(hms(end)) * 60 + minute(hms(end)) ) # 处理时间戳数据框:提取每个时间戳的当日分钟数 tdata_df <- tdata_df %>% mutate( time_min = hour(timestamp) * 60 + minute(timestamp) )
第三步:编写匹配逻辑函数
写一个函数判断单个时间分钟数属于哪个时间范围:
- 对于不跨天的范围(
start_min <= end_min):只要时间分钟数在start_min和end_min之间即可匹配 - 对于跨天的范围(
start_min > end_min):时间分钟数大于等于start_min(当日后半段),或者小于等于end_min(次日凌晨),都算匹配
get_matched_value <- function(target_min, range_df) { for (i in 1:nrow(range_df)) { s <- range_df$start_min[i] e <- range_df$end_min[i] if (s <= e) { if (target_min >= s && target_min <= e) { return(range_df$value[i]) } } else { if (target_min >= s || target_min <= e) { return(range_df$value[i]) } } } # 没有匹配到任何范围时返回NA,你可以改成自己需要的默认值 return(NA) }
第四步:应用函数得到结果
把函数应用到每个时间戳的分钟数上,得到对应的value:
tdata_df <- tdata_df %>% mutate(value = sapply(time_min, get_matched_value, range_df = time_range_df))
最终结果如下:
timestamp time_min value 1 2018-04-20 21:00:00 1260 3 2 2018-04-21 00:49:00 49 3 3 2018-04-21 04:38:00 278 NA 4 2018-04-21 08:27:00 507 4 5 2018-04-21 12:16:00 736 2 6 2018-04-21 16:05:00 965 3
注:第三行的NA是因为04:38不在你给出的任何时间范围内(你的范围覆盖了05:00-08:29、08:30-11:29、11:35-15:09、15:10-次日02:29,但02:29-05:00是空白区间),如果需要处理这个空白区间,可以在time_range_df里添加对应的范围。
内容的提问来源于stack exchange,提问作者zaja9031
相关产品推荐
相关产品推荐

