2017-05-29 4 views
2

Je souhaite trouver des informations dans une colonne en fonction de l'autre colonne. J'ai donc quelques mots dans une colonne et des phrases complètes dans une autre. Je voudrais savoir s'il trouve les mots dans ces phrases. Mais parfois, les mots ne sont pas les mêmes, donc je ne peux pas utiliser la fonction SQL like. Ainsi, je pense que la correspondance floue + une sorte de « comme » la fonction serait utile que les données ressemble à ceci:Ligne de correspondance floue dans une colonne avec la même ligne dans la colonne suivante

Names     Sentences 
Airplanes Sarl   Airplanes-Sàrl is part of Airplanes-Group Sarl. 
Kidco Ltd.    100% ownership of Kidco.Ltd. is the mother company. 
Popsi Co.    Cola Inc. is 50% share of PopsiCo which is part of LaLo. 

Les données a environ 2000 lignes qui ont besoin d'une logique pour savoir si Airplanes Sarl est en effet dans la phrase ou non, et cela vaut également pour Kidco Ltd., qui est dans la phrase «Kidco.Ltd». Pour simplifier, je n'ai pas besoin de chercher toutes les phrases dans la colonne, il suffit de chercher le mot Kidco Ltd. et de le chercher dans la même ligne de la base de données.

je l'ai déjà essayé en Python avec: df.apply (Lambda: fuzz.ratio (s [ 'Noms'], [s 'Phrases']), axe = 1)

Mais je eu beaucoup d'erreurs unicode/ascii donc j'ai abandonné et je voudrais essayer dans R. Des suggestions sur la façon de faire à ce sujet dans R? J'ai vu des réponses sur Stackoverflow qui correspondraient à toutes les phrases de la colonne, ce qui est différent de ce que je veux. Aucune suggestion?

+0

pouvez-vous nous lier à la réponse ce flou correspondait à tout? –

+0

comme votre table est petite, vous pouvez essayer des distances levenshtein. disons d est la distance, n1 le nombre de caractères dans col1 et n2 le nombre de caractères dans col2. si le nom n'est pas du tout dans la phrase, la distance devrait être plus proche de n2, si elle est exactement là, la distance devrait être n2-n1. Ensuite, vous définissez un seuil, je pense que cela peut bien fonctionner. –

Répondre

2

Peut-être essayer tokenization + correspondance phonétique:

library(RecordLinkage) 
library(quanteda) 
df <- read.table(header=T, sep=";", text=" 
Names     ;Sentences 
Airplanes Sarl   ;Airplanes-Sàrl is part of Airplanes-Group Sarl. 
Kidco Ltd.    ;Airplanes-Sàrl is part of Airplanes-Group Sarl. 
Kidco Ltd.    ;100% ownership of Kidco.Ltd. is the mother company. 
Popsi Co.    ;Cola Inc. is 50% share of PopsiCo which is part of LaLo. 
Popsi Co.    ;Cola Inc. is 50% share of Popsi Co which is part of LaLo.") 
f <- soundex 
tokens <- tokenize(as.character(df$Sentences), ngrams = 1:2) # 2-grams to catch "Popsi Co" 
tokens <- lapply(tokens, f) 
mapply(is.element, soundex(df$Names), tokens) 
# A614 K324 K324 P122 P122 
# TRUE FALSE TRUE TRUE TRUE 
1

Voici une solution en utilisant la méthode que je suggère dans les commentaires, dans cet exemple, il fonctionne bien:

library("stringdist") 

df <- as.data.frame(matrix(c("Airplanes Sarl","Airplanes-Sàrl is part of Airplanes-Group Sarl.", 
          "Kidco Ltd.","100% ownership of Kidco.Ltd. is the mother company.", 
          "Popsi Co.","Cola Inc. is 50% share of PopsiCo which is part of LaLo.", 
          "some company","It is a truth universally acknowledged...", 
          "Hello world",list(NULL)), 
        ncol=2,byrow=TRUE,dimnames=list(NULL,c("Names","Sentences"))),stringsAsFactors=FALSE) 

null_elements <- which(sapply(df$Sentences,is.null)) 
df$Sentences[null_elements] <- "" # replacing NULLs to avoid errors 
df$dist <- mapply(stringdist,df$Names,df$Sentences) 
df$n2 <- nchar(df$Sentences) 
df$n1 <- nchar(df$Names) 
df$match_quality <- df$dist-(df$n2-df$n1) 
cutoff <- 2 
df$match <- df$match_quality <= cutoff 
df$Sentences[null_elements] <- list(NULL) # setting null elements back to initial value 
df$match[null_elements] <- NA # optional, set to FALSE otherwise, as it will prevent some false positives if Names is shorter than cutoff 

# Names            Sentences dist n2 n1 match_quality match 
# 1 Airplanes Sarl   Airplanes-Sàrl is part of Airplanes-Group Sarl. 33 47 14    0 TRUE 
# 2  Kidco Ltd.  100% ownership of Kidco.Ltd. is the mother company. 42 51 10    1 TRUE 
# 3  Popsi Co. Cola Inc. is 50% share of PopsiCo which is part of LaLo. 48 56 9    1 TRUE 
# 4 some company    It is a truth universally acknowledged... 36 41 12    7 FALSE 
# 5 Hello world              NULL 11 0 11   22 NA 
+0

Moody_Mudskipper, la réponse est vraiment bonne! Cependant, si les données dans 'Sentences' sont NULL, cela signifie qu'il y a une correspondance TRUE. Vous pouvez l'essayer avec l'exemple que vous avez donné, puis insérer n'importe quoi dans 'Noms' et laisser 'Phrases' vide. – Probs

+0

Je pense que ça devrait bien fonctionner maintenant, bien que je n'ai pas eu de vraies correspondances dans mon cas, j'ai eu des erreurs si Sentences était NULL, dites-moi si cela fonctionne. –