用最频繁的模糊匹配替换字符串

Replace string with most frequent fuzzy match

我有一个非结构化名称的数据框,我想在一列中创建一个 'master' 已清理名称列表,在另一列中创建所有变体。我正在使用 stringdist 包。下面是一个小例子:

library(dplyr) # for pipes 
library(tidyr) # for expand_grid()
library(stringdist) 

words <- c("dog","dot","don","con","cry","croak","cat","dogg", "dogy", "dog", "cat", "dog")
# compare everything to everything 
words_df <- expand_grid(raw = words, clean = words) %>%
    mutate(dist = stringdist(raw, clean, method = "jw") %>% 
    # compute word frequency 
    group_by(clean) %>%
    mutate(count = n()) %>%
filter(dist < 0.3) 

这会产生一个 df,其中包含所有足够相似的组合的距离和字数:

|raw |clean |      dist| count|
|:---|:-----|---------:|-----:|
|dog |dog   | 0.0000000|    36|
|dog |dot   | 0.2222222|    12|
|dog |don   | 0.2222222|    12|
|dog |dogg  | 0.0833333|    12|
|dog |dogy  | 0.0833333|    12|
|dog |dog   | 0.0000000|    36|
|dog |dog   | 0.0000000|    36|
|dot |dog   | 0.2222222|    36|
|dot |dot   | 0.0000000|    12|
|dot |don   | 0.2222222|    12|

您可以看到,在 clean 列中,我有两个条目 "dog" 和 "dogg",我想将它们合并为一个条目(狗),因为字符串 "dog"出现的频率更高。

这是我目前尝试过的方法:

dict <- words_df %>%
    mutate(clean_new = ifelse(dist < 0.085, words_df[which.max(words_df$count)][[1]][1], clean))    

这导致:

|raw |clean |      dist| count|clean_new |
|:---|:-----|---------:|-----:|:---------|
|dog |dog   | 0.0000000|    36|NA        |
|dog |dot   | 0.2222222|    12|dot       |
|dog |don   | 0.2222222|    12|don       |
|dog |con   | 0.4444444|    12|con       |
|dog |cry   | 1.0000000|    12|cry       |
|dog |croak | 0.4888889|    12|croak     |
|dog |cat   | 1.0000000|    24|cat       |
|dog |dogg  | 0.0833333|    12|NA        |
|dog |dogy  | 0.0833333|    12|NA        |
|dog |dog   | 0.0000000|    36|NA        |

本质上,我想要创建的是一个包含所有单词变体的字典,基于最接近的单词匹配的频率。

谢谢大家!

dplyr 管道语句将 return 一个包含 9 行的数据框,每行对应原始 words 向量中的每个唯一元素。首先我们 group_by raw 列为每个唯一的词创建一个组,然后 filter 通过你的距离阈值,然后在 clean 中找到频率最高的对应词原始数据集。在您的示例中,除了 "dog."

的两个变体之外,所有单词都与自己匹配

代码

words_df %>%
  group_by(raw) %>%
  filter(dist < 0.085) %>%
  summarize(clean = clean[which.max(count)])

输出

# A tibble: 9 x 2
  raw   clean
  <chr> <chr>
1 cat   cat  
2 con   con  
3 croak croak
4 cry   cry  
5 dog   dog  
6 dogg  dog  
7 dogy  dog  
8 don   don  
9 dot   dot