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

如何用R data.table fread读取压缩文件夹CSV并添加原文件名列

问题描述

我有一个包含多个结构相同CSV文件的压缩文件夹,目前通过shell脚本预处理保留前4列,再用data.table包的fread()函数读取后合并为一个数据框。现有代码如下:

library(data.table)
library(dplyr)

# 创建示例CSV文件并压缩
df1 <- data.frame(a = seq(1,16,by=2), b = LETTERS[1:8], x= month.abb[1:8], y = sample(10:20,8, replace = TRUE), z=letters[1:8])
df2 <- data.frame(a = seq(1,32,by=4), b = LETTERS[9:16], x= month.abb[3:10], y = sample(10:20,8, replace = TRUE), z=letters[9:16])
df3 <- data.frame(a = seq(1,8,by=1), b = LETTERS[17:24], x= month.abb[5:12], y = sample(10:20,8, replace = TRUE), z=letters[17:24])

write.csv(df1, "file1.csv", row.names=FALSE)
write.csv(df2, "file2.csv", row.names=FALSE)
write.csv(df3, "file3.csv", row.names=FALSE)

zip("files.zip", c("file1.csv", "file2.csv", "file3.csv"))

# 解压、预处理并读取到R中
fread_files <-
  fread(
    cmd = "unzip -p -a files.zip | cut -d ',' -f 1-4",
    sep = ",",
    header = TRUE,
    stringsAsFactors = FALSE,
    fill = TRUE) %>%
  as.data.frame() %>%
  filter(a != "a")

当前输出已满足预处理要求,但缺少原文件名列,无法追踪数据来源。尝试在shell脚本中添加awk或sed语句未成功,需要可行方案,期望输出包含filename列区分各文件数据:

> fread_files

    a b   x  y filename
1   1 A Jan 14 file1.csv
2   3 B Feb 17 file1.csv
3   5 C Mar 16 file1.csv
4   7 D Apr 12 file1.csv
5   9 E May 18 file1.csv
6  11 F Jun 11 file1.csv
7  13 G Jul 17 file1.csv
8  15 H Aug 12 file1.csv
9   1 I Mar 13 file2.csv
10  5 J Apr 17 file2.csv
11  9 K May 20 file2.csv
12 13 L Jun 15 file2.csv
13 17 M Jul 12 file2.csv
14 21 N Aug 16 file2.csv
15 25 O Sep 16 file2.csv
16 29 P Oct 18 file2.csv
17  1 Q May 20 file3.csv
18  2 R Jun 15 file3.csv
19  3 S Jul 18 file3.csv
20  4 T Aug 15 file3.csv
21  5 U Sep 17 file3.csv
22  6 V Oct 16 file3.csv
23  7 W Nov 11 file3.csv
24  8 X Dec 10 file3.csv
解决方案

方法一:修改Shell命令,通过awk添加文件名

核心思路是逐个处理压缩包中的每个CSV文件,用awk给表头追加filename列,给数据行追加对应文件名,再合并输出。直接修改fread的cmd参数即可:

fread_files <-
  fread(
    cmd = "unzip -l files.zip | grep '\\.csv$' | awk '{print $4}' | while read file; do unzip -p -a files.zip \"$file\" | cut -d ',' -f 1-4 | awk -v fn=\"$file\" 'NR==1{print $0,\",filename\"} NR>1{print $0,\",\"fn}'; done",
    sep = ",",
    header = TRUE,
    stringsAsFactors = FALSE,
    fill = TRUE) %>%
  as.data.frame()

命令拆解:

  1. unzip -l files.zip | grep '\.csv$' | awk '{print $4}':提取压缩包内所有CSV文件名
  2. while read file; do ... done:循环遍历每个CSV文件
  3. unzip -p -a files.zip "$file" | cut -d ',' -f 1-4:解压单个文件并保留前4列
  4. awk -v fn="$file" 'NR==1{print $0,",filename"} NR>1{print $0,","fn}':给表头添加filename列,给每行数据追加当前文件名

方法二:纯R代码实现(无需复杂Shell命令)

如果不熟悉Shell语法,可先解压所有文件,再逐个读取并添加文件名后合并,逻辑更直观:

library(data.table)
library(dplyr)

# 创建临时目录存放解压后的文件
temp_dir <- tempdir()
unzip("files.zip", exdir = temp_dir)

# 获取所有CSV文件的路径和文件名
csv_files <- list.files(temp_dir, pattern = "\\.csv$", full.names = TRUE)
csv_names <- basename(csv_files)

# 逐个读取文件、保留前4列、添加文件名后合并
fread_files <- lapply(seq_along(csv_files), function(i) {
  fread(csv_files[i], sep = ",", header = TRUE, stringsAsFactors = FALSE) %>%
    select(1:4) %>%
    mutate(filename = csv_names[i])
}) %>% bind_rows()

# 清理临时文件(可选操作)
unlink(temp_dir, recursive = TRUE)

这种方法兼容性更强,也更便于后续维护和调整。

内容的提问来源于stack exchange,提问作者Annabanana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:30:40