【问题标题】:How do I determine whether time-coded data falls into time range?如何确定时间编码数据是否属于时间范围?
【发布时间】:2021-11-20 08:00:21
【问题描述】:

我一直在尝试编写一个 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")
        }
      }
      ))}}
}

但是,此函数为我的新“目标列”的每一行返回 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”列,但是即使时间点没有落入其中之一,该函数也会错误地返回“in”行值间隔。

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

【问题讨论】:

  • 您可以添加minimal reproducible example。使用dputdata.frame 命令?添加 MRE 和所需输出的示例(以代码形式,而不是表格和图片)使其他人更容易找到和测试您的问题的答案。这样你就可以帮助别人帮助你!
  • 这能回答你的问题吗? Join tables by date range
  • 谢谢达里奥!我已经在参与者 1 Recording 1 上尝试了 sqldf 包 ``` result = sqldf("select * from data1 left join data2 on data1.time between data2.tmin and data2.tmax") ``` 效果很好!现在我想知道我是否可以在这个函数中添加一个分组变量?感谢您提供这些其他建议,这是我第一次在这里提问!
  • 找到解决方案达里奥!非常感谢您引导我进入 sqldf() 方向!
  • 不客气! ;) 另外,我认为你 should/could accept your own answer (你只在 48 小时之后)这样你的问题对其他搜索同样问题的人有用..

标签: r for-loop if-statement time


【解决方案1】:

使用 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 是标识参与者和记录编号的分组变量。

【讨论】:

    【解决方案2】:

    这是使用 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]))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 2017-01-11
      • 1970-01-01
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 2012-08-25
      相关资源
      最近更新 更多