如何在R中判断时间编码数据是否落入指定时间区间
问题根因
你的三次代码写法都存在逻辑漏洞:
- 第一版代码内层for循环只要判断完第一个区间,无论结果如何都会直接return,永远不会遍历后续区间,因此只能匹配到第一个区间的符合条件的数据
- 第二版用ifelse但没有写明确的return语句,自定义函数无返回值,所以得到的结果都是NULL
- 第三版的
any()位置使用错误:any(data_split_target[[m]][["tmin"]])<=x是只要所有tmin里存在一个值小于等于x就为真,any(x<= data_split_target[[m]][["tmax"]])是只要所有tmax里存在一个值大于等于x就为真,相当于只要x大于最小tmin、小于最大tmax就会返回in,完全不校验是否落在同一个区间内,自然会出现大量误判
修复方案1:调整原有循环逻辑
仅需要修改内层判断逻辑,遍历所有区间,只要找到任意一个满足条件的区间就标记为in,所有区间都不满足才标记为overlap:
# 按受试者+录音号拆分两个数据框 data1_split <- split(data1, paste(data1$Participant, data1$RecordingNumber, sep = "_")) data2_split <- split(data2, paste(data2$Participant, data2$RecordingNumber, sep = "_")) # 遍历两个数据框共有的分组 for (grp in intersect(names(data1_split), names(data2_split))) { cur_data1 <- data1_split[[grp]] cur_intervals <- data2_split[[grp]] # 逐个判断时间点是否落在任意有效区间内 cur_data1$target <- sapply(cur_data1$time, function(x) { if (any(cur_intervals$tmin <= x & x <= cur_intervals$tmax)) { return("in") } else { return("overlap") } }) data1_split[[grp]] <- cur_data1 } # 把拆分后的结果合并为完整数据框 data1_final <- do.call(rbind, data1_split)
修复方案2:高效非等值连接写法(推荐)
使用data.table包的非等值连接可以直接完成匹配,不需要写嵌套循环,数据量越大性能优势越明显:
library(data.table) # 将数据框转为data.table格式 setDT(data1) setDT(data2) # 按受试者、录音号分组,匹配时间点是否落在有效区间内 data1_final <- data2[data1, on = .(Participant, RecordingNumber, tmin <= time, tmax >= time), .(Participant, RecordingNumber, time, target = fifelse(!is.na(tmin), "in", "overlap"))]
内容的提问来源于stack exchange,提问作者paulinemaes
相关产品推荐
相关产品推荐

