【发布时间】: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 的每个拆分元素的第一个区间,但不继续其他区间。
我尝试过的解决方案:
- 使用 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。
- 将 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。使用
dput或data.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