2011-05-28 10 views
22

¿Es posible crear una barra de progreso para los datos cargados en R usando load()?¿Cómo creo una barra de progreso para la carga de datos en R?

Para un proyecto de análisis de datos, matrices grandes se están cargando en R desde archivos .RData, que tardan varios minutos en cargarse. Me gustaría tener una barra de progreso para controlar cuánto tiempo pasará antes de que se carguen los datos. R ya tiene una buena funcionalidad de progress bar integrada, pero load() no tiene ganchos para monitorear la cantidad de datos que se han leído. Si no puedo usar la carga directamente, ¿hay alguna forma indirecta de que pueda crear dicha barra de progreso? Tal vez cargar el archivo .RData en portafolios y juntarlos para R. ¿Alguien tiene pensamientos o sugerencias sobre esto?

+0

No sé cómo hacer una barra de progreso, pero ¿ha considerado al menos mostrar un temporizador? Encuentro que ejecutar un temporizador hace que la espera pase más rápido, y luego sé que el programa aún está respondiendo. Puede mostrar un mensaje como 'Usted ha estado esperando 1:32 y la espera es normalmente ~ 3 minutos. ¡Tómate un café! ' –

+0

Dos preguntas anteriores: http://stackoverflow.com/questions/5423760/how-do-you-create-a-progress-bar-when-using-the-foreach-function-in-r/ 6170107 # 6170107 y http://stackoverflow.com/q/3820402/583830 sugieren 'txtProgressBar' y' gtkProgressBar'. El último es del paquete RGtk2. ¿Es esto lo que estás buscando? – jthetzel

+0

Lo siento, eché de menos que ya conoces la función 'txtProgressBar' y que tu pregunta es sobre cargar archivos .Rdata. – jthetzel

Respuesta

12

Se me ocurrió la siguiente solución, que funcionará para archivos de menos de 2^32 - 1 bytes.

El objeto R necesita ser serializado y guardado en un archivo, como lo hace el siguiente código.

saveObj <- function(object, file.name){ 
    outfile <- file(file.name, "wb") 
    serialize(object, outfile) 
    close(outfile) 
} 

Luego leemos los datos binarios en fragmentos, haciendo un seguimiento de cuánto se lee y actualizando la barra de progreso en consecuencia.

loadObj <- function(file.name){ 
    library(foreach) 
    filesize <- file.info(file.name)$size 
    chunksize <- ceiling(filesize/100) 
    pb <- txtProgressBar(min = 0, max = 100, style=3) 
    infile <- file(file.name, "rb") 
    data <- foreach(it = icount(100), .combine = c) %do% { 
     setTxtProgressBar(pb, it) 
     readBin(infile, "raw", chunksize) 
    } 
    close(infile) 
    close(pb) 
    return(unserialize(data)) 
} 

El código se puede ejecutar de la siguiente manera:

> a <- 1:100000000 
> saveObj(a, "temp.RData") 
> b <- loadObj("temp.RData") 
    |======================================================================| 100% 
> all.equal(b, a) 
[1] TRUE 

Si referente al método barra de progreso en contra de leer el archivo en un único trozo vemos el método barra de progreso es un poco más lento, pero no lo suficiente preocuparse de.

> system.time(unserialize(readBin(infile, "raw", file.info("temp.RData")$size))) 
    user system elapsed 
    2.710 0.340 3.062 
> system.time(b <- loadObj("temp.RData")) 
    |======================================================================| 100% 
    user system elapsed 
    3.750 0.400 4.154 

Así que, aunque el método anterior funciona, creo que es completamente inútil debido a las restricciones de tamaño de archivo. Las barras de progreso solo son útiles para archivos grandes que tardan mucho tiempo en leerse.

¡Sería genial si alguien pudiera encontrar algo mejor que esta solución!

3

¿Podría sugerir, en cambio, acelerar las cargas (y guardar) veces para que no se necesite una barra de progreso? Si leer una matriz es "rápido", entonces podría informar el progreso entre cada matriz de lectura (si tiene muchas).

Aquí hay algunas medidas. Simplemente configurando compress = FALSE, la velocidad de carga se duplica. Pero al escribir un serializador de matriz simple, la velocidad de carga es casi 20 veces más rápida.

x <- matrix(runif(1e7), 1e5) # Matrix with 100k rows and 100 columns 

system.time(save('x', file='c:/foo.bin')) # 13.26 seconds 
system.time(load(file='c:/foo.bin')) # 2.03 seconds 

system.time(save('x', file='c:/foo.bin', compress=FALSE)) # 0.86 seconds 
system.time(load(file='c:/foo.bin')) # 0.92 seconds 

system.time(saveMatrix(x, 'c:/foo.bin')) # 0.70 seconds 
system.time(y <- loadMatrix('c:/foo.bin')) # 0.11 seconds !!! 
identical(x,y) 

donde saveMatrix/loadMatrix se definen de la siguiente manera. Actualmente no manejan dimnames y otros atributos, pero eso podría agregarse fácilmente.

saveMatrix <- function(m, fileName) { 
    con <- file(fileName, 'wb') 
    on.exit(close(con)) 
    writeBin(dim(m), con) 
    writeBin(typeof(m), con) 
    writeBin(c(m), con) 
} 

loadMatrix <- function(fileName) { 
    con <- file(fileName, 'rb') 
    on.exit(close(con)) 
    d <- readBin(con, 'integer', 2) 
    type <- readBin(con, 'character', 1) 
    structure(readBin(con, type, prod(d)), dim=d) 
} 
+0

Solo necesitamos cargar una matriz única que tenga varias (3+) gigas de tamaño. Consideré dividir la matriz en varias partes y luego leerlas por separado, pero esa es una solución fea y no vale la complejidad solo para una barra de progreso. – Nixuz

+0

... entonces la cargaMatriz anterior debería acelerar considerablemente ... ¿Lo intentó? – Tommy

+0

La [bigmemory library] (http://cran.r-project.org/web/packages/bigmemory/index.html) para guardar y cargar matrices numéricas muy grandes, sería una solución buena y rápida también. – Nixuz

Cuestiones relacionadas