Fuzzy Left Join 精确+部分字符串匹配

Fuzzy Left Join exact + partial string match

我正在使用 fuzzy_left_join 函数通过精确 + 模糊匹配来匹配 table。

我使用的 match_fun 参数之一涉及检查字符串的一部分是否包含在另一个字符串中。当仅使用精确匹配时,它 returns 值,但当添加下面的函数时,连接仅 returns NA 值。

比较字符串的函数:

detect <- function(x, y){ 
  any(unlist(strsplit(x, split = "/")) %in% unlist(strsplit(y, split = "/")))
    }

想法是,在第一个 table X 上,名为“Names”的列的行值类似于“a/b/c”,在列“来自第二个 table Y 的名称”,值也类似于“a/d/e”,因此字符串的“a”部分也包含在第二个值中, TRUE 应该 return(从而允许加入)。

当使用简单连接时,没有自定义函数,它可以工作并找到一些值:

x <- tribble(~X1, ~X2, ~Names,
        #--|--|----
        "5000", "a", "a/b/c",
        "6000", "b", "d/e/f",
        "7000", "c", "g/h/i")

y <- tribble(~Y1, ~Y2, ~Names,
        #--|--|----
        "5000", "a", "a/j/k",
        "6000", "b", "l/m/n",
        "8000", "d", "o/p/q")

fuzzyjoin::fuzzy_left_join(x, y, by = c("X1" = "Y1", "X2" = "Y2"),
                           match_fun = list(`==`, `==`))

# Produces:

#> A tibble: 3 x 6
#>   X1    X2    Names.x           Y1    Y2    Names.y      
#>  <chr> <chr> <chr>             <chr> <chr> <chr>        
#> 1 5000  a     a/b/c             5000  a     a/j/k
#> 2 6000  b     d/e/f             6000  b     l/m/n  
#> 3 7000  c     g/h/i             NA    NA    NA           

但是添加自定义函数时:

fuzzyjoin::fuzzy_left_join(x, y, by = c("X1" = "Y1", "X2" = "Y2", "Names" = "Names"),
                           match_fun = list(`==`, `==`, detect))

# Produces:

#> A tibble: 3 x 6
#> X1    X2    Names.x             Y1    Y2    Names.y
#> <chr> <chr> <chr>             <chr> <chr> <chr>  
#> 1 5000  a     a/b/c             NA    NA    NA     
#> 2 6000  b     d/e/f             NA    NA    NA     
#> 3 7000  c     g/h/i             NA    NA    NA     


# Intended:

#> A tibble: 3 x 6
#> X1    X2    Names.x             Y1    Y2    Names.y
#> <chr> <chr> <chr>              <chr> <chr> <chr>  
#> 1 5000  a     a/b/c             5000  a     a/j/k
#> 2 6000  b     d/e/f             NA    NA    NA     
#> 3 7000  c     g/h/i             NA    NA    NA   

你能给点意见吗?

match_fun 中应用的函数不适用于一次组合。它将函数应用于所有组合,因此您需要更改 detect 函数:

detect <- function(x, y){ 
  mapply(function(x, y) any(x == y), strsplit(x, '/'), strsplit(y, '/'))
}

然后尝试:

fuzzyjoin::fuzzy_left_join(x, y, by = c("X1" = "Y1", "X2" = "Y2", "Names"),
                           match_fun = list(`==`, `==`, detect))

#  X1    X2    Names.x Y1    Y2    Names.y
#  <chr> <chr> <chr>   <chr> <chr> <chr>  
#1 5000  a     a/b/c   5000  a     a/j/k  
#2 6000  b     d/e/f   NA    NA    NA     
#3 7000  c     g/h/i   NA    NA    NA