You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中不加载全量数据到内存,按列合并多个CSV文件

在R中增量合并大型CSV文件(不载入全量内存)

问题背景

现有一组按列拆分存储的大型CSV文件(示例为5个文件,每个文件包含原矩阵的2列),需要在不将所有文件全量载入内存的前提下,按列合并这些文件并输出完整的CSV到磁盘。

示例文件对应关系:

  • 1.csv:包含X1、X2列
  • 2.csv:包含X3、X4列
  • 3.csv:包含X5、X6列
  • 4.csv:包含X7、X8列
  • 5.csv:包含X9、X10列

解决方案

方法1:使用readr包逐行处理

readr提供高效的逐行读取接口,适合内存有限的场景:

library(readr)

# 定位文件路径并排序(保证列顺序正确)
path <- paste0(getwd(), "/example/")
file_paths <- sort(paste0(path, dir(path)))

# 初始化输出文件连接,写入合并后的表头
out_con <- file("merged_full.csv", "w")
# 收集所有文件的列名
full_header <- unlist(lapply(file_paths, function(f) names(read_csv(f, n_max = 0))))
writeLines(paste(full_header, collapse = ","), out_con)

# 逐行读取并合并写入
line_idx <- 1
repeat {
  # 读取每个文件的当前行
  current_rows <- lapply(file_paths, function(f) {
    read_csv(f, skip = line_idx, n_max = 1, col_names = FALSE)
  })
  # 所有文件都读取完毕则终止循环
  if (all(sapply(current_rows, nrow) == 0)) break
  # 合并当前行的所有列并写入
  merged_row <- do.call(cbind, current_rows)
  writeLines(paste(unlist(merged_row), collapse = ","), out_con)
  line_idx <- line_idx + 1
}
close(out_con)

方法2:使用data.table分块读取合并

data.table的fread读取效率极高,分块读取适合超大型文件:

library(data.table)

path <- paste0(getwd(), "/example/")
file_paths <- sort(paste0(path, dir(path)))

# 生成完整表头
full_header <- unlist(lapply(file_paths, function(f) names(fread(f, nrows = 0))))
# 写入表头到输出文件
fwrite(data.table(t(full_header)), "merged_full.csv", col.names = FALSE)

# 设置分块大小(根据内存情况调整,如1000/5000行)
chunk_size <- 1000
start_row <- 1

repeat {
  # 分块读取每个文件的对应行
  chunks <- lapply(file_paths, function(f) {
    fread(f, skip = start_row - 1, nrows = chunk_size)
  })
  # 所有块都为空则终止
  if (all(sapply(chunks, nrow) == 0)) break
  # 合并分块并追加写入
  merged_chunk <- do.call(cbind, chunks)
  fwrite(merged_chunk, "merged_full.csv", append = TRUE, col.names = FALSE)
  start_row <- start_row + chunk_size
}

方法3:基础R实现(无需额外包)

如果不想依赖第三方包,可使用基础R的文件连接操作:

path <- paste0(getwd(), "/example/")
file_paths <- sort(paste0(path, dir(path)))

# 打开所有文件的读取连接
file_cons <- lapply(file_paths, file, "r")
# 读取并合并表头
headers <- lapply(file_cons, readLines, n = 1)
full_header <- paste(unlist(strsplit(unlist(headers), ",")), collapse = ",")

# 初始化输出文件并写入表头
out_con <- file("merged_full.csv", "w")
writeLines(full_header, out_con)

# 逐行读取合并
repeat {
  current_lines <- lapply(file_cons, readLines, n = 1)
  # 所有文件读取完毕则终止
  if (all(sapply(current_lines, length) == 0)) break
  # 处理部分文件先读完的空行情况
  current_lines <- lapply(current_lines, function(x) if (length(x) == 0) "" else x)
  merged_line <- paste(unlist(strsplit(unlist(current_lines), ",")), collapse = ",")
  writeLines(merged_line, out_con)
}

# 关闭所有文件连接
lapply(file_cons, close)
close(out_con)

注意事项

  • 文件排序:必须保证file_paths的顺序对应原矩阵的列顺序,若文件名无规律,可根据文件内的列名排序。
  • 分块大小调整:方法2中的chunk_size可根据可用内存灵活调整,内存充足时调大以提升效率。
  • 异常处理:实际生产环境中可添加文件存在性检查、行数一致性校验等逻辑。

内容的提问来源于stack exchange,提问作者mr.T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:55:17