【问题标题】:Left join using R/dplyr with join based on calculation使用 R/dplyr 与基于计算的连接进行左连接
【发布时间】:2019-07-29 05:48:57
【问题描述】:

我正在尝试使用 dplyr 连接 R 中的两个表,方式如下:

表 1:

ID    CHAR1    CHAR2
01      xyz      abc
02      abc      xyz

等等……

表 2:

ID    YEAR    VALUE1    STATUS
01    2012      455          T
01    2013       14          B
01    2014      234          C
01    2015       17          T
02    2014      213          B
02    2015      456          B
02    2016       17          B

我有一个名为 MODEL_YEAR 的单独变量,在本例中设置为 2015。

我希望我的新表如下所示:

ID  CHAR1  CHAR2  VALUE_Tminus1 VALUE_Tminus2 STATUS_Tminus1 STATUS_Tminus2
01    xyz    abc            234            14              C              B
02    abc    xyz            213            NA              B             NA

新列会从 MODEL_YEAR 回溯。例如,VALUE_Tminus1 取 2014 年的 VALUE1。我希望新表可以追溯到 10 年前,在没有可用数据的情况下出现 NA。

到目前为止,我已尝试将 MODEL_YEAR 作为列添加到表 1 中,然后将表 1 左连接到表 2,如下所示:

left_join(Table_1, Table_2, by=c("ID"="ID", "MODEL_YEAR"=("YEAR"-1))

但这不起作用,因为我不能以这种方式从“YEAR”中减去 1。我想我可以通过添加大量新列并进行多次连接来做到这一点,但我不确定并想知道是否有更简洁的方法?也许使用 data.table - 我知道这可以用于连接,但我不熟悉它。

非常感谢

【问题讨论】:

    标签: r dplyr data.table left-join


    【解决方案1】:

    既然有标签,这里有一个data.table的解决方案:

    包

    library(data.table)
    library(magrittr) # For readability only
    

    您的数据的可重现示例

    MODEL_YEAR <- 2015L
    tab1 <- fread(
      'ID    CHAR1    CHAR2
      01      xyz      abc
      02      abc      xyz',
      colClasses = 'character'
    )
    tab2 <- fread(
      'ID    YEAR    VALUE1    STATUS
      01    2012      455          T
      01    2013       14          B
      01    2014      234          C
      01    2015       17          T
      02    2014      213          B
      02    2015      456          B
      02    2016       17          B',
      colClasses = c('character', 'integer', 'integer', 'character')
    )
    

    解决办法:

    setkey(tab1, ID)
    setkey(tab2, ID, YEAR)
    tab2[CJ(ID, YEAR = seq(MODEL_YEAR - 1, MODEL_YEAR - 5), unique = TRUE)] %>% 
      .[, YEAR := paste0('Tminus', MODEL_YEAR - YEAR)] %>%
      dcast(ID ~ YEAR, value.var = c('VALUE1', 'STATUS')) %>% 
      tab1[.]
    
    #    ID CHAR1 CHAR2 VALUE1_Tminus1 VALUE1_Tminus2 VALUE1_Tminus3 VALUE1_Tminus4 VALUE1_Tminus5 STATUS_Tminus1 STATUS_Tminus2 STATUS_Tminus3 STATUS_Tminus4 STATUS_Tminus5
    # 1: 01   xyz   abc            234             14            455             NA             NA              C              B              T           <NA>           <NA>
    # 2: 02   abc   xyz            213             NA             NA             NA             NA              B           <NA>           <NA>           <NA>           <NA>
    

    要获得更多延迟,只需将数字 5 更改为您想要的任何值。

    【讨论】:

    • 非常感谢 - 这太棒了,我以前从未遇到过 CJ 功能。我遇到的一个小问题:我忘了提到 tab1 包含 tab2 中不存在的 ID,这些 ID 正在使用上面的代码删除。有没有办法保留它们,将 NA 分配给这些行的新列?
    • CJ 在基础 R 中有一个表亲,称为expand.grid。如果我正确理解了您的问题,我认为您可以将最后一个参数更改为 .[tab1] 或者您是否还有 tab2 中不存在于 tab1 中的东西然后 merge() 和 all = TRUE 可能只是改变最后一个论点。
    猜你喜欢
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多