【问题标题】:Merge two tables exact and fuzzy合并两个表精确和模糊
【发布时间】:2018-05-04 07:05:45
【问题描述】:

我有两个表,我想根据一个变量的完全匹配和另一个变量的模糊匹配来合并它们。

考虑下面的两个表格。对于 dt1 中的每个 id1,我想在 dt2 中找到一个与大小完全匹配的 id2,并且 dt2 中的日期值等于或晚于 dt1 中的日期字段。如果有多个匹配项,我希望随机选择一个。

dt1 <- data.table(c("A", "B"), c(2, 3), as.Date(c("2013-03-27", "2014-05-08"), format = '%Y-%m-%d'))
setnames(dt1, c("V1", "V2", "V3"),
c("id1", "size", "date"))

dt2 <- data.table(1:10, c(2, 4, 3, 2, 2, 2, 3, 2, 4, 4), as.Date(c("2014-02-25", "2011-08-02", "2014-06-21", "2013-11-29", "2012-02-21", "2011-12-02",
"2014-04-22", "2011-03-05", "2014-04-21", "2014-10-29"), format = '%Y-%m-%d'))
setnames(dt2, c("V1", "V2", "V3"),
c("id2", "size", "date"))

生成的表格可能如下所示:

   id1 size       date  id2
1:   A    2 2013-03-27    1
2:   B    3 2014-05-08    3

或像这样(取决于随机选择)

   id1 size       date  id2
1:   A    2 2013-03-27    4
2:   B    3 2014-05-08    3    

【问题讨论】:

    标签: r merge data.table fuzzy-logic exact-match


    【解决方案1】:

    要按大小连接并选择适当的日期条目,我们可以使用非等连接:

    > # Rename the date columns to make the join step clear:
    > setnames(dt1, "date", "date1")
    > setnames(dt2, "date", "date2")
    
    > # Non equi-join will give all entries in dt2 matching on size where
    > # date2 >= date1:
    > dt2[dt1, on=.(size, date2 >= date1)]
       id2 size      date2 id1
    1:   4    2 2013-03-27   A
    2:   1    2 2013-03-27   A
    3:   3    3 2014-05-08   B
    

    我找不到一种可靠的方法来结合连接执行随机选择步骤。作为一个 hacky 解决方案,我们可以在上面的表格中添加一个包含混洗行号的新列,然后根据 id1 选择混洗行号最大的行:

    > joined <- dt2[dt1, on=.(size, date2 >= date1)]
    > joined[, selection_column := sample(.I, .N)] 
    > filtered <- joined[,.SD[which.max(selection_column)], by=id1]
    > filtered[, selection_column := NULL]
    > filtered
       id1 id2 size      date2
    1:   A   1    2 2013-03-27
    2:   B   3    3 2014-05-08
    

    或者,我们可以使用dplyr 来做随机选择步骤:

    > library(dplyr)
    > dt2[dt1, on=.(size, date2 >= date1)] %>% 
    +   group_by(id1) %>% 
    +   sample_n(1) %>% 
    +   as.data.table()  
       id2 size      date2 id1
    1:   4    2 2013-03-27   A
    2:   3    3 2014-05-08   B
    

    【讨论】:

    • dt2[dt1, on=.(size, date &gt;= date), .(id1, id2 = sample(id2,1)), by=.EACHI] 呢?
    • 如果您不想保留大小和日期列,这可行,但我看不到使用该方法保留多个列的方法。
    • @ScottRitchie 我没有在 thelatemail 的答案中看到任何“缺失”的列。此外,如果您想在之后进行随机选择,这很简单 - 一种方法是:dt2[dt1, on=.(size, date &gt;= date)][, .SD[sample(.N, 1)], by = id1]。另请注意,您不需要重命名列。
    • @eddi 看起来你是对的。我不知道为什么我昨天无法让这些方法发挥作用。
    【解决方案2】:

    我不确定大多数人在说“模糊匹配”时通常会想到什么——你想组合两个表,然后对匹配的结果做一些随机的事情,例如:

    library(data.table)
    library(tidyverse)
    
    set.seed(1234)
    dt1 <- data.table(c("A", "B"), c(2, 3), as.Date(c("2013-03-27", "2014-05-08"), format = '%Y-%m-%d'))
    setnames(dt1, c("V1", "V2", "V3"),
             c("id1", "size", "date"))
    
    dt2 <- data.table(1:10, c(2, 4, 3, 2, 2, 2, 3, 2, 4, 4), as.Date(c("2014-02-25", "2011-08-02", "2014-06-21", "2013-11-29", "2012-02-21", "2011-12-02",
                                                                       "2014-04-22", "2011-03-05", "2014-04-21", "2014-10-29"), format = '%Y-%m-%d'))
    setnames(dt2, c("V1", "V2", "V3"),
             c("id2", "size", "date"))
    
    dt <- full_join(dt1, dt2, by = "size") %>% 
      filter(date.y >= date.x) %>% 
      group_by(size) %>%
      sample_n(size = 1)
    

    【讨论】:

      猜你喜欢
      • 2018-06-09
      • 1970-01-01
      • 2021-01-26
      • 2017-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      相关资源
      最近更新 更多