Увеличение скорости bind_rows в цикле (3000 кадров данных) - PullRequest
1 голос
/ 10 мая 2019

Я проанализировал очень большую базу данных с более чем 5 миллионами строк данных и 40 столбцами.Результаты разбиты на небольшие файлы .Rdata по практическим соображениям.Всего у меня более 3000 файлов размером до 1 МБ.

Я разработал быстрый цикл для объединения этих файлов в один фрейм данных с использованием dplyr, однако это очень медленно, и я считаю, что есть более быстрые способыдля этого.

Я пытался использовать матрицы с предварительным распределением, но мои данные были как текстовые, так и числовые и получали ошибки.Фреймы данных даже медленнее при использовании базы 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)}
    }

Есть ли более эффективный способ написать этот цикл?

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Другой вариант с 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 голос
/ 10 мая 2019

С помощью purrr::map и purrr::reduce вы можете импортировать и связывать их без использования цикла 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)
0 голосов
/ 10 мая 2019

Использование dplyr и bind_rows

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

Результаты

user  system elapsed 
2.70    0.15    2.87  

Использование функции rbindlist

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

Результаты

 user  system elapsed 
 0.05    0.00    0.04 

Это именно то, что мне было нужно. На вопрос дан ответ. Спасибо всем.

...