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?
CodePudding user response:
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.
CodePudding user response:
A base R alternative using grepl
join_word_match <- function(a, b, first_col, second_col)
data.frame(do.call(rbind, apply(b, 1, function(x){
res <- grepl(paste0("\\b", x[second_col], "\\b"), unlist(a[, first_col]))
do.call(cbind, c(a[res,], x))})))
join_word_match(a, b, "navn", "knavn")
navn person knavn tall
1 Oslo kommune a Oslo 1
2 Oslo kommune c Oslo 1
3 Eid fylkeskommune b Eid 2
4 Kommunen i Eidsberg a Eidsberg 3
5 Kommunen i Os b Os 4