【问题标题】:Extracting one text files from multiple zip archives in R从 R 中的多个 zip 存档中提取一个文本文件
【发布时间】:2016-09-16 17:40:47
【问题描述】:

我正在尝试从位于一个文件夹中的每个 zip 文件中提取一个文本文件。然后我想将这些文本文件合并到一个数据框中。

该文件夹有多个 Zip 文件:

pf_0915.zip
pf_0914.zip
pf_0913.zip
.....

这些 zip 文件中包含多个文本文件。我只对名为 abc.txt 的文件感兴趣。这是一个没有标题的固定宽度格式文件。我已经使用 read_fwd 为这个文件设置了读取。由于所有提取的文本文件都具有相同的名称,因此最好根据存档名称重命名它们。即 pf_0915.zip 中的 abc.txt 可以称为 abc_0915.txt。全部读取后,应将它们组合成一个名为 abcCombined.txt 的大文件。

或者在读取每个新的 abc.txt 文件时,我们可以将其添加到 abcCombined.txt。

我尝试了各种版本的 unzip() 和 unz(),但没有取得多大成功。这是在没有遍历所有 zip 文件的情况下完成的。最后,这个目录包含许多 zip 文件,有没有办法通过像 grep 这样的模式匹配来读取其中的一些文件。例如,我有兴趣只阅读 9 月的文件,那些 .._09...txt。

任何提示将不胜感激。

【问题讨论】:

  • 你能分享一个示例代码来看看你尝试了什么吗?

标签: r zip text-files extract


【解决方案1】:

以下内容:

  1. 在目录中创建文件向量
  2. 使用list 参数到unzip() 来查看内容的元数据
  3. 构建正则表达式以仅查找目标文件(如果您的用例泛化为更广泛的模式,我会这样做)
  4. 测试是否有任何文件符合您的条件
  5. 仅将这些文件保存到合成向量中
  6. 迭代该向量并
    • 仅将目标文件提取到临时目录中
    • 将其读入data.frame
    • 最终将单个data.frames 绑定为一个大合一

您可以根据需要写出合并后的data.frame

library(purrr)

target_dir <- "so"
extract_file <- "abc.txt"

list.files(target_dir, full.names=TRUE) %>% 
  keep(~any(grepl(sprintf("^%s$", extract_file), unzip(., list=TRUE)$Name))) %>% 
  map_df(function(x) {
    td <- tempdir()
    read.fwf(unzip(x, extract_file, exdir=td), widths=c(4,1,4,2))
  }) -> combined_df

下面的版本只是扩展了上面的一些快捷键:

only_files_with_this_name <- function(zip_path, name) {
  zip_contents <- unzip(zip_path, list=TRUE)
  look_for <- sprintf("^%s$", name)
  any(grepl(look_for, zip_contents$Name))
}

list.files(target_dir, full.names=TRUE) %>% 
  keep(only_files_with_this_name, name=extract_file)) %>% 
  map_df(function(x) {
    td <- tempdir()
    file_in_zip <- unzip(x, extract_file, exdir=td)
    read.fwf(file_in_zip, widths=c(4,1,4,2))
    unlink(file_in_zip)
  }) -> combined_df

【讨论】:

  • 按广告宣传。惊人的节省时间。从 15 个大型 zip 文件中提取 15 个固定宽度的文本文件,然后在不到 10 秒的时间内进行合并和清理,从而产生一个干净的 250 万行数据帧 - 是的!您能解释一下代码的 keep(... 行中发生了什么吗?再次感谢。
  • 那是 #3、#4 和 #5。 unzip() 返回 zip 存档中的文件列表,其中包含几列 infio。 $Name 仅检索文件名。这将传递给grepl(),它会搜索完全匹配的内容(如果需要,您可以调整正则表达式以使其更宽松)。如果grepl() 的任何结果是TRUEany() 将返回单个TRUEkeep() 只保留 TRUE 的那些。
  • 谢谢。我试图添加一个额外的过滤器以仅保留某些 zip 文件,在这种情况下,那些名称中包含“_09”的文件。我试图用 keep(~any(grepl("_09", list.files(target_dir, full.names=TRUE)))) 替换第一行,但我收到一个错误,提示缺少参数“.p”,与没有默认值。
【解决方案2】:

由于我的声誉低,无法发表评论,所以虽然这是部分答案:

如果您知道各种 zip 中的文件名,则获取该文件的语法如下所示:

my_data<-read.csv(unz("pf_0915.zip","abc.txt"))

这显然是 csv 的代码,不是固定宽度的文本,但如果你已经设置好了,它会是这样的

my_data<-read_fwd(unz("pf_0915.zip","abc.txt") ... ) 

所有其他参数都在 ...

如果您有很多 zip,您可以循环执行此操作,并将它们累积在数据框、数据表中,无论您的船漂浮的任何结构......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多