rstringrfuzzyjoin

Join tables with inexact match in R. Only match if a whole word matches


I have a problem that can be reproduced in the following way:

library(tidyverse)
a <- tibble(navn=c("Oslo kommune", "Oslo kommune", "Kommunen i Os", "Kommunen i Eidsberg", "Eid fylkeskommune"), person=c("a", "c", "b", "a", "b"))
b <- tibble(knavn=c("Oslo", "Eid", "Eidsberg", "Os"), tall=c(1,2,3,4))

library(fuzzyjoin)
library(stringr)

c <- a %>%
  fuzzy_left_join(b, by=c("navn"="knavn"), match_fun=str_detect)

I want "Oslo kommune" to match with "Oslo" not with "Os", and "Kommunen i Eidsberg" to match with "Eidsberg" not "Eid". I want the function to look only for whole words in variable navn in a that matches with the word in the variable knavn in b. So that c becomes:

tibble(navn=c("Oslo kommune", "Oslo kommune", "Kommunen i Os", "Kommunen i Eidsberg", "Eid fylkeskommune"), person=c("a", "c", "b", "a", "b"), knavn=c("Oslo","Oslo", "Os", "Eidsberg", "Eid"),tall=c(1,1,4,3,2))

How could I do that?


Solution

  • You can add \\b to capture words:

    a %>%
      fuzzy_left_join(b, by = c("navn" = "knavn"), 
                      match_fun = \(x, y) str_detect(x, paste0("\\b", y, "\\b")))
    
    # A tibble: 5 × 4
      navn                person knavn     tall
      <chr>               <chr>  <chr>    <dbl>
    1 Oslo kommune        a      Oslo         1
    2 Oslo kommune        c      Oslo         1
    3 Kommunen i Os       b      Os           4
    4 Kommunen i Eidsberg a      Eidsberg     3
    5 Eid fylkeskommune   b      Eid          2
    

    If you're working in the tidyverse, glue("\\b{y}\\b") might be better.