2016-11-25 2 views
4

J'ai besoin de calculer la similarité de Jaccard entre chaque mot de 2 vecteurs. Chaque mot par chaque mot. Et extraire le mot le plus similaire.Calculer la similarité de Jaccard entre chaque mot dans 2 vecteurs

Voici mon Slightly lent Code:

txt1 <- c('The quick brown fox jumps over the lazy dog') 
txt2 <- c('Te quick foks jump ovar lazzy dogg') 

words <- strsplit(as.character(txt1), " ") 
words.p <- strsplit(as.character(txt2), " ") 

r <- length(words[[1]]) 
c <- length(words.p[[1]]) 

m <- matrix(nrow=r, ncol=c) 
for (i in 1:r){ 
    for (j in 1:c){ 
    m[i,j] = stringdist(tolower(words.p[[1]][j]), tolower(words[[1]][i]), method='jaccard', q=2) 
    } 
} 

ind <- which(m == min(m))-nrow(m) 
words[[1]][ind] 

S'il vous plaît me aider à améliorer et embellir ce code pour une grande trame de données.

+0

Quelle est la taille « grand », et combien de temps faut-il utiliser votre code? – lukeA

+0

Essayez cette 'spply (mots.p, fonction (x) mapply (stringdist, mots, x, méthode = 'jaccard'))'. Cela vous donnera directement une matrice que vous pouvez facilement examiner. –

Répondre

3

Préparation (ajouté tolower ici):

txt1 <- c('The quick brown fox jumps over the lazy dog') 
txt2 <- c('Te quick foks jump ovar lazzy dogg') 

words <- unlist(strsplit(tolower(as.character(txt1)), " ")) 
words.p <- unlist(strsplit(tolower(as.character(txt2)), " ")) 

Obtenez des distances pour chaque mot:

dists <- sapply(words, Map, f=stringdist, list(words.p), method="jaccard") 

Pour chaque mot words trouver le mot le plus proche de words.p:

matches <- words.p[sapply(dists, which.min)] 

cbind(words, matches) 
       matches 
[1,] "the" "te" 
[2,] "quick" "quick" 
[3,] "brown" "ovar" 
[4,] "fox" "foks" 
[5,] "jumps" "jump" 
[6,] "over" "ovar" 
[7,] "the" "te" 
[8,] "lazy" "lazzy" 
[9,] "dog" "dogg" 

EDIT:

Pour obtenir la meilleure paire de mots correspondant vous devez d'abord sélectionner la distance minimale de chaque mot words à tous les mots words.p:

mindists <- sapply(dists, min) 

Cela obtenir vos meilleures distances possibles pour chaque mot. Ensuite, vous sélectionnez le mot de words avec la distance minimale:

words[which.min(mindists)] 

Ou en une ligne:

words[which.min(sapply(dists, min))] 
+0

Merci! Mais je veux obtenir seulement un meilleur mot, dans ce cas c'est "rapide". Comment l'extraire? – Dennix

+0

@Dennix a ajouté une ligne sur la façon de le faire dans la réponse (après EDIT) –

+0

@ KarolisKoncevičius, Merci pour votre solution. Je cherchais quelque chose de similaire mais pour la liste d'adresses correspondante. J'ai donc un jeu de données qui contient environ 70 000 adresses différentes et un autre jeu de données volumineux qui contient environ 4 enregistrements de manque (0,4 million). Je veux faire correspondre chaque adresse avec le grand ensemble de données en regardant les mots de l'adresse. Comment puis-je atteindre cet objectif? J'ai posté une question sur le lien, http://stackoverflow.com/questions/42486172/r-string-match-for-address-using-stringdist-stringdistmatrix S'il vous plaît aider !! – user1412