【发布时间】: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