提高循环内 bind_rows 的速度(3000 个数据帧)
Increase speed of bind_rows within loop (3000 dataframes)
我分析了一个非常大的数据库,其中包含超过 500 万条数据行和 40 列。
出于实际原因,结果被分成小的“.Rdata”文件。
我总共有超过 3000 个文件,每个文件的大小都达到 1Mb。
我设计了一个快速循环,使用 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)}
}
有没有更有效的方法来编写这个循环?
使用 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)
另一个选项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()
使用 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
这正是我所需要的。问题得到解答。谢谢大家
我分析了一个非常大的数据库,其中包含超过 500 万条数据行和 40 列。 出于实际原因,结果被分成小的“.Rdata”文件。 我总共有超过 3000 个文件,每个文件的大小都达到 1Mb。
我设计了一个快速循环,使用 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)}
}
有没有更有效的方法来编写这个循环?
使用 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)
另一个选项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()
使用 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
这正是我所需要的。问题得到解答。谢谢大家