tidytext spanish sentiment idf hacer data como analyze r lda topic-modeling topicmodels

spanish - tidytext en r



¿Eliminar documentos vacíos de DocumentTermMatrix en R topicmodels? (5)

Estoy haciendo modelado de temas usando el paquete topicmodels en R. Estoy creando un objeto Corpus, haciendo un preprocesamiento básico y luego creando una DocumentTermMatrix:

corpus <- Corpus(VectorSource(vec), readerControl=list(language="en")) corpus <- tm_map(corpus, tolower) corpus <- tm_map(corpus, removePunctuation) corpus <- tm_map(corpus, removeWords, stopwords("english")) corpus <- tm_map(corpus, stripWhitespace) corpus <- tm_map(corpus, removeNumbers) ...snip removing several custom lists of stopwords... corpus <- tm_map(corpus, stemDocument) dtm <- DocumentTermMatrix(corpus, control=list(minDocFreq=2, minWordLength=2))

Y luego realizar LDA:

LDA(dtm, 30)

Esta llamada final a LDA () devuelve el error

"Each row of the input matrix needs to contain at least one non-zero entry".

Supongo que esto significa que hay al menos un documento que no tiene términos después del preprocesamiento. ¿Hay alguna manera fácil de eliminar documentos que no contengan términos de una DocumentTermMatrix?

Busqué en la documentación del paquete topicmodels y encontré la función removeSparseTerms, que elimina los términos que no aparecen en ningún documento, pero no hay un análogo para eliminar documentos.


Esto es solo para elaborar sobre la respuesta dada por el estudio.

En lugar de eliminar las filas vacías de la matriz dtm, podemos identificar los documentos en nuestro corpus que tienen longitud cero y eliminar los documentos directamente del corpus, antes de realizar un segundo dtm con solo documentos no vacíos.

Esto es útil para mantener una correspondencia 1: 1 entre el dtm y el corpus.

empty.rows <- dtm[rowTotals == 0, ]$dimnames[1][[1]] corpus <- corpus[-as.numeric(empty.rows)]


La respuesta de agstudy funciona muy bien, pero usarla en una computadora lenta resultó algo problemático.

tic() row_total = apply(dtm, 1, sum) dtm.new = dtm[row_total>0,] toc() 4.859 sec elapsed

(esto fue hecho con un 4000x15000 dtm)

El cuello de botella parece estar aplicando sum() a una matriz dispersa.

Una matriz de término de documento creada por el paquete tm contiene los nombres i y j, que son índices para los que las entradas están en la matriz dispersa. Si dtm$i no contiene un índice de fila particular p , entonces la fila p está vacía.

tic() ui = unique(dtm$i) dtm.new = dtm[ui,] toc() 0.121 sec elapsed

ui contiene todos los índices distintos de cero, y como dtm$i ya está ordenado, dtm.new estará en el mismo orden que dtm . La ganancia de rendimiento puede no ser importante para matrices de términos de documentos más pequeños, pero puede volverse significativa con matrices más grandes.


Simplemente elimine los términos dispersos del DTM y todo funcionará bien.

dtm <- DocumentTermMatrix(crude, sparse=TRUE)


Solo un pequeño apéndice a la respuesta de Darío Lacan:

empty.rows <- dtm[rowTotals == 0, ]$dimnames[1][[1]]

recogerá la id del registro, en lugar de números de orden. Prueba esto:

library(tm) data("crude") dtm <- DocumentTermMatrix(crude) dtm[1, ]$dimnames[1][[1]] # return "127", not "1"

Si construye su propio corpus con numeración consecutiva, después de la limpieza de datos, algunos documentos pueden eliminarse y la numeración también se romperá. Entonces, es mejor usar la id directamente:

corpus <- tm_filter( corpus, FUN = function(doc) !is.element(meta(doc)$id, empty.rows)) # !( meta(doc)$id %in% emptyRows ) )


"Each row of the input matrix needs to contain at least one non-zero entry"

El error significa que la matriz dispersa contiene una fila sin entradas (palabras). una Idea es calcular la suma de palabras por fila

rowTotals <- apply(dtm , 1, sum) #Find the sum of words in each Document dtm.new <- dtm[rowTotals> 0, ] #remove all docs without words