【问题标题】:Replace string with most frequent fuzzy match用最频繁的模糊匹配替换字符串
【发布时间】:2020-02-05 18:25:34
【问题描述】:

我有一个非结构化名称的数据框,我想在一列中创建一个已清理名称的“主”列表,而另一列中的所有变体。我正在使用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),因为字符串“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        |

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

谢谢大家!

【问题讨论】:

  • 只是为了指出未来,如果您将其扩展到很长的单词列表,此代码将非常低效。如果有很多重复,它将冗余计算相同单词对的距离分数。更有效的解决方案是计算unique(words) 上的成对距离,并分别将每个单词的计数制成表格,然后将两者结合起来。

标签: r stringdist


【解决方案1】:

dplyr 管道语句将返回一个包含 9 行的数据框,其中一个用于原始 words 向量中的每个唯一元素。首先我们group_byraw 列为每个唯一单词创建一个组,然后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  

【讨论】:

    猜你喜欢
    • 2020-03-13
    • 2012-02-14
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 2021-04-19
    • 1970-01-01
    相关资源
    最近更新 更多