2 votes

Correspondance partielle de chaînes de caractères en R et valeur de retour (en R)

Je dispose de plusieurs bases de données d'approvisionnement sur lesquelles je dois exécuter une liste de "mots-clés" que j'ai construite pour identifier certains produits et, en cas de correspondance, j'aimerais classer les produits dans une catégorie chirurgicale.

Voici un exemple.

Base de données des marchés publics (en fait, j'ai plus de 2 000 000 de lignes à parcourir) :

d<-data.frame(prod_desc=c("BANDELETTE TVTO-OBTRYX HALO", "BANDELETTE MINI ARC PRECISES", "BANDELETTE D'ANALYSE POUR GLYCEMIE", "DIACH. BANDELETTE STER 19MM X 72MM","SLING MALE SYSTEM","DIACHILON","AIGUILLE","GANT","LABEL","CRAYON"),label=1:10)

Liste de mots-clés et valeur de retour (liste réelle beaucoup plus longue) :

kw<-data.frame(kw=c("bandelette","tvt","bande transvaginale","sling system","argus"),category="ss_bandelette")

Je voudrais trouver les produits prod_desc qui contient ma chaîne de mots-clés kw et s'il y a une concordance, je voudrais ajouter une colonne dans le fichier d qui renverrait le category associé à la kw dans le kw cadre de données.

Pour l'instant, j'ai pu obtenir le résultat souhaité en utilisant le code suivant :

d$match <- ifelse(d$cat <- grepl(paste(kw$kw,collapse="|"), d$name,ignore.case = TRUE) == "TRUE","SS_Bandelette","-")

Mais ce code n'est pas vraiment efficace car j'ai environ 350 mots-clés qui sont associés à environ 30 catégories différentes. Quel code puis-je utiliser pour renvoyer automatiquement la catégorie dans le champ d le cadre de données si l'un de mes mots-clés est déclenché ?

Merci beaucoup pour votre aide.

Phil

1voto

joel.wilson Points 6177
# made all to lowercase
d$prod_desc <- tolower(d$prod_desc)
# create a logical matrix that specifies which keywords are present on each row of 'd'
m = data.frame(sapply(kw$kw, grepl, d$prod_desc))
colnames(m) = kw$kw

# create a column in 'd' with the corresponding keyword      
d$kw <- apply(m, 1, function(x) names(x)[which(x)[1]])
# simple merge
merge(d, kw, by = "kw", all.x = T)

#           kw                          prod_desc label      category
#1  bandelette bandelette d'analyse pour glycemie     3 ss_bandelette
#2  bandelette diach. bandelette ster 19mm x 72mm     4 ss_bandelette
#3  bandelette        bandelette tvto-obtryx halo     1 ss_bandelette
#4  bandelette       bandelette mini arc precises     2 ss_bandelette
#5        <NA>                  sling male system     5          <NA>
#6        <NA>                          diachilon     6          <NA>
#7        <NA>                           aiguille     7          <NA>
#8        <NA>                               gant     8          <NA>
#9        <NA>                              label     9          <NA>
#10       <NA>                             crayon    10          <NA>

0voto

Khaynes Points 717
# Create dataframe as per original question
d<-data.frame(prod_desc=c("BANDELETTE TVTO-OBTRYX HALO", "BANDELETTE MINI ARC PRECISES", "BANDELETTE D'ANALYSE POUR GLYCEMIE", "DIACH. BANDELETTE STER 19MM X 72MM","SLING MALE SYSTEM","DIACHILON","AIGUILLE","GANT","LABEL","CRAYON"),label=1:10)
# Create keywords as per origianl question
kw<-data.frame(kw=c("bandelette","tvt","bande transvaginale","sling system","argus"),category="ss_bandelette")
# Assume you want match/tag string on word boundaries? If not; "BANDELETTE TVTO-OBTRYX HALO" would match to "tvt" for instance.
kw$kw <- paste0("\\b",kw$kw,"\\b")

x <- sapply(kw$kw, function(x) grepl(tolower(x), tolower(d$prod_desc)))
d$Match <- apply(x, 1, function(i) paste0(names(i)[i]))
d$Match <- kw$category[match(d$Match,kw$kw)]
d
#                             prod_desc label         Match
# 1         BANDELETTE TVTO-OBTRYX HALO     1 ss_bandelette
# 2        BANDELETTE MINI ARC PRECISES     2 ss_bandelette
# 3  BANDELETTE D'ANALYSE POUR GLYCEMIE     3 ss_bandelette
# 4  DIACH. BANDELETTE STER 19MM X 72MM     4 ss_bandelette
# 5                   SLING MALE SYSTEM     5          <NA>
# 6                           DIACHILON     6          <NA>
# 7                            AIGUILLE     7          <NA>
# 8                                GANT     8          <NA>
# 9                               LABEL     9          <NA>
# 10                             CRAYON    10          <NA>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X