我有一个数据集,其中包含事件的开始和结束时间(称为df_time),另一个数据集具有事件发生的时间(df_val)。我想使用df_time仅将df_val过滤为记录的时间间隔内发生的事件。
尽管如此,我还是迷失了。
start = c(1, 5, 7, 4)
end = c(2, 7, 11, 7)
df_time = data.frame(start, end)
time = c(3, 6, 2, 10, 11)
val = c(100, 20, 30, 40, 50)
df_val = data.frame(time, val)
df_val %>% select_all() %>%
filter(time >= df_time$start & time <= df_time$end)
输出:
time val
1 6 20
Warning messages:
1: In time >= df_time$start :
longer object length is not a multiple of shorter object length
2: In time <= df_time$end :
longer object length is not a multiple of shorter object length
上面的命令将带有警告消息(如上),并给我错误的输出(忽略等于值时间戳的开始/结束)。在上面,应该打印除3以外的所有值。
我不确定如何解决此问题,将不胜感激!
答案 0 :(得分:1)
这是您要实现的目标吗?
library(tidyverse)
start = c(1, 5, 7, 4)
end = c(2, 7, 11, 7)
df_time = data.frame(start, end)
time = c(3, 6, 2, 10, 11)
val = c(100, 20, 30, 40, 50)
df_val = data.frame(time, val)
# return one row for each start/end pair that time falls between
map2_dfr(start, end, ~filter(df_val, time >= .x, time <= .y) %>% mutate(start = .x, end = .y))
#> time val start end
#> 1 2 30 1 2
#> 2 6 20 5 7
#> 3 10 40 7 11
#> 4 11 50 7 11
#> 5 6 20 4 7
#return unique pairs
map2_dfr(start, end, ~filter(df_val, time >= .x, time <= .y)) %>% unique()
#> time val
#> 1 2 30
#> 2 6 20
#> 3 10 40
#> 4 11 50
#simpler method, probably
df_val %>% filter(map_lgl(time, ~any((.x >= start) & .x <= end)))
#> time val
#> 1 6 20
#> 2 2 30
#> 3 10 40
#> 4 11 50
由reprex package(v0.2.1)于2019-07-25创建
编辑:添加了一些替代方法
答案 1 :(得分:0)
这是使用data.table
使用非等价内部联接的另一种选择:
library(data.table)
setDT(df_time)
setDT(df_val)
df_time[df_val, on=.(ID, start<time, end>time), nomatch=0L,
c(mget(paste0("x.", names(df_time))), mget(paste0("i.", names(df_val))))]
输出:
x.ID x.start x.end i.ID i.time i.val
1: 1 5 7 1 6 20
2: 1 4 7 1 6 20
3: 1 7 11 1 10 40