shell 如何使用R data.table fread()函数读取压缩文件夹中的所有CSV文件,预处理,并在结果中添加一个原始文件名的列?

33qvvth1  于 2023-05-18  发布在  Shell
关注(0)|答案(2)|浏览(216)

我有一个压缩文件夹,里面有许多具有相同布局的CSV文件。我正在使用shell脚本进行预处理后阅读这些文件,该脚本保留了前四列。我正在使用data.tablefread()包,返回一个 Dataframe 如下:

library(data.table)
 
# Create sample CSV files and zip them in a folder
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"))

# Unzip, pre-process, and read into R with fread() 
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")

我的输出看起来不错:

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

现在,我试图添加一个列,有原始文件名,能够跟踪我的数据是来自哪里。我想要的输出应该看起来像这样:

>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脚本中添加另一个管道和awksed语句,但没有太多成功,因为我对R的了解要比shell多得多。如有任何建议,不胜感激。谢谢大家。

67up9zun

67up9zun1#

一种选择是单独读取文件(不幸的是,重复调用unzip),并允许rbindlist分配文件名列。

lapply(setNames(nm = unzip("files.zip", list = TRUE)$Name),
       function(fn) fread(cmd = paste("unzip -p -a files.zip", fn, "| cut -d, -f1-4"))) %>%
  rbindlist(idcol = "filename")
#      filename     a      b      x     y
#        <char> <int> <char> <char> <int>
#  1: file1.csv     1      A    Jan    12
#  2: file1.csv     3      B    Feb    13
#  3: file1.csv     5      C    Mar    16
#  4: file1.csv     7      D    Apr    10
#  5: file1.csv     9      E    May    10
#  6: file1.csv    11      F    Jun    11
#  7: file1.csv    13      G    Jul    14
#  8: file1.csv    15      H    Aug    14
#  9: file2.csv     1      I    Mar    13
# 10: file2.csv     5      J    Apr    12
# ---                                    
# 15: file2.csv    25      O    Sep    14
# 16: file2.csv    29      P    Oct    19
# 17: file3.csv     1      Q    May    15
# 18: file3.csv     2      R    Jun    15
# 19: file3.csv     3      S    Jul    11
# 20: file3.csv     4      T    Aug    14
# 21: file3.csv     5      U    Sep    20
# 22: file3.csv     6      V    Oct    18
# 23: file3.csv     7      W    Nov    18
# 24: file3.csv     8      X    Dec    13

这种方法的一个好处是它不会破坏ay列的int质量(在您的例子中将是character)。

3xiyfsfu

3xiyfsfu2#

我用lapplytransform得到了你想要的输出。我把文件名放在一个向量中,以便以后使用。在fread函数中使用unzip函数,您可以在zip文件中读取文件。transform的第一部分用于从zip阅读当前文件,然后第二部分用于添加具有文件名的列。

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

df1 <- do.call(bind_rows, lapply(csvFiles, function(X) 
    transform(fread(unzip("files.zip", X), 
                sep = ",", 
                header = TRUE, 
                stringsAsFactors = FALSE, 
                fill = TRUE,
                select = c(1,2,3,4)), 
          filename = X)))

View(df1)

相关问题