R语言中将数千个CSV文件合并为单个dataframe的高效方法咨询
批量合并CSV文件的R代码提速方案
原有代码性能瓶颈
原有代码的性能瓶颈主要来自两处:
- 循环内逐次调用
rbind合并数据:每一轮循环都需要完整复制已有的全部数据再拼接新数据,2500次循环的累积开销非常高- base R内置的
read.csv读取效率偏低,批量读取大量小文件时耗时会被放大
优化方案
方案1:data.table实现(性能最优,首选)
data.table是R中处理表格数据速度最快的工具包之一,fread读取CSV的速度是read.csv的5~10倍,配合rbindlist一次性合并所有列表数据,可以避免循环拼接的性能损耗,2500个3MB的文件正常可在10秒内完成读取合并。
# 首次使用需先安装:install.packages("data.table") library(data.table) read_data <- function(ex_files, ex) { ex <- as.character(ex) # 批量读取所有文件到列表,同时新增generation列 df_list <- lapply(1:length(ex_files), function(n) { file_path <- paste0("Experiment ", ex, "/all e", ex, " gen", n, ".csv") temp <- fread(file_path) temp[, generation := n] return(temp) }) # 一次性合并所有列表元素 # 若存在部分文件列顺序/数量不一致,可将fill改为TRUE自动对齐 df <- rbindlist(df_list, use.names = TRUE, fill = FALSE) # 如果需要转回普通data.frame格式,可取消注释下行 # setDF(df) return(df) }
方案2:tidyverse生态实现(适合习惯tidy语法的用户)
使用vroom包快速读取文件,配合purrr批量操作,代码可读性更高。
# 首次使用需先安装:install.packages(c("vroom", "purrr", "dplyr")) library(vroom) library(purrr) library(dplyr) read_data <- function(ex_files, ex) { ex <- as.character(ex) df_list <- map(1:length(ex_files), function(n) { file_path <- paste0("Experiment ", ex, "/all e", ex, " gen", n, ".csv") vroom(file_path, show_col_types = FALSE) %>% mutate(generation = n) }) df <- bind_rows(df_list) return(df) }
可选并行提速
如果设备CPU核心数充足,可以把批量读取的循环替换为并行版本,进一步降低耗时,以data.table方案为例,Windows下并行代码参考:
library(data.table) library(parallel) read_data <- function(ex_files, ex, cores = detectCores() - 1) { ex <- as.character(ex) cl <- makeCluster(cores) clusterExport(cl, c("ex", "fread"), envir = environment()) df_list <- parLapply(cl, 1:length(ex_files), function(n) { file_path <- paste0("Experiment ", ex, "/all e", ex, " gen", n, ".csv") temp <- fread(file_path) temp[, generation := n] return(temp) }) stopCluster(cl) df <- rbindlist(df_list, use.names = TRUE, fill = FALSE) return(df) }
内容的提问来源于stack exchange,提问作者dimmerz
相关产品推荐
相关产品推荐

