Trouver les Phrases de mots 2 et 3 en utilisant le paquet 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 R text mining package (peut-être qu'il y a un autre package que je ne connais pas). J'ai essayé d'utiliser le générateur de jetons, mais semblent n'avoir aucune chance.

Si vous avez travaillé sur une situation similaire dans le passé, pourriez-vous poster un code qui est testé et fonctionne réellement? Merci beaucoup!

23
demandé sur appletree 2012-01-17 20:53:33

7 réponses

vous pouvez passer dans une fonction de tokenizing personnalisée à la fonction tm 's DocumentTermMatrix , donc si vous avez le 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 dans la fonction tokenize_ngrams est le nombre de mots par phrase. Cette fonctionnalité est également implémentée dans le paquet RTextTools , ce qui simplifie encore plus 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)

renvoie une classe de DocumentTermMatrix pour utilisation avec paquet tm .

11
répondu Timothy P. Jurka 2012-01-18 03:17:48

Ceci est la partie 5 du FAQ du paquet:

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

Oui. RWeka fournit un tokenizer pour n-grammes arbitraire qui peut être transmis directement au constructeur de matrice de document-terme. 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])
7
répondu Ben 2013-05-30 03:52:46

c'est ma propre création faite pour différents buts, mais je pense que peut être applicable à vos besoins aussi:

#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)
3
répondu Tyler Rinker 2015-02-24 18:46:02

le corpus la bibliothèque a 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.

2
répondu Patrick Perry 2017-10-05 11:34:35

j'ajoute un problème similaire en utilisant les paquets tm et ngram . Après avoir débogué mclapply , j'ai vu là où les problèmes sur les documents avec moins de 2 mots avec l'erreur suivante

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

donc j'ai ajouté un filtre pour supprimer le document avec le nombre de mots bas:

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

alors ma fonction tokenize ressemble à:

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 != '']
}

ensuite vous pouvez tester la fonction avec:

dtmTest <- lapply(myCorpus.3, bigramTokenizer)

et enfin:

dtm <- DocumentTermMatrix(myCorpus.3, control = list(tokenize = bigramTokenizer))
1
répondu Géraud 2015-03-16 10:42:25

Try tidytext package

library(dplyr)
library(tidytext)
library(janeaustenr)
library(tidyr

)

supposez que j'ai un CommentData de dataframe qui contient une colonne de commentaires et je veux trouver occurrence de deux mots ensemble. Alors essayez

bigram_filtered <- CommentData %>%
  unnest_tokens(bigram, Comment, token= "ngrams", n=2) %>%
  separate(bigram, c("word1","word2"), sep=" ") %>%
  filter(!word1 %in% stop_words$word,
         !word2 %in% stop_words$word) %>%
  count(word1, word2, sort=TRUE)

le code ci-dessus crée des tokens, puis supprime les mots d'arrêt qui n'aident pas à l'analyse(par ex. le,la, un,etc. Ensuite, vous compter l'apparition de ces mots. Vous utiliserez alors la fonction unite pour combiner des mots individuels et consignez leur occurrence.

bigrams_united <- bigram_filtered %>%
  unite(bigram, word1, word2, sep=" ")
bigrams_united
1
répondu Monika Singh 2017-07-11 13:15:15

essayez ce code.

library(tm)
library(SnowballC)
library(class)
library(wordcloud)

keywords <- read.csv(file.choose(), header = TRUE, na.strings=c("NA","-","?"))
keywords_doc <- Corpus(VectorSource(keywords$"use your column that you need"))
keywords_doc <- tm_map(keywords_doc, removeNumbers)
keywords_doc <- tm_map(keywords_doc, tolower)
keywords_doc <- tm_map(keywords_doc, stripWhitespace)
keywords_doc <- tm_map(keywords_doc, removePunctuation)
keywords_doc <- tm_map(keywords_doc, PlainTextDocument)
keywords_doc <- tm_map(keywords_doc, stemDocument)

c'est la section bigrams ou tri grammes que vous pouvez utiliser.""

BigramTokenizer <-  function(x)
unlist(lapply(ngrams(words(x), 2), paste, collapse = " "), use.names = FALSE)
# creating of document matrix
keywords_matrix <- TermDocumentMatrix(keywords_doc, control = list(tokenize = BigramTokenizer))

# remove sparse terms 
keywords_naremoval <- removeSparseTerms(keywords_matrix, 0.95)

# Frequency of the words appearing
keyword.freq <- rowSums(as.matrix(keywords_naremoval))
subsetkeyword.freq <-subset(keyword.freq, keyword.freq >=20)
frequentKeywordSubsetDF <- data.frame(term = names(subsetkeyword.freq), freq = subsetkeyword.freq) 

# Sorting of the words
frequentKeywordDF <- data.frame(term = names(keyword.freq), freq = keyword.freq)
frequentKeywordSubsetDF <- frequentKeywordSubsetDF[with(frequentKeywordSubsetDF, order(-frequentKeywordSubsetDF$freq)), ]
frequentKeywordDF <- frequentKeywordDF[with(frequentKeywordDF, order(-frequentKeywordDF$freq)), ]

# Printing of the words
wordcloud(frequentKeywordDF$term, freq=frequentKeywordDF$freq, random.order = FALSE, rot.per=0.35, scale=c(5,0.5), min.freq = 30, colors = brewer.pal(8,"Dark2"))

Espérons que cette aide. C'est un code entier que vous pouvez utiliser.

0
répondu Renato Lyke 2017-06-30 18:54:18