2010-02-13 9 views
7

Tengo un proceso en R que crea un conjunto de objetos, los serializa y los coloca en archivos de texto sin formato. Esta parecía ser una muy buena forma de manejar las cosas, ya que estoy trabajando con Hadoop y todas las necesidades de salida para transmitir a través de stdin y stdout.R: serializar objetos al archivo de texto y viceversa

El problema que me queda es cómo leer estos objetos fuera del archivo de texto y de nuevo en R en mi máquina de escritorio. Aquí hay un ejemplo de trabajo que ilustra el desafío:

Vamos a crear un archivo tmp y escribir un solo objeto en él. Este objeto es simplemente un vector:

outCon <- file("c:/tmp", "w") 
mychars <- rawToChar(serialize(1:10, NULL, ascii=T)) 
cat(mychars, file=outCon) 
close(outCon) 

El objeto mychars se parece a esto:

> mychars 
[1] "A\n2\n133633\n131840\n13\n10\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" 

cuando se escribe en el archivo de texto que se parece a esto:

A 
2 
133633 
131840 
13 
10 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 

Soy probablemente pasando por alto algo terriblemente obvio, pero ¿cómo vuelvo a leer este archivo en R y desinstalo el objeto? Cuando pruebo scan() o readLines() ambos quiero tratar los nuevos caracteres de línea como delimitadores de registro y termino con un vector donde cada elemento es una fila del archivo de texto. Lo que realmente quiero es una cadena de texto con todo el contenido del archivo. Entonces puedo deserializar la cadena.

Perl volverá a leer los saltos de línea en una cadena, pero no sé cómo anular la forma en que R trata los saltos de línea.

Respuesta

7

JD, lo hacemos en el paquete digest a través de serialize() a/desde raw. Eso es bueno ya que puede almacenar objetos serializados en SQL y otros lugares. De hecho, también lo almacenaría como RData, que es mucho más rápido que load() (¡sin análisis!) Y save().

O, si tiene que ser RawToChar() y ASCII a continuación, utilizar algo como esto (tomado directamente de help(digest) donde comparamos la serialización de la copia de archivos:

# test 'length' parameter and file input 
fname <- file.path(R.home(),"COPYING") 
x <- readChar(fname, file.info(fname)$size) # read file 
for (alg in c("sha1", "md5", "crc32")) { 
    # partial file 
    h1 <- digest(x , length=18000, algo=alg, serialize=FALSE) 
    h2 <- digest(fname, length=18000, algo=alg, serialize=FALSE, file=TRUE) 
    h3 <- digest(substr(x,1,18000) , algo=alg, serialize=FALSE) 
    stopifnot(identical(h1,h2), identical(h1,h3)) 
    # whole file 
    h1 <- digest(x , algo=alg, serialize=FALSE) 
    h2 <- digest(fname, algo=alg, serialize=FALSE, file=TRUE) 
    stopifnot(identical(h1,h2)) 
} 

así que con que su ejemplo se convierte en esto:

R> outCon <- file("/tmp/jd.txt", "w") 
R> mychars <- rawToChar(serialize(1:10, NULL, ascii=T)) 
R> cat(mychars, file=outCon); close(outCon) 
R> fname <- "/tmp/jd.txt" 
R> readChar(fname, file.info(fname)$size) 
[1] "A\n2\n133633\n131840\n13\n10\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" 
R> unserialize(charToRaw(readChar(fname, file.info(fname)$size))) 
[1] 1 2 3 4 5 6 7 8 9 10 
R> 
+0

En retrospectiva, debería haber mantenido mis objetos en bruto. Estaré seguro y notaré que cuando improviso mis lecciones aprendidas del uso de R en Hadoop, parece que la pieza que me faltaba era la función readChar() Gracias de nuevo Dirk! –

+0

Derecha. ¡Y, por completo, olvidé conectar nuestro paquete RProtoBuf que, por supuesto, también ayuda! Sin embargo, todavía no hay ningún binario de Windows, ya que no tenemos una versión construida en MinGW de la biblioteca adecuada para enlazar con R. –

Cuestiones relacionadas