无需Pandas:400个列名不同的大CSV文件合并方案(Python/R)
Python 实现方法
文件太大没法用Pandas?直接用Python内置的csv模块逐行处理就行,完全不占内存:
思路
- 只在输出文件开头写一次统一的表头
id,mean - 每个输入文件跳过自己的原始表头,按列位置取第1列(id)和第2列(不管原来叫啥,都当mean)
- 读一行写一行,根本不用把整个文件塞进内存
代码
import csv import os # 替换为你的实际路径 input_folder = "存放CSV的文件夹路径" output_path = "合并后的结果.csv" new_headers = ["id", "mean"] # 筛选文件夹内所有CSV文件 all_csvs = [f for f in os.listdir(input_folder) if f.lower().endswith(".csv")] # 打开输出文件准备写入 with open(output_path, "w", newline="", encoding="utf-8") as out_file: writer = csv.writer(out_file) writer.writerow(new_headers) # 写入统一表头 for csv_file in all_csvs: full_path = os.path.join(input_folder, csv_file) with open(full_path, "r", encoding="utf-8") as in_file: reader = csv.reader(in_file) next(reader) # 跳过原始表头 # 逐行读取,仅保留前两列写入 for row in reader: if len(row) >= 2: # 过滤空行或数据不全的行 writer.writerow([row[0], row[1]])
小提示
- 如果CSV使用制表符/分号分隔,在
csv.reader和csv.writer中添加delimiter="\t"或delimiter=";"参数 - 可额外添加逻辑跳过完全空的行
R 实现方法
R也能实现低内存的逐行处理,两种方案可选:
方案一:纯内置函数(无需额外装包)
思路
- 先将统一表头写入输出文件
- 遍历每个输入文件,跳过原始表头后拆分每行数据,仅保留前两列,拼接后追加到输出文件
代码
# 替换为你的实际路径 input_folder <- "存放CSV的文件夹路径" output_path <- "合并后的结果.csv" new_headers <- c("id", "mean") # 写入统一表头 writeLines(paste(new_headers, collapse = ","), output_path) # 获取所有CSV文件的完整路径 all_csvs <- list.files(input_folder, pattern = "\\.csv$", full.names = TRUE) for (file in all_csvs) { # 打开文件连接 con <- file(file, "r") readLines(con, n = 1) # 跳过原始表头 # 逐行读取并处理 while (length(line <- readLines(con, n = 1)) > 0) { # 拆分行数据(逗号分隔,其他分隔符修改sep参数) parts <- strsplit(line, ",", fixed = TRUE)[[1]] if (length(parts) >= 2) { new_line <- paste(parts[1], parts[2], sep = ",") writeLines(new_line, output_path, append = TRUE) } } close(con) }
方案二:用data.table(效率更高)
如果文件数量多、体积大,data.table的fread支持逐块读取,内存占用极低且速度更快:
代码
library(data.table) # 替换为你的实际路径 input_folder <- "存放CSV的文件夹路径" output_path <- "合并后的结果.csv" new_headers <- c("id", "mean") # 先写入空的表头结构 fwrite(data.table(id = character(), mean = character()), output_path, col.names = TRUE) all_csvs <- list.files(input_folder, pattern = "\\.csv$", full.names = TRUE) for (file in all_csvs) { # 跳过原始表头,仅读取前两列并赋予统一列名 chunk <- fread(file, skip = 1, select = c(1,2), col.names = new_headers, sep = ",", showProgress = FALSE) # 追加写入结果文件 fwrite(chunk, output_path, append = TRUE, col.names = FALSE) }
小提示
- 若CSV使用其他分隔符,修改
strsplit的sep或fread的sep参数即可 - 可添加
tryCatch包裹循环内代码,避免单个文件读取失败中断整个流程
内容的提问来源于stack exchange,提问作者Joman
相关产品推荐
相关产品推荐

