vie*_*tti 8 string r matrix stringdist
我发现了优秀的包"stringdist",现在想用它来计算字符串距离.特别是我有一组单词,我想打印近似匹配,其中"近匹配"是通过一些算法,如Levenshtein距离.
我在shell脚本中的工作代码非常慢,我能够在stringdist中加载并生成带有指标的矩阵.现在我想将该矩阵归结为只有近似匹配的较小矩阵,例如,度量值非零但小于某个阈值.
kp <- c('leaflet','leafletr','lego','levenshtein-distance','logo')
kpm <- stringdistmatrix(kp,useNames="strings",method="lv")
> kpm
leaflet leafletr lego levenshtein-distance
leafletr 1
lego 5 6
levenshtein-distance 16 16 18
logo 6 7 1 19
m = as.matrix(kpm)
close = apply(m, 1, function(x) x>0 & x<5)
> close
leaflet leafletr lego levenshtein-distance logo
leaflet FALSE TRUE FALSE FALSE FALSE
leafletr TRUE FALSE FALSE FALSE FALSE
lego FALSE FALSE FALSE FALSE TRUE
levenshtein-distance FALSE FALSE FALSE FALSE FALSE
logo FALSE FALSE TRUE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)
好的,现在我有一个(大)dist,如何将它减少回一个输出类似的列表
leafletr,leaflet,1
logo,lego,1
Run Code Online (Sandbox Code Playgroud)
仅适用于度量标准为非零且小于n = 5的情况?我发现"apply()"让我做了测试,现在我需要弄清楚如何使用它.
问题不是stringdist和stringdistmatrix特有的,并且是非常基本的R,但我仍然被卡住了.我怀疑答案涉及subset(),但我不知道如何将"dist"转换为其他东西.
设置您的数据:
library('stringdist')
library('dplyr')
kp <- c('leaflet','leafletr','lego','levenshtein-distance','logo')
kpm <- stringdistmatrix(kp,useNames="strings",method="lv")
Run Code Online (Sandbox Code Playgroud)
在这里我们可以更改kpm为数据框:
kpm <- data.frame(as.matrix(kpm))
Run Code Online (Sandbox Code Playgroud)
这是一种获得带有“ 1”的数据框来标记单词足够接近的位置的方法:
idx <- apply(kpm, 2, function(x) x >0 & x<5)
idx <- apply(idx, 1:2, function(x) if(isTRUE(x)) x<-1 else x<-NA)
#> idx
# leaflet leafletr lego levenshtein.distance logo
# leaflet NA 1 NA NA NA
# leafletr 1 NA NA NA NA
# lego NA NA NA NA 1
# levenshtein-distance NA NA NA NA NA
# logo NA NA 1 NA NA
Run Code Online (Sandbox Code Playgroud)
为了使事情变得简单,请熔化数据框,对其进行过滤,并删除最后一列:
final <- melt(idx) %>%
filter(value==1) %>%
select(Var1, Var2)
Run Code Online (Sandbox Code Playgroud)
别忘了将所有内容转换回角色,而不是因素!(有时就像R中的一个破记录...)
final[] <- lapply(final, as.character)
#> final
# Var1 Var2
# leafletr leaflet
# leaflet leafletr
# logo lego
# lego logo
Run Code Online (Sandbox Code Playgroud)
现在我们摆脱了重复项:
final <- final[!duplicated(data.frame(list(do.call(pmin,final),do.call(pmax,final)))),]
Run Code Online (Sandbox Code Playgroud)
加上一些好名声,您就可以走了。
names(final) <- c('string 1', 'string 2')
#> final
# string 1 string 2
# leafletr leaflet
# logo lego
Run Code Online (Sandbox Code Playgroud)
(尽管您请求了一个列表,但这是一个数据框。从这里可以很容易地根据需要将其转换为所需的任何内容,例如,写入csv等)。
你可以这样做:
library(reshape2)
d <- unique(melt(m))
out <- subset(d, value > 0 & value < 5)
Run Code Online (Sandbox Code Playgroud)
在这里,melt使m成长的形式(2列与字符串名称和与该值的一个列)。但是,由于我们已经融化了对称矩阵,因此我们将其unique用于重复数据删除。
另一种方法是使用dplyr(因为所有酷孩子dplyr现在都在使用管道):
library(dlpyr)
library(reshape2)
library(magrittr)
out <- melt(m) %>% distinct() %>% filter(value > 0 & value < 5)
Run Code Online (Sandbox Code Playgroud)
第二个选项可能更快,但我还没有真正计时。