r- 从 zip 读取并与数据框列中的值匹配

r- Reading from zip and matching with values from dataframe column

我试图通过读取两个数据集来制作一个数据帧,但我使用的方法非常慢 - 读取和处理 600Mb 的数据可能需要长达 10 个小时。我相信一定有一种更快的方法可以做到这一点,但我想我看不出是什么似乎在减慢这个过程。以下是介绍这些步骤的可重现示例。

所需的软件包:

library(tidyverse)

第一组是 .csv 文件。可以使用以下内容重新创建示例:

info <- data.frame(identification = c("a", "b", "c", "d", "e"), attr = c(0:4))
info %>% write_csv("folder/info.csv") 

第二个是压缩文件。可以使用以下内容重新创建示例:

a <- data.frame(var = c(41:50), val = c(31:40))
a %>% write_csv("folder/file/a_df.csv")  

b <- data.frame(var = c(41:50), val = c(31:40))
b %>% write_csv("folder/file/b_df.csv")

c <- data.frame(var = c(41:50), val = c(31:40))
c %>% write_csv("folder/file/c_df.csv")

d <- data.frame(var = c(41:50), val = c(31:40))
d %>% write_csv("folder/file/d_df.csv")

e <- data.frame(var = c(41:50), val = c(31:40))
e %>% write_csv("folder/file/e_df.csv")

files2zip <- dir('folder/file/', full.names = TRUE)
zip(zipfile = 'testZip', files = files2zip)

我使用的方法如下:

 data1 <- read_csv("folder/info.csv")

read_from_zip <- function(identification) {
  fn <- paste0("folder/file/", identification, ".csv")  
  # read zip files
  zip_file <- paste0("./folder/testZip.zip")
  id_2_zip <- unzip( zip_file
                     ,files = fn)  
  df <- read_csv(id_2_zip)
  }

df <- data1 %>% group_by(identification) %>% nest() %>%
  mutate(trj = map(identification, read_from_zip)) 

df <- df %>% select(identification, trj) %>% unnest()

我猜这样的东西会起作用:

tmpdir <- tempfile()
dir.create(tmpdir)

一个方便的向量,如果你需要的话:

filesvec <- paste0(letters[1:5], '.csv')

请注意,这需要是压缩文件中列出的 "verbatim",包括任何前导目录。 (您可以使用 junkpaths=TRUE 代替 unzip()system('unzip -j ...') 来删除前导路径。)过去,我通过快速调用 unzip(zipfile, list=TRUE) 创建了这个文件名向量和 greping 输出。这样,如果您小心,那么您将 (a) 在提取文件之前始终知道文件丢失,并且 (b) 不会在 unzip() 或 non-zero return 代码中引起异常来自 system('unzip ...')。你可能会这样做:

filesvec <- unzip(zipfile, list=TRUE)
filesvec <- filesvec[ grepl("\.csv$", filesvec) ]
# some logic to ensure you have some or all of what you need

然后其中一个

unzip(zipfile, files=filesvec, exdir=tmpdir)
system(paste(c("unzip -d", shQuote(c(tempdir(), 'foo.zip', 'a.csv','b.csv')))))

从这里,您可以通过以下方式访问文件:

alldata <- sapply(file.path(tmpdir, filesvec), read.csv, simplify=FALSE)

其中列表的名字是文件名(包括前导路径?),内容应该都是data.frames.

完成后,是否清理临时文件取决于您对临时文件的强迫症程度。您的 OS 可能会 一段时间后为您清理它们。如果您对 space 很紧张或只是偏执狂,您可以使用以下方法进行清理:

ign <- sapply(file.path(tmpdir, filesvec), unlink) 
unlink(tmpdir, recursive=TRUE) # remove the temp dir we created

(你可以只使用第二个命令,但如果你使用不同的 temp-directory 方法,我想我会小心。)