我想用vroom读取一个远程归档文件,并获得一个附加列,其中包含文件名而不是归档名.如果vroom没有本地archive\u提取步骤(如下面的示例所示),这是否可行?

非常感谢.

library(tidyverse)
library(archive)
library(vroom)

file <-  "ftp://opendata.dwd.de/climate_environment/CDC/grids_germany/daily/regnie/ra2021m.tar"

test1 <- vroom_fwf(file,  col_positions = fwf_widths(rep(4, 611)),
            col_types = , cols(.default = col_integer()),
          na = "-999", id = "filename")

test1$filename %>% unique()
#> [1] "ftp://opendata.dwd.de/climate_environment/CDC/grids_germany/daily/regnie/ra2021m.tar"

my_dir <- fs::file_temp() %>% fs::dir_create()

archive_extract(file, dir = my_dir)

test2 <- fs::dir_ls(my_dir)  %>%
  vroom_fwf(  col_positions = fwf_widths(rep(4, 611)),
              col_types = , cols(.default = col_integer()),
              na = "-999", id = "filename") 

test2$filename %>% unique()
#>   [1] ".../AppData/Local/Temp/Rtmp2TTpuI/filebfd82b6b1f6/ra210101.gz"
#>   [2] ".../AppData/Local/Temp/Rtmp2TTpuI/filebfd82b6b1f6/ra210102.gz"
#>   [3] ".../AppData/Local/Temp/Rtmp2TTpuI/filebfd82b6b1f6/ra210103.gz"
...

reprex package(v2.0.1)于2022-07-25创建

推荐答案

这就是vroom vignette人的建议:

Reading single files from multiple multi-file zip archives

如果您正在读取包含多个文件的zip文件

read_all_zip <- function(file, ...) {
  filenames <- unzip(file, list = TRUE)$Name
  vroom(purrr::map(filenames, ~ unz(file, .x)), ...)
}

根据您的用例进行调整,这会产生如下结果:

read_all_tar_remote_v1 <- function(file) {
  con <- file(file, open = "rb")
  filenames <- untar(con, list = T)
  df <- purrr::map(filenames,~ vroom_fwf(archive_read(file, file = .x, format='tar'),
                                 col_positions = fwf_widths(rep(4, 611)),
                                 col_types = , cols(.default = col_integer()),
                                 na = "-999", id = "filename", guess_max=2000))
  df
}
read_all_tar_remote_v1(file)

然而,这很慢(而且崩溃的频率比我糟糕的互联网连接要高),因为如前所述,hereuntar需要读取整个归档文件才能获得文件名.

does下载整个档案,因为untar需要阅读整个文件才能看到其中的内容.tar文件中没有主目录供untar读取;每个文件都有自己的512字节头块.您不需要将其保存到硬盘来读取目录,但这样做可能同样简单.

因此,我想,你的问题.

避免这种情况的一种方法是使用archive_read作为索引位置.

read_all_tar_remote_v2 <- function(file) {
  df <- purrr::map(1:365,~ vroom_fwf(archive_read(file, file = .x, format='tar'),
                  col_positions = fwf_widths(rep(4, 611)),
                  col_types = , cols(.default = col_integer()),
                  na = "-999", id = "filename", guess_max=2000))
df
}

然而,这并没有给出确切的文件名,但至少有一个索引允许您区分它们.这是对当前实现的唯一改进.

mylist <- read_all_tar_remote_v2(file)
mylist[[1]]$filename %>% unique
[1] "archive_read(ftp://opendata.dwd.de/climate_environment/CDC/grids_germany/daily/regnie/ra2021m.tar)[1]"

由于在读取之前您可能不知道文件的数量,因此您可能希望在函数中包含错误管理.

read_all_tar_remote_v3 <- function(file, maxfiles = 10000) {
  mylist <- list()
  for (i in 1:maxfiles) {
    print(paste('reading file', i,'/', maxfiles))
   #ERROR HANDLING
   possibleError <- tryCatch({
     mydf <- vroom_fwf(archive_read(file, file = i, format='tar'),
                                           col_positions = fwf_widths(rep(4, 611)),
                                           col_types = , cols(.default = col_integer()),
                                           na = "-999", id = "filename", guess_max=2000)
     mylist[[i]] <- mydf
     },
     error=function(e) e
   )
   
   if(inherits(possibleError, "error")){
     break
   } 
  }
   return(mylist)
}

这比你目前的方法更快还是更好?我让你决定,但我不会这么说.

我会继续提取单个文件,因为在没有完整内容的情况下读取名称似乎是tar种格式的限制.

R相关问答推荐

如果行和列名以相同的开头,将矩阵值设置为0

如何修复R码的置换部分?

通过使用str_detect对具有相似字符串的组进行分组

根据模式将一列拆分为多列,并在R中进行拆分

计算具有奇数日期的运行金额

如何使用列表中多个列表中的第一条记录创建数据框

R函数,用于生成伪随机二进制序列,其中同一数字在一行中不出现超过两次

基于R中的间隔扩展数据集行

使用R中的dist()迭代ID匹配的欧几里德距离

为什么这个表格格罗布不打印?

为R中的16组参数生成10000个样本的有效方法是什么?

SHILINY中DT列的条件着色

有没有办法通过str_Detect()或其他字符串匹配函数来连接两个长度不等的数据帧?

如何将EC50值绘制在R中的剂量-react 曲线上?

如何在内联代码中添加额外的空格(R Markdown)

如何在R中创建这些列?

根据用户输入更改标记大小和 colored颜色 (R)

带有Bootswatch Cerulean主题的shiny 仪表板中的浏览&按钮可见性问题

如何将两个用不同的运算符替换*的矩阵相乘

如何使用包含要子集的值的列表或数据框来子集多个列?