【问题标题】:non-equi join in dplyrdplyr 中的非 equi 加入
【发布时间】:2021-03-12 21:12:28
【问题描述】:

我在代码中经常使用 dplyr,并且经常必须在日期上完成非 equi left join。我想使用整洁的语法和管道来做到这一点。我看到了一个名为fuzzyjoin 的包,它完成了这个任务,但是我正在使用的客户端在他们的服务器上没有这个包。他们有一套标准的软件包,安装新软件包很困难。现在,我已经编写了这个函数,non_equi_left_join,它可以帮助我完成我想要完成的任务:

    library(data.table)
    library(dplyr)
    library(lubridate)
      
    # lst_conditions: conditions for the left join
    non_equi_left_join <- function(df_lhs, df_rhs, lst_conditions) {
      sel_columns_lhs <- unique(unlist(map(lst_conditions, 1)))
      sel_columns_rhs <- unique(unlist(map(lst_conditions, 3)))
      
      setDT(df_lhs)[, paste0(sel_columns_lhs, "_tempJoin") := mget(sel_columns_lhs)]
      setDT(df_rhs)[, paste0(sel_columns_rhs, "_tempJoin") := mget(sel_columns_rhs)]
      
      onkey <- unlist(paste(
        paste0(map(lst_conditions, 3), "_tempJoin"),
        map(lst_conditions, 2),
        paste0(map(lst_conditions, 1), "_tempJoin")
        ))
      
      df_ret <-
        df_rhs[df_lhs, on = onkey]
      
      df_ret[, grep(".*_tempJoin$", colnames(df_ret)):=NULL]
      return(setDF(df_ret) %>% as_tibble())
      
    }

_tempJoin 部分是为了摆脱这篇文章中列出的行为:fuzzyjoin two data frames using data.table

我创建了加入中涉及的所有列的副本,并在加入后立即删除它们。该函数帮助我编写以下代码:

    df1 <- data.frame(
      ID = c(1L,2L,3L,3L),
      CallDate  = c(ymd("2021-01-20"), ymd("2021-02-20"), ymd("2021-02-04"), ymd("2021-04-02"))
    ) %>% as_tibble()
    
    df2 <- data.frame(
      ID = c(1L,2L,3L,3L),
      CustomerType = c("basic", "basic", "basic", "premium"),
      StartDate = c(ymd("2021-02-02"), ymd("2021-02-02"), ymd("2021-02-02"), ymd("2021-02-05")),
      EndDate   = c(ymd("2099-01-01"), ymd("2099-01-01"), ymd("2021-02-05"), ymd("2099-01-01"))
    ) %>% as_tibble()
    
    
    lst_condition <- 
      list(c("ID", "==", "ID"),
           c("CallDate", "<=", "StartDate"),
           c("CallDate", ">=", "EndDate") )
    
    df1 %>%
      non_equi_left_join(., df2, lst_condition)

我知道它很粗糙,但在我测试它的示例上运行良好。我担心它可能会默默地给我不正确的结果。这里需要专家意见。我使用的数据通常是几百 MB 的数据帧。

谢谢。

【问题讨论】:

  • 您可能需要包含许可证并且应该感谢创建者,但是由于fuzzyjoin 是开源的,您不能只复制并粘贴您需要的功能的源代码到您的“自定义”代码?一种安装新软件包的穷人方式。

标签: r dplyr data.table


【解决方案1】:

为什么不自始至终使用 data.table?我认为以下内容将为您提供所需的内容:

df1 <- data.table(df1)
df2 <- data.table(df2)

df2[df1, on = .(ID == ID, StartDate <= CallDate, EndDate >= CallDate), 
              .(x.ID, x.CustomerType, x.StartDate, x.EndDate, i.ID, CallDate)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2017-05-29
    • 1970-01-01
    • 2020-09-30
    相关资源
    最近更新 更多