Точное нечеткое левое соединение частичное совпадение строк

#r #string #left-join #fuzzyjoin

#r #строка #левое соединение #нечеткое соединение

Вопрос:

Я использую функцию fuzzy_left_join для сопоставления таблиц с точным нечетким соответствием.

Один из аргументов match_fun, который я использую, включает проверку, содержится ли часть строки внутри другой строки. При использовании только точного сопоставления он возвращает значения, но при добавлении функции ниже соединение возвращает только значения NA.

Функция для сравнения строк:

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

Идея состоит в том, что в первой таблице X столбец с именем «Имена» имеет значения строк типа «a / b / c», а в столбце «Имена» из второй таблицы Y значения также похожи на «a / d / e», следовательно, часть строки «a» содержитсятакже и для второго значения, и должно вернуться значение TRUE (и, таким образом, разрешить объединение).

При использовании простого соединения без пользовательской функции оно работает и находит некоторые значения:

 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   
  

Не могли бы вы высказать несколько мыслей?

Ответ №1:

Функция, применяемая в 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     
  

Комментарии:

1. Отлично! Кажется, работает. Будет ли это также работать нормально, если в обеих таблицах разное количество строк?