2017-05-22 2 views
1

J'ai du mal à comprendre l'exploration de texte et à déterminer les fréquences des mots. Je commence juste à avoir une compréhension de R et de ses paquets et je viens de découvrir tm (après avoir lu un moment, j'ai le sentiment que cela pourrait résoudre mon problème).R Text Mining - le mot le plus courant dans une chaîne de caractères entière

Ma question est: comment puis-je déterminer les deux plus fréquemment utilisés dans une chaîne sur toute la colonne?

je l'exemple suivant:

structure(list(Location = c("Chicago", "Chicago", "Chicago", 
"LA", "LA", "LA", "LA", "LA", "LA", "Texas", "Texas", "Texas", 
"Texas", "Texas"), Code = c(4450L, 4450L, 4450L, 4450L, 4450L, 
4450L, 4450L, 4450L, 4450L, 4410L, 4410L, 4410L, 4410L, 4410L 
), Description = c("LABOR - CROSSOVER BOARD BRACKET", "LABOR - CROWN DOOR GASKET", 
"LABOR - CROWN DOOR GASKET - APPLY 4' NEW GASKET AND RE-APPLY", 
"LABOR - CUSHIONING DEVICE - END OF CAR CUSTOMER SUPPLIED MATERIAL", 
"LABOR - DOOR EDGE", "LABOR - DOOR GASKET, CROWN CORNER", "LABOR - DOOR LOCK POCKET STG", 
"LABOR - DOOR LOCK RECEPTICALS STG", "LABOR - DOOR LOCK STG", 
"BOLT, HT, UNDER 5/8\"\" DIA & 6\"\" - SIDE POST", "BOLT, HT, UNDER 5/8\"\" DIA & 6\"\" - TRAINLINE TROLLEY", 
"BOLT,HT,5/8 IN.DIA.OR LESS UNDER 6\"\" LONG - BRAKE STEP", "BOLT,HT,5/8 IN.DIA.OR LESS UNDER 6\"\" LONG - CROSSOVER BOARD", 
"BOLT,HT,5/8 IN.DIA.OR LESS UNDER 6\"\" LONG - CROSSOVER BOARD BRACKET" 
), `Desired Description Based on frequency` = c("Labor - CROWN DOOR GASKET", 
"Labor - CROWN DOOR GASKET", "Labor - CROWN DOOR GASKET", "Labor - DOOR LOCK", 
"Labor - DOOR LOCK", "Labor - DOOR LOCK", "Labor - DOOR LOCK", 
"Labor - DOOR LOCK", "Labor - DOOR LOCK", "Bolt - HT", "Bolt - HT", 
"Bolt - HT", "Bolt - HT", "Bolt - HT")), .Names = c("Location", 
"Code", "Description", "Desired Description Based on frequency" 
), row.names = c(NA, -14L), class = "data.frame") 

En fin de compte, je voudrais pouvoir ajouter cette colonne:

Desired Description Based on frequency 
Labor - CROWN DOOR GASKET 
Labor - CROWN DOOR GASKET 
Labor - CROWN DOOR GASKET 
Labor - DOOR LOCK 
Labor - DOOR LOCK 
Labor - DOOR LOCK 
Labor - DOOR LOCK 
Labor - DOOR LOCK 
Labor - DOOR LOCK 
Bolt - HT 
Bolt - HT 
Bolt - HT 
Bolt - HT 
Bolt - HT 

Fondamentalement, je veux évaluer tous les 4450 ou 4410s et de voir sur tous les la description dans le tableau, qui le plus commun et ajouter que comme une colonne. Une autre condition serait basée sur l'emplacement. Quelqu'un peut-il m'aider s'il vous plaît avec un exemple simple?

Merci beaucoup

+1

Bienvenue ALORS. Veuillez utiliser 'dput' pour fournir vos données d 'entrée et le cadre de données de sortie désiré (aimée dans l' info - lettre R sur l 'étiquette). – lukeA

+0

Merci Luc. Mes données d'entrée sont énormes, donc j'en ai pris une petite fraction pour montrer un exemple simple de ce que je souhaite réaliser. Je peux fournir plus d'informations si ce n'est pas assez clair. – iCosmin

+1

Je voulais dire: veuillez éditer votre message et remplacer l'échantillon de données par 'dput (datasample)' - cela facilite l'importation de l'échantillon dans une session R et la lecture/expérimentation avec celui-ci. La façon dont vous l'avez fourni, il faudrait placer un délimiteur pour l'importer. – lukeA

Répondre

1

Je ne pense pas qu'il y ait une taille unique-it-all solution à votre problème. (En commençant par le fait qu'il n'y a pas de règle précise à laquelle ou combien de mots à prendre pour la description.) Cependant, voici deux rapides & approches sales qui pourraient être utiles comme point de départ:

library(tm) 
txts <- gsub("[^A-Z]", " ", df$Description) 
groups <- paste(df$Location, df$Code) 

# 1 
opts <- list(tolower=F, removePunctuation=TRUE, wordLengths=c(2, Inf)) 
lst <- split(txts, groups) 
res <- sapply(lst, function(x) { 
    freq <- termFreq(paste(x, collapse=" "), opts)/length(x) 
    paste(names(freq[rank(-freq, ties.method = "first")<=3]), collapse = " - ") 
}) 
rep(res, lengths(lst)) 

# 2 
lst <- lapply(strsplit(txts, "\\s+"), function(x) x[1:min(c(3,length(x)))]) 
lst <- split(lst, groups) 
n <- lengths(lst) 
lst <- mapply("/", lapply(lst, function(x) sort(table(unlist(x)), decreasing = T)), n) 
rep(sapply(lst, function(x) paste(names(x)[x>=.5], collapse=" - ")), n) 
+0

Luke, tu es un génie! Merci beaucoup pour cette solution géniale. Je ne le comprendrais pas dans les âges. J'apprécie vraiment votre aide. La deuxième approche a fonctionné le mieux pour moi. Pouvez-vous s'il vous plaît me montrer comment puis-je ajouter le résultat de "rep" comme une nouvelle colonne dans mon df d'origine? Je n'ai juste pas trouvé de moyen pour le moment. Merci encore d'être si utile. – iCosmin

+0

@iCosmin Comme 'df $ myResult <- rep (...)'? – lukeA

+0

Précisément. En attendant, j'ai obtenu le même résultat en utilisant mutate. Votre solution fonctionne parfaitement sur les données de l'échantillon, mais lorsque je l'applique à l'ensemble de mes données (271231 obs.), Il semble que la partie regroupement ne fonctionne plus. Lorsque j'imprime chaque étape, tout est exactement le même que dans notre exemple, mais si je regarde de plus près, le résultat renvoie effectivement les mots les plus fréquents dans la description mais n'applique pas la condition de localisation. Y at-il un travail autour? Si je change l'ordre dans les groupes (groupes <- paste (df $ Code, df $ Location) j'obtiens un résultat différent, aidez s'il vous plaît – iCosmin