Tres fracasos y medio con R

15 Dic

Hoy, mientras Raúl departía en el cuarto de al lado —él os dirá por qué y para qué— y hacía tiempo para saludarlo, me he entretenido fracasando tres veces y media en lo que abajo desarrollo. No pensaba publicarlo hasta que, reflexionando, he considerado que, a veces, más útil es una buena pregunta que algunas certezas. Inconcluso —o fracasado— puede no significar inútil o imperfecto.

Veamos en qué han consistido mis fraccionarios fracasos.

He intentado algo imposible: leer un fichero de texto de dos gigas en un ordenador de otras cuantas de RAM. Como no tenía un fichero de tal magnitud a mano, me lo he fabricado a partir de otro de cuatro meguillas:

asdf <- read.table( "fichero_de_4_megas.txt", header = T, sep = "\t" )
write.table( asdf, file = "test_data.txt", row.names = F, sep = "\t" )
for( i in 1:500 ) write.table( asdf, file = "test_data.txt", row.names = F, col.names = F, append = T, sep = "\t" )

Dos gigas, pues, de columnas de texto separadas por tabuladores en test_data.txt. Raúl seguía ocupado y he probado la opción más básica (primer fracaso):

bigdata <- read.table( "test_data.txt", header = T, sep = "\t" )

Al cabo de un rato he obtenido un error. He olvidado, por primerizo, usar system.time para ver cuánto se ha demorado el castañetazo. En la siguiente sería.

El segundo fracaso lo he cosechado con una versión más sofisticada de read.table (es decir, read.table con guirnaldas y abalorios para, como dicen los que hacen llorar a Cervantes, eficientar la lectura de datos:

bigdata <- read.table( "test_data.txt", header = T, sep = "\t", comment.char = "", colClasses = c( "numeric", "factor", "numeric", "factor", "numeric", "factor", "factor", "factor", "factor", "factor", "numeric", "numeric", "numeric", "factor", "factor" ) )

Eliminar el caracter de comentario y predefinir el tipo de columnas sólo ha servido para acelerar el momento en el que malloc se ha pegado un cabezazo contra el techo de la RAM. Fracaso dos.

A la tercera he tenido un medio éxito  —¿de qué estaría hablando Raúl tanto rato?— utilizando un paquete que publicó en CRAN un personaje de mala calaña al que no hay que creer nada de cuanto dice o escribe:

library( colbycol )
system.time( bigdata <- cbc.read.table( "test_data.txt", header = T, sep = "\t" ) )

La función cbc.read.table de este malhadado paquete rasca el disco duro durante 1.092,80 segundos y termina felizmente. Quien lea la documentación que la acompaña descubrirá que ni ha cargado datos ni ha hecho mucho más de provecho: sólo los ha almacenado en disco de otra manera. No obstante, se pueden cargar columnas individuales y hacer cosas con ellas con comandos del tipo:

col.1 <- cbc.get.col( bigdata, 1 )

No obstante, si uno trata de recomponer el conjunto de datos íntegro en memoria mediante algo parecido a

mis.datos <- sapply( 1:ncol( bigdata), function( x ) cbc.get.col( bigdata, x ) )

el ordenador inicia un encomiable pero fútil esfuerzo hacia un fracaso ineluctable. Es decir, falla. No obstante, como ha sido posible todavía hacer algo con los datos, consideraré que el fracaso, en este caso, ha sido parcial.

El cuarto ensayo ha sido un remedo de algo que leí. Tenía ganas de probar sqldf (y también SQLite, claro). ¿Que qué es SQLite? Pues es una base de datos que algunos lleváis en el bolsillo. De hecho, la llevaba un tipo que alegaba que, en bases de datos, Oracle y nada más…

Pero, retomando el hilo de nuestro tema, haciendo:

library(sqldf)
tmp <- file( "test_data.txt" )
system.time( bigdata <- sqldf( "select * from tmp", dbname = tempfile(), file.format = list(header = T, row.names = F, sep = "\t")) )

uno vuelve a toparse con el consabido error. Efectivamente, los datos se cargan en SQLite pero luego, al tratar de importarlos a R… catástrofe. Eso sí, en tan sólo 688,20 segundos.

El problema de la lectura de conjuntos grandes de datos en R es acuciante y está —manifiesta y reiteradamente— sobre la mesa. Las buenas noticias son que problemas como el que cuento, hace ocho años, se tenían con ficheros de 10 megas. Dentro de nada, esto que escribo hoy será una reliquia que se leerá con un punto de nostalgia.

11 respuestas a «Tres fracasos y medio con R»

  1. Hola buenas, estoy empezando a interesarme por R y leyendo entre otras vuestras estupendas aportaciones. Uno de los problemas efectivamente que encontré fue la de importar ficheros de gran tamaño. La cuestión es: si dividimos el fichero en ficheros más pequeños, y después los unimos en R, ¿este proceso de unión también dará errores, o hay manera de solventarlo?

  2. dcb, creo que tu experiencia probando ese paquete será bien recibida en el blog. Yo tenía intención de probarlo algún día… pero nunca saco tiempo para ponerme.

  3. para el fin de semana, seguramente pueda hacer pruebas. Algo básico, leer un fichero de texto y probar a hacer algún análisis sencillo, aunque sea con una muestra. Durante la semana, a ratos, me estoy documentando.

    He podido indagar también sobre el paquete filehash, que se supone traslada los datos que estarían en memoria a determinado formato de bbdd en disco y que supuestamente serían una solución «completa» al problema. Más info aquí y en otros sitios simplemente buscando por google:

    http://www.biostat.jhsph.edu/~rpeng/RR/filehashRnews/filehashTR.pdf

    http://yusung.blogspot.com/search?q=filehash

    La duda que me queda es la facilidad de manejo que tengan y el comportamiento de estos sistemas a la hora de hacer análisis. Prometo ir dando impresiones de lo que vaya probando y ojalá haya alguien que los haya usado y nos pueda ilustrar mejor.,

    Saludos

  4. Hola, he estado probando parte de lo que comenté arriba, y finalmente he llegado a buen puerto en la misión de cargar un conjunto de datos de 4,7Gb con la librería filehash y la inestimable ayuda del paquete colbycol de Carlos J. Gil Bellosta. El archivo es cargado correctamente , aunque hay problemas para ejecutar funciones estadísticas de R sobre la totalidad del fichero, como regresiones por ejemplo, aunque supongo que en cierta medida pueden ser de una u otra manera esquivadas en ciertos casos. Los detalles son un poco extensos para ponerlos en un comentario de un artículo, así que me he decidido a ponerlo en un blog que llevaba bastante sin actualizar y que trata temas afines.

    http://probabilitum.blogspot.com/2010/01/software-estadistico-r-trabajar-con.html

    espero no incomode que lo ponga como link a un blog mío ; ruego no se tome esto como spam, ya que sinceramente, sólo es ánimo de avanzar un poco en solucionar o atajar este tipo de problemas.

    Saludos.

  5. Muy bien por los comentarios. De hecho, habrás visto que muchas de mis entradas están incompletas: siempre espero que venga alguien a completar los detalles.

    A todo esto: déjame un correo. El mío, por si acaso, es

    cgb de datanalytics y luego, punto y lo de siempre.

  6. Pingback: R y conjuntos de datos “grandes” « Datanalytics: estadística y minería de datos

  7. Hola a todos, creo que tengo una solución a este problema, aunque reitero que no lo he probado con un archivo de datos de dos gigas, si lo hice con un archivo de 182 megas. Consiste en poder comprimir el documento en un formato especial con extensión .dta el cual es un formato comprimido de la base en stata. R permite realizar esto con el paquete foregin, luego de esto la lectura de este archivo comprimido supera en tiempo a la lectura del read.table y scan. Personalmente escribi algo de esto en el siguiente post

    http://alexjzc.wordpress.com/2010/01/17/time-read-compressing-r/

    Faltaría probar con un archivo como el que uds generan. Muchos éxitos.

  8. Pingback: datanalytics » R y conjuntos de datos “grandes”

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *