Esta es una nueva versión de otra pregunta publicada, ahora con un ejemplo reproducible.

Estoy tratando de convertir una matriz de características de documento de 29117 Tweets a un marco de datos en R, pero aparece el error

"Error en asMethod (objeto): error de Cholmod 'problema demasiado grande' en el archivo ../Core/cholmod_dense.c, línea 105"

El tamaño del dfm es de aproximadamente 21 MB con 29117 filas y 78294 características (las palabras en los tweets se dividen en columnas con un 1 o 0, dependiendo de si la palabra aparece en el tweet)

##generel info;
memory.size(max=TRUE)
# [1] 11418.75
sessionInfo()
# R version 3.6.1 (2019-07-05)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# Running under: Windows 10 x64 (build 18362)

##install packages, load librarys
# install.packages(c("quanteda", "devtools"))
# devtools::install_github("quanteda/quanteda.corpora")
library("quanteda")
library(RJSONIO)
library(data.table)
library(jsonlite)
library(dplyr)
library(glmnet)

##load data, convert to a dataframe, convert to a dfm

baseurl <- "https://raw.githubusercontent.com/alexlitel/congresstweets/master/data/"
d0 <- fromJSON(paste0(baseurl, "2019-10-07.json"), flatten = TRUE)
d1 <- fromJSON(paste0(baseurl, "2019-10-06.json"), flatten = TRUE)
d2 <- fromJSON(paste0(baseurl, "2019-10-05.json"), flatten = TRUE)
d3 <- fromJSON(paste0(baseurl, "2019-10-04.json"), flatten = TRUE)
d4 <- fromJSON(paste0(baseurl, "2019-10-03.json"), flatten = TRUE)
d5 <- fromJSON(paste0(baseurl, "2019-10-02.json"), flatten = TRUE)
d6 <- fromJSON(paste0(baseurl, "2019-10-01.json"), flatten = TRUE)
d7 <- fromJSON(paste0(baseurl, "2019-09-30.json"), flatten = TRUE)
d8 <- fromJSON(paste0(baseurl, "2019-09-29.json"), flatten = TRUE)
d9 <- fromJSON(paste0(baseurl, "2019-09-28.json"), flatten = TRUE)
d10 <- fromJSON(paste0(baseurl, "2019-09-27.json"), flatten = TRUE)
d11 <- fromJSON(paste0(baseurl, "2019-09-26.json"), flatten = TRUE)
d12 <- fromJSON(paste0(baseurl, "2019-09-25.json"), flatten = TRUE)

d <- rbind(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12)

rm(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12)

d$text <- as.character(d$text)

dfm <-dfm((corpus(select(d, id, text))), remove_punct=TRUE, remove=c(  stopwords("english"), "t.co", "https", "rt", "amp", "http", "t.c", "can"))

dfm_df <- convert(dfm, to= 'data.frame')

#Error in asMethod(object) : 
  #Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105

El siguiente código funciona en una muestra del conjunto de datos con 2000 filas (12577 características en dfm (2 MB)).

Necesito convertir el dfm a un marco de datos porque quiero agregar variables y usarlas en una regresión logística binaria (lazo), como fuente y si el tweet es un retweet y contiene una url


d_t <- d[c(1:2000), (1:7)]

##code control variable

#url

d_t$url<- as.integer(ifelse(grepl("://", d_t$text), "1", "0"))

#source used
d_t$source_grp[grepl("Twitter for Android", d_t$source)] <- "Twitter for Android"
d_t$source_grp[grepl("Twitter Web Client", d_t$source)] <- "Twitter Web Client"
d_t$source_grp[grepl("Twitter for iPhone", d_t$source)] <- "Twitter for iPhone"
d_t$source_grp[grepl("Twitter for Windows", d_t$source)] <- "Twitter for Windows"
d_t$source_grp[grepl("Twitter for Samsung Tablets", d_t$source)] <- "Samsung Tablets"
d_t$source_grp[grepl("Twitter for Android Tablets", d_t$source)] <- "Android Tablets"
d_t$source_grp[grepl("Twitter for Windows Phone", d_t$source)] <- "Windows Phone"
d_t$source_grp[grepl("Twitter for BlackBerry", d_t$source)] <- "BlackBerry"
d_t$source_grp[grepl("Twitter for iPad", d_t$source)] <- "Twitter for iPad"
d_t$source_grp[grepl("Twitter for Mac", d_t$source)] <- "Twitter for Mac"
d_t$source_grp[is.na(d_t$source_grp)] <- "Other"   

#retweet

d_t$retweet <- ifelse(grepl("RT @", d_t$text), "1", "0") #create a variable that takes the value 1 when it is a RT

##create a x and y matrix

x= model.matrix ( retweet~., cbind(select(d_t, retweet, source_grp, url), convert(dfm((corpus(select(d_t, id, text))), remove_punct=TRUE, remove=c(  stopwords("english"), "t.co", "https", "rt", "amp", "http", "t.c", "can")), to="data.frame")) )[,-1]

y=d_t$retweet

lasso <- cv.glmnet(x=x, y=y, alpha=1, nfolds=5, family="binomial")


He leído otras publicaciones que dicen que el error 'problema demasiado grande' se debe a la cantidad de RAM. Estos datos no son muy grandes y he intentado crear una máquina virtual con 30RAM (en una ventana de 64 bits con 30 GB de espacio libre), pero sigo recibiendo el mismo error. Por lo tanto, me pregunto si el problema es la cantidad de RAM o si hay límites en la cantidad de columnas en los marcos de datos en R. Puedo agregar sin problemas DFM adicionales del mismo tamaño y más grandes en la memoria.

No es una solución reducir el conjunto de datos y volver a ejecutar el código, ya que esto ya es una muestra. Necesito crear un marco de datos (o algo así) a partir de un dfm creado a partir de un conjunto de datos de 6 millones de filas (si es posible)

Se agradece cualquier ayuda / solución, también otras formas de agregar variables al dfm, sin convertirlo en un marco de datos.

¡Gracias de antemano!

1
Mette Foss 9 oct. 2019 a las 13:48

1 respuesta

La mejor respuesta

El problema es que está intentando convertir una matriz dispersa (dfm) en un objeto denso. En su caso, esto tiene dimensiones de:

> dfm
Document-feature matrix of: 29,117 documents, 78,294 features (100.0% sparse).

> prod(dim(dfm))
[1] 2279686398

O 2.3 mil millones de celdas, razón por la cual ocurre el error. El objeto es extremadamente escaso, por lo que no es un problema como dfm, pero explota cuando intenta registrar tantos ceros en una matriz. La mayor parte del objeto está vacío:

> sparsity(dfm)
[1] 0.9996795

Lo que significa que el 99,97% de las celdas son ceros. Incluso si pudiera crear el marco de datos, ajustar un modelo LASSO no funcionará debido a esta extrema falta de información en las entidades.

¿Solución? Recorta algunas funciones.

Esto funciona, al menos en mi máquina:

> dfmtrimmed <- dfm_trim(dfm, min_docfreq = 10, min_termfreq = 20, verbose = TRUE)
Removing features occurring: 
  - fewer than 20 times: 73,573
  - in fewer than 10 documents: 70,697
  Total features removed: 73,573 (94.0%).
> dfmtrimmed
Document-feature matrix of: 29,117 documents, 4,721 features (99.6% sparse).

> nrow(convert(dfmtrimmed, to = "data.frame"))
[1] 29117

Pero esto sigue siendo un 99,6% escaso, por lo que tiene mucho más sentido recortar de manera más agresiva.

2
Ken Benoit 9 oct. 2019 a las 16:29