如何根据 `dbplyr` 上的日期左连接数据框

How to left join on a dataframe based on dates on `dbplyr`

我正在尝试根据条件加入两个 data.frame。考虑以下情况,我有 df_adf_b.

library(tidyverse)

# Dummy data A
df_a <- tibble(
   id = c("a", "b", "c", "a"),
   text = c("hi","why", "bye","cry"),
   created_date = c(as.Date("2020-01-01"), as.Date("2020-02-02"), as.Date("2020-03-01"), as.Date("2020-04-04"))
)

# Dummy data B
df_b <- tibble(
  id = c("a", "b", "c", "a"),
  group = c("GROUP A","GROUP B","GROUP C", "GROUP C"),
  start_date = c(as.Date("2020-01-01"), as.Date("2020-01-01"), as.Date("2020-01-01"), as.Date("2020-02-04"))
)

> df_a
# A tibble: 4 x 3
  id    text  created_date
  <chr> <chr> <date>      
1 a     hi    2020-01-01  
2 b     why   2020-02-02  
3 c     bye   2020-03-01  
4 a     cry   2020-04-04

> df_b
# A tibble: 4 x 3
  id    group  start_date
  <chr> <chr>  <date>    
1 a     GROUP A 2020-01-01
2 b     GROUP B 2020-01-01
3 c     GROUP C 2020-01-01
4 a     GROUP C 2020-02-04

# Current solution
d_current_sol <- df_a %>% 
  left_join(
    df_b %>% 
      distinct(id, .keep_all = T), by = "id"
    )

> d_current_sol
# A tibble: 4 x 5
  id    text  created_date group  start_date
  <chr> <chr> <date>       <chr>  <date>    
1 a     hi    2020-01-01   GROUP A 2020-01-01
2 b     why   2020-02-02   GROUP B 2020-01-01
3 c     bye   2020-03-01   GROUP C 2020-01-01
4 a     cry   2020-04-04   GROUP A 2020-01-01

# Desired solution
> d_desired
# A tibble: 4 x 5
  id    text  created_date start_date group  
  <chr> <chr> <date>       <date>     <chr>  
1 a     hi    2020-01-01   2020-01-01 GROUP A
2 b     why   2020-02-02   2020-01-01 GROUP B
3 c     bye   2020-03-01   2020-01-01 GROUP C
4 a     cry   2020-04-04   2020-02-04 GROUP C

如您在 df_b 中所见,id = a 的开始日期首先是 2020-01-01,然后是 2020-02-04

我想要的是 df_a2020-02-04 之后的任何行,它的关联组是 "GROUP C"。这在最终数据框中得到了说明 d_desired

但是,对于我们将行与单个行项匹配的传统 left_join,我们只会获得最早的条目 (d_current_sol)。使用 map() 和使用 mutate() 的自定义函数很容易做到,但是,SQL 在翻译 dplyr 查询时不支持。

有谁知道通过 tidyverse 范式来做到这一点的方法吗?因为我将在 PostgreSQL 数据库上使用 dbplyr 到 运行。

这个?

df_a %>% 
  left_join(df_b, by = "id"  ) %>% 
  filter( created_date >= start_date) %>% 
  group_by(id, created_date) %>% 
  top_n(1,start_date)
# A tibble: 4 x 5
# Groups:   id, created_date [4]
  id    text  created_date group   start_date
  <chr> <chr> <date>       <chr>   <date>    
1 a     hi    2020-01-01   GROUP A 2020-01-01
2 b     why   2020-02-02   GROUP B 2020-01-01
3 c     bye   2020-03-01   GROUP C 2020-01-01
4 a     cry   2020-04-04   GROUP C 2020-02-04