如何判断时间编码数据是否落入时间范围?

How do I determine whether time-coded data falls into time range?

我一直在尝试编写一个for循环以确定我的时间数据是否在特定时间范围内。我已经解决了所有关于堆栈溢出的相关问题,到目前为止,这是我得到的:

基本上,我有一个包含元音声学测量值的数据框。对于每个元音,我还有参与者说出元音的时间(以秒为单位)。

然后我有第二个数据框,包括时间间隔。这些间隔对应于参与者说话的时间段,并且没有重叠的噪音。因此,这些间隔从我的第一个数据帧中识别出可用于后续分析的元音,因为它们的声学测量没有被其他噪音污染

我需要在数据框 1 中创建一个新列(“目标”),用于指示每个参与者和每个记录的元音是否属于数据框 2 的间隔之一。

这些是数据框 1 中感兴趣的变量:

    Participant RecordingNumber    time
1        FSO110               1  37.258
2        FSO110               1  37.432
3        FSO110               1  37.496
4        FSO110               1  38.138
5        FSO110               1  38.499
6        FSO110               1  42.124
7        FSO110               1  61.733
8        FSO110               1  61.924
9        FSO110               1  61.980
10       FSO110               1  62.260
11       FSO110               1  62.610
12       FSO110               1  62.943
13       FSO110               1 194.929
14       FSO110               1 195.403
15       FSO110               1 401.114
16       FSO110               1 401.341

这些是数据框 2 中感兴趣的变量:

Participant RecordingNumber    tmin    tmax 
FSO110       1                 445.695 447.250   
FSO110       1                 448.444 449.093   
FSO110       1                 452.990 453.292   
FSO110       1                 481.177 481.709   
FSO110       2                 41.202  41.511   
FSO110       2                 42.176  43.132   
FSO110       2                 44.640  47.710   
FSO110       2                 53.819  56.253   
FSO110       2                 113.453 114.803   
FSO110       2                 123.135 123.374

到目前为止,我已经到达那里:

# split dataframes by Participant and Recording Number
data1 <- split(data1, paste0(data1$Participant, data1$RecordingNumber))
data2 <- split(data2, paste0(data2$Participant, data2$RecordingNumber))

# loop through each element of each splitted df 
for (n in seq_along(data1)){
  for (m in seq_along(data2)){
    if(n == m){
    data_split[[n]][["target"]] = as.character(lapply(data1[[n]][["time"]], FUN = function(x){
      for (i in 1:nrow(data2[[m]])){
          if(data2[[m]][["tmin"]]<=x & x<= data2[[m]][["tmax"]]){
            return(paste0("in"))}
        else{
          return(paste0("overlap"))}
          }
      }
    ))}
}

该功能似乎有效。但是,它仅适用于 i == 1(数据行 2)。因此,它正确地识别了数据 1 中的时间点,这些时间点落入数据 2 的每个拆分元素的第一个间隔,但不会继续其他间隔。

我尝试过的解决方案:

  1. 使用 ifelse 代替 if 语句
for (n in seq_along(data1)){
  for (m in seq_along(data2)){
    if (n == m){
      data1[[n]][["target"]] = as.character(lapply(data1[[n]][["time"]], FUN = function(x){
        for (i in 1:nrow(data2[[m]])){
          ifelse((data2[[m]][["tmin"]]<=x & x<= data2[[m]][["tmax"]]), "in", "overlap")
        }
      }
      ))}}
}

但是,对于我的新“目标列”的每一行,此函数 returns NULL。

  1. 将 any() 添加到我的 if 语句中:
for (n in seq_along(data_split)){
  for (m in seq_along(data_split_target)){
    if(n == m) {
    data_split[[n]][["target"]] = as.character(lapply(data_split[[n]][["time"]], FUN = function(x){
      for (i in 1:nrow(data_split_target[[m]])){
          if(any(data_split_target[[m]][["tmin"]])<=x & any(x<= data_split_target[[m]][["tmax"]])){
            return(paste0("in"))}
        else{
          return(paste0("overlap"))}
          }
      }
    ))}
}

同样,该函数似乎可以正常工作,因为它正确地创建了一个包含“in”和“overlap”行的新“target”列,但函数错误地returns“in”行值,即使时间点没有落入其中一个区间。

有人可以帮助我吗?非常感谢!

这是使用 split/Map 的基础 R 方法。
拆分数据集,然后 Map 将函数 f 应用于每个子 df。

meas_split <- split(measures, list(measures$Participant, measures$RecordingNumber))
int_split <- split(intervals, list(intervals$Participant, intervals$RecordingNumber))

nms <- intersect(names(meas_split), names(int_split))
i <- match(names(meas_split[nms]), names(int_split[nms]))
j <- match(names(int_split[nms]), names(meas_split[nms]))

f <- function(X, Y){
  yes <- sapply(X[["time"]], \(x){
    x > Y[["tmin"]] & x < Y[["tmax"]]
  })
  as.integer(colSums(yes) > 0)
}

measures$target <- unlist(Map(f, meas_split[i], int_split[j]))

使用 sqldf 包解决了它。

result_all = sqldf("select * from data1
                left join data2
                on data1.rec = data2.rec
                and data1.time between data2.tmin and data2.tmax")

其中 $rec 是标识参与者和记录编号的分组变量。