Я выполняю большое количество сопоставлений строк с использованием меры расстояния Левенштейна, но поскольку мне нужно уметь учитывать пространственную смежность в скрытой структуре строки, я должен был создать свой собственный скрипт, включая функцию веса.Улучшение производительности сценария для (расстояния Левенштейна с весами) в R
Моя проблема в том, что мой сценарий очень неэффективен. Я должен выполнить приблизительно 600 000 сравнений, и для выполнения сценария потребуется несколько часов. Я за то, чтобы найти способ сделать мой скрипт более эффективным, но, будучи самоучкой, я не знаю, как решить эту проблему.
Вот функции:
zeros <- function(lengthA,lengthB){
m <- matrix(c(rep(0,lengthA*lengthB)),nrow=lengthA,ncol=lengthB)
return(m)
}
weight <- function(A,B,weights){
if (weights == TRUE){
# cost_weight defines the matrix structure of the AOI-placement
cost_weight <- matrix(c("a","b","c","d","e","f","g","h","i","j","k","l",
"m","n","o","p","q","r","s","t","u","v","w","x"),
nrow=6)
max_walk <- 8.00 # defined as the maximum posible distance between letters in
# the cost_weight matrix
indexA <- which(cost_weight==A, arr.ind=TRUE)
indexB <- which(cost_weight==B, arr.ind=TRUE)
walk <- abs(indexA[1]-indexB[1])+abs(indexA[2]-indexB[2])
w <- walk/max_walk
}
else {w <- 1}
return(w)
}
dist <- function(A, B, insertion, deletion, substitution, weights=TRUE){
D <- zeros(nchar(A)+1,nchar(B)+1)
As <- strsplit(A,"")[[1]]
Bs <- strsplit(B,"")[[1]]
# filling out the matrix
for (i in seq(to=nchar(A))){
D[i + 1,1] <- D[i,1] + deletion * weight(As[i],Bs[1], weights)
}
for (j in seq(to=nchar(B))){
D[1,j + 1] <- D[1,j] + insertion * weight(As[1],Bs[j], weights)
}
for (i in seq(to=nchar(A))){
for (j in seq(to=nchar(B))){
if (As[i] == Bs[j]){
D[i + 1,j + 1] <- D[i,j]
}
else{
D[i + 1,j + 1] <- min(D[i + 1,j] + insertion * weight(As[i],Bs[j], weights),
D[i,j + 1] + deletion * weight(As[i],Bs[j], weights),
D[i,j] + substitution * weight(As[i],Bs[j], weights))
}
}
}
return(D)
}
levenshtein <- function(A, B, insertion=1, deletion=1, substitution=1){
# Compute levenshtein distance between iterables A and B
if (nchar(A) == nchar(B) & A == B){
return(0)
}
if (nchar(B) > nchar(A)){
C <- A
A <- B
B <- A
#(A, B) <- (B, A)
}
if (nchar(A) == 0){
return (nchar(B))
}
else{
return (dist(A, B, insertion, deletion, substitution)[nchar(A),nchar(B)])
}
}
Сравнивая производительность моей меры Левенштейна к одному из пакета stringdist производительность 83 раз хуже.
library (stringdist)
library(rbenchmark)
A <-"abcdefghijklmnopqrstuvwx"
B <-"xwvutsrqponmlkjihgfedcba"
benchmark(levenshtein(A,B), stringdist(A,B,method="lv"),
columns=c("test", "replications", "elapsed", "relative"),
order="relative", replications=10)
test replications elapsed relative
2 stringdist(A, B, method = "lv") 10 0.01 1
1 levenshtein(A, B) 10 0.83 83
У кого-нибудь есть идея улучшить мой скрипт?
Эти два расстояния также не согласуются друг с другом: 'Левенштейна (А, В)' является 11,25 и 'stringdist (А, В, метод =«LV»)' равно 24. – shadow
Это потому что 'levenshtein()' помещает весы в буквы, основанные на матрице 'cost_weight', определенной под функцией' weight() '. –