我有一个带有ID列和lubridate时间间隔列的数据帧df1,我想过滤(子样本)一个数据帧df2,它有ID和DateTime列,这样只有df2行,其中DateTime符合df1中相应的ID间隔。保持。我想在一个整齐的框架中这样做。 可以使用连接轻松完成(参见下面的示例),但我想知道是否会有更直接的解决方案(可能是基于purrr的),以避免连接然后从第二个数据帧中删除时间间隔数据。谢谢。
这里发布的问题Merge two dataframes if timestamp of x is within time interval of y与此处提出的问题很接近,但提议的解决方案与我开发的解决方案类似,而不是在整齐的框架中。
显示问题的最小代码和我当前的解决方案:
library(tibble)
library(lubridate)
df1 <- tribble(
~ID, ~Date1, ~Date2,
"ID1", "2018-04-16", "2018-06-14",
"ID2", "2018-04-20", "2018-06-25")
df1 <- mutate(df1,Interval = interval(ymd(Date1),ymd(Date2)))
df2 <- tribble(
~ID, ~DateTime,
"ID1", "2018-04-12",
"ID1", "2018-05-05",
"ID2", "2018-04-23",
"ID2", "2018-07-12")
df2 <- mutate(df2,DateTime=ymd(DateTime))
df1看起来像这样
> df1
# A tibble: 2 x 4
ID Date1 Date2 Interval
<chr> <chr> <chr> <S4: Interval>
1 ID1 2018-04-16 2018-06-14 2018-04-16 UTC--2018-06-14 UTC
2 ID2 2018-04-20 2018-06-25 2018-04-20 UTC--2018-06-25 UTC
和df2像这样:
> df2
# A tibble: 4 x 2
ID DateTime
<chr> <date>
1 ID1 2018-04-12
2 ID1 2018-05-05
3 ID2 2018-04-23
4 ID2 2018-07-12
在df2中,ID1的第二条记录不在df1的ID1区间内。 ID2的第二条记录也不在df1的ID2区间内。
我目前基于连接和删除连接列的解决方案如下:
df_out <- df2 %>%
left_join(.,df1,by="ID") %>%
filter(.,DateTime %within% Interval) %>%
select(.,-Interval)
> df_out
# A tibble: 2 x 4
ID DateTime Date1 Date2
<chr> <date> <chr> <chr>
1 ID1 2018-05-05 2018-04-16 2018-06-14
2 ID2 2018-04-23 2018-04-20 2018-06-25
我感觉有一个整齐的替代方案,可以避免连接,然后删除Interval列应该存在。
有一个名为fuzzyjoin
的包可以根据间隔做一个semi_join
。半连接意味着它根据与“正确”数据帧的匹配来过滤“左”数据帧。尝试:
library(fuzzyjoin)
df2 %>%
fuzzy_semi_join(df1,
by=c("DateTime"="Date1", "DateTime"="Date2"),
match_fun=list(`>=`, `<=`))
结果如下:
# A tibble: 2 x 2
ID DateTime
<chr> <date>
1 ID1 2018-05-05
2 ID2 2018-04-23