如何在tidyverse框架中最有效地过滤数据帧中的另一个值?

问题描述 投票:0回答:1

我有一个带有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列应该存在。

r tidyverse purrr
1个回答
0
投票

有一个名为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
© www.soinside.com 2019 - 2024. All rights reserved.