Encontrar frases de 2 y 3 palabras usando el paquete R TM

Estoy tratando de encontrar un código que realmente funcione para encontrar las frases de dos y tres palabras usadas con más frecuencia en el paquete de minería de textos R (quizás haya otro paquete que desconozco). He estado tratando de usar el tokenizer, pero parece que no tengo suerte.

Si trabajaste en una situación similar en el pasado, ¿podrías publicar un código que haya sido probado y que realmente funcione? Muchas gracias!

Puede pasar una función personalizada de tokenización a DocumentTermMatrix función DocumentTermMatrix tm , por lo que si tiene instalado el paquete tau es bastante sencillo.

 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)) 

Donde n en la función tokenize_ngrams es el número de palabras por frase. Esta característica también se implementa en el paquete RTextTools , lo que simplifica aún más las cosas.

 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) 

Esto devuelve una clase de DocumentTermMatrix para usar con el paquete tm .

Esta es la parte 5 de las preguntas frecuentes del paquete tm :

5. ¿Puedo usar bigrams en lugar de tokens individuales en una matriz de documento de términos?

Sí. RWeka proporciona un tokenizador para n-gtwigs arbitrarios que pueden pasarse directamente al constructor de matriz de documento de término. P.ej:

  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]) 

Esta es mi propia creación inventada para diferentes propósitos, pero creo que también puede ser aplicable a sus necesidades:

 #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) 

La biblioteca corpus tiene una función llamada term_stats que hace lo que desea:

 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) 

Aquí, el count es el número de apariciones, y el support es la cantidad de documentos que contiene el término.

Agrego un problema similar al usar paquetes tm y ngram . Después de depurar mclapply , vi que había problemas en documentos con menos de 2 palabras con el siguiente error

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

Así que agregué un filtro para eliminar documentos con un número bajo de conteos de palabras:

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

Entonces mi función tokenize se ve así:

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

Entonces puedes probar la función con:

 dtmTest <- lapply(myCorpus.3, bigramTokenizer) 

Y finalmente:

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

Prueba el paquete tidytext

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

)

Supongamos que tengo un dataDame CommentData que contiene la columna de comentarios y quiero encontrar la ocurrencia de dos palabras juntas. Entonces intenta

 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) 

El código anterior crea tokens, y luego elimina palabras de tope que no ayudan en el análisis (por ejemplo, the, an, to, etc.) Luego cuentas la ocurrencia de estas palabras. Luego usará la función unir para combinar palabras individuales y registrar su ocurrencia.

 bigrams_united <- bigram_filtered %>% unite(bigram, word1, word2, sep=" ") bigrams_united 

Prueba este código

 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) 

Esta es la sección bigrams o tri gramos que puedes usar

 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")) 

Espero que esto ayude. Este es un código completo que podrías usar.

Intereting Posts