Analicé una base de datos muy grande con más de 5 millones de líneas de datos con 40 columnas. Los resultados se dividen en pequeños archivos '.Rdata' por razones prácticas. En total, tengo más de 3000 archivos, cada uno con un tamaño de hasta 1Mb.

He diseñado un bucle rápido para combinar estos archivos en un solo marco de datos usando dplyr, sin embargo, esto es muy lento y creo que hay formas más rápidas de hacerlo.

Traté de usar matrices con preasignación pero mis datos son texto y números y recibí errores. Los marcos de datos son aún más lentos cuando se usa la base R.

list_files = as.data.frame(list.files(path = "output", pattern = 'Rdata'))
names(list_files) = 'full_name'

list_files = list_files %>% 
    separate(full_name, sep ="_", into = c('col1','col2')) %>% 
        separate(col2, sep = '.R', into = c('col3','col4')) %>%
            mutate(col3 = as.numeric(col3)) %>% 
            arrange(col3) %>%  mutate(col3 = as.character(col3))

datax <- c()

for(i in 1:length(list_files$col3))
    {
        load(paste('output/MyData_',list_files$col3[i],'.Rdata',sep=''))
##here loads results_df2
        datax = datax %>% bind_rows(results_df2)
        if((i %% 100) == 0) { print(i)}
    }

¿Hay una manera más eficiente de escribir este bucle?

1
Arkadi w 10 may. 2019 a las 14:26

3 respuestas

La mejor respuesta

Usando dplyr y bind_rows

system.time( for(i in 1:50) { datax = datax %>% bind_rows( ll[[i]]) })

Resultados

user  system elapsed 
2.70    0.15    2.87  

Uso de la función rbindlist

system.time(ans1 <- rbindlist(ll))

Resultados

 user  system elapsed 
 0.05    0.00    0.04 

Esto es exactamente lo que necesitaba. La pregunta es respondida. Gracias a todos.

0
Arkadi w 10 may. 2019 a las 18:32

Con purrr::map y purrr::reduce, puede importarlos y vincularlos sin usar un bucle for.

library(purrr)
library(dplyr)

# save data frame as rds
# mtcars %>% saveRDS("mtcars1.rds")
# mtcars %>% saveRDS("mtcars2.rds")

# list files
files <- list.files(pattern = "rds")

# read and bind
files %>% map(readRDS) %>% 
                reduce(bind_rows)
1
Imran Kocabiyik 10 may. 2019 a las 13:00

Otra opción con data.table

library(data.table)
library(dplyr)

list_files = list.files(path = "output", pattern = 'Rdata')
lapply(list_files, function(x) load(x) %>% data.table() ) %>% rbindlist()  
1
Fino 10 may. 2019 a las 13:40