24 votes

Recherche de phrases de 2 et 3 mots à l'aide du logiciel R TM

J'essaie de trouver un code qui fonctionne réellement pour trouver les phrases de deux et trois mots les plus fréquemment utilisées dans le package de text mining R (il y a peut-être un autre package pour cela que je ne connais pas). J'ai essayé d'utiliser le tokenizer, mais je n'ai pas eu de chance.

Si vous avez travaillé sur une situation similaire dans le passé, pourriez-vous poster un code qui a été testé et qui fonctionne réellement ? Je vous remercie de tout cœur !

11voto

Timothy P. Jurka Points 878

Vous pouvez passer une fonction de symbolisation personnalisée à la fonction tm 's DocumentTermMatrix donc si vous avez un paquet tau installé, c'est assez simple.

library(tm); library(tau);

tokenize_ngrams <- function(x, n=3) return(rownames(as.data.frame(unclass(textcnt(x,method="string",n=n)))))

texts <- c("This is the first document.", "This is the second file.", "This is the third text.")
corpus <- Corpus(VectorSource(texts))
matrix <- DocumentTermMatrix(corpus,control=list(tokenize=tokenize_ngrams))

n en el tokenize_ngrams est le nombre de mots par phrase. Cette fonctionnalité est également implémentée dans le paquet RTextTools ce qui simplifie encore les choses.

library(RTextTools)
texts <- c("This is the first document.", "This is the second file.", "This is the third text.")
matrix <- create_matrix(texts,ngramLength=3)

Cette méthode renvoie une classe de DocumentTermMatrix à utiliser avec le paquet tm .

8voto

Ben Points 8166

Il s'agit de la cinquième partie de la FAQ de la tm l'emballage :

5. Puis-je utiliser des bigrammes au lieu de tokens simples dans une matrice terme-document ?

Oui. RWeka fournit un tokenizer pour les n-grammes arbitraires qui peut être directement transmis au constructeur de la matrice terme-document. Par exemple :

  library("RWeka")
  library("tm")

  data("crude")

  BigramTokenizer <- function(x) NGramTokenizer(x, Weka_control(min = 2, max = 2))
  tdm <- TermDocumentMatrix(crude, control = list(tokenize = BigramTokenizer))

  inspect(tdm[340:345,1:10])

4voto

Tyler Rinker Points 27607

Il s'agit d'une création personnelle à des fins diverses, mais je pense qu'elle peut s'appliquer à vos besoins également :

#User Defined Functions
Trim <- function (x) gsub("^\\s+|\\s+$", "", x)

breaker <- function(x) unlist(strsplit(x, "[[:space:]]|(?=[.!?*-])", perl=TRUE))

strip <- function(x, digit.remove = TRUE, apostrophe.remove = FALSE){
    strp <- function(x, digit.remove, apostrophe.remove){
        x2 <- Trim(tolower(gsub(".*?($|'|[^[:punct:]]).*?", "\\1", as.character(x))))
        x2 <- if(apostrophe.remove) gsub("'", "", x2) else x2
        ifelse(digit.remove==TRUE, gsub("[[:digit:]]", "", x2), x2)
    }
unlist(lapply(x, function(x) Trim(strp(x =x, digit.remove = digit.remove, 
    apostrophe.remove = apostrophe.remove)) ))
}

unblanker <- function(x)subset(x, nchar(x)>0)

#Fake Text Data
x <- "I like green eggs and ham.  They are delicious.  They taste so yummy.  I'm talking about ham and eggs of course"

#The code using Base R to Do what you want
breaker(x)
strip(x)
words <- unblanker(breaker(strip(x)))
textDF <- as.data.frame(table(words))
textDF$characters <- sapply(as.character(textDF$words), nchar)
textDF2 <- textDF[order(-textDF$characters, textDF$Freq), ]
rownames(textDF2) <- 1:nrow(textDF2)
textDF2
subset(textDF2, characters%in%2:3)

3voto

Patrick Perry Points 1079

En corpus dispose d'une fonction appelée term_stats qui fait ce que vous voulez :

library(corpus)
corpus <- gutenberg_corpus(55) # Project Gutenberg #55, _The Wizard of Oz_
text_filter(corpus)$drop_punct <- TRUE # ignore punctuation
term_stats(corpus, ngrams = 2:3)
##    term             count support
## 1  of the             336       1
## 2  the scarecrow      208       1
## 3  to the             185       1
## 4  and the            166       1
## 5  said the           152       1
## 6  in the             147       1
## 7  the lion           141       1
## 8  the tin            123       1
## 9  the tin woodman    114       1
## 10 tin woodman        114       1
## 11 i am                84       1
## 12 it was              69       1
## 13 in a                64       1
## 14 the great           63       1
## 15 the wicked          61       1
## 16 wicked witch        60       1
## 17 at the              59       1
## 18 the little          59       1
## 19 the wicked witch    58       1
## 20 back to             57       1
## ⋮  (52511 rows total)

Ici, count est le nombre d'apparitions, et support est le nombre de documents contenant le terme.

1voto

Géraud Points 11

J'ajoute un problème similaire en utilisant tm y ngram paquets. Après le débogage mclapply J'ai vu qu'il y avait des problèmes sur les documents de moins de 2 mots avec l'erreur suivante

   input 'x' has nwords=1 and n=2; must have nwords >= n

J'ai donc ajouté un filtre pour supprimer les documents dont le nombre de mots est faible :

    myCorpus.3 <- tm_filter(myCorpus.2, function (x) {
      length(unlist(strsplit(stringr::str_trim(x$content), '[[:blank:]]+'))) > 1
    })

Ma fonction de symbolisation ressemble alors à ce qui suit :

bigramTokenizer <- function(x) {
  x <- as.character(x)

  # Find words
  one.list <- c()
  tryCatch({
    one.gram <- ngram::ngram(x, n = 1)
    one.list <- ngram::get.ngrams(one.gram)
  }, 
  error = function(cond) { warning(cond) })

  # Find 2-grams
  two.list <- c()
  tryCatch({
    two.gram <- ngram::ngram(x, n = 2)
    two.list <- ngram::get.ngrams(two.gram)
  },
  error = function(cond) { warning(cond) })

  res <- unlist(c(one.list, two.list))
  res[res != '']
}

Vous pouvez ensuite tester la fonction avec :

dtmTest <- lapply(myCorpus.3, bigramTokenizer)

Et enfin :

dtm <- DocumentTermMatrix(myCorpus.3, control = list(tokenize = bigramTokenizer))

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