在R中自动读取zip文件

在R中自动读取zip文件,r,compression,R,Compression,我需要自动将csv数据文件读入zip文件 例如,我会键入: read.zip(file = "myfile.zip") 在内部,我们要做的是: 将myfile.zip解压缩到临时文件夹 使用Read.csv 如果zip文件中有多个文件,则会引发错误 我的问题是获取包含在zip文件中的文件名,以便通过read.csv命令提供该文件。有人知道怎么做吗 更新 以下是我基于@Paul answer编写的函数: read.zip <- function(zipfile, row.names=N

我需要自动将csv数据文件读入zip文件

例如,我会键入:

read.zip(file = "myfile.zip")
在内部,我们要做的是:

  • 将myfile.zip解压缩到临时文件夹
  • 使用
    Read.csv
如果zip文件中有多个文件,则会引发错误

我的问题是获取包含在zip文件中的文件名,以便通过
read.csv
命令提供该文件。有人知道怎么做吗

更新

以下是我基于@Paul answer编写的函数:

read.zip <- function(zipfile, row.names=NULL, dec=".") {
    # Create a name for the dir where we'll unzip
    zipdir <- tempfile()
    # Create the dir using that name
    dir.create(zipdir)
    # Unzip the file into the dir
    unzip(zipfile, exdir=zipdir)
    # Get the files into the dir
    files <- list.files(zipdir)
    # Throw an error if there's more than one
    if(length(files)>1) stop("More than one data file inside zip")
    # Get the full name of the file
    file <- paste(zipdir, files[1], sep="/")
    # Read the file
    read.csv(file, row.names, dec)
}
read.zip 1)停止(“zip中有多个数据文件”)
#获取文件的全名

文件您可以使用
解压
解压文件。我只是提到这一点,因为你的问题不清楚你是否知道这一点。关于阅读文件。将文件解压缩到临时目录(
?tempdir
)后,只需使用
list.files
查找转储到临时目录中的文件。在您的情况下,这只是一个文件,您需要的文件。使用
read.csv
读取它非常简单:

l = list.files(temp_path)
read.csv(l[1])

假设您的
tempdir
位置存储在
temp\u路径中

另一个使用
unz
的解决方案中:

read.zip <- function(file, ...) {
  zipFileInfo <- unzip(file, list=TRUE)
  if(nrow(zipFileInfo) > 1)
    stop("More than one data file inside zip")
  else
    read.csv(unz(file, as.character(zipFileInfo$Name)), ...)
}

read.zip如果您的系统上安装了zcat(linux、macos和cygwin就是这种情况),您还可以使用:

zipfile<-"test.zip"
myData <- read.delim(pipe(paste("zcat", zipfile)))

zipfile我在尝试从zip自动读取多个csv文件时发现了此线程。我根据更广泛的情况调整了解决方案。我还没有测试过奇怪的文件名之类的东西,但这对我来说很有用,所以我想我应该分享一下:

read.csv.zip <- function(zipfile, ...) {
# Create a name for the dir where we'll unzip
zipdir <- tempfile()
# Create the dir using that name
dir.create(zipdir)
# Unzip the file into the dir
unzip(zipfile, exdir=zipdir)
# Get a list of csv files in the dir
files <- list.files(zipdir)
files <- files[grep("\\.csv$", files)]
# Create a list of the imported csv files
csv.data <- sapply(files, function(f) {
    fp <- file.path(zipdir, f)
    return(read.csv(fp, ...))
})
return(csv.data)}

read.csv.zip以下内容对上述答案进行了细化。FUN可以是read.csv、cat或任何您喜欢的内容,前提是第一个参数将接受文件路径。例如

head(read.zip.url("http://www.cms.gov/Medicare/Coding/ICD9ProviderDiagnosticCodes/Downloads/ICD-9-CM-v32-master-descriptions.zip", filename = "CMS32_DESC_LONG_DX.txt"))

read.zip.url <- function(url, filename = NULL, FUN = readLines, ...) {
  zipfile <- tempfile()
  download.file(url = url, destfile = zipfile, quiet = TRUE)
  zipdir <- tempfile()
  dir.create(zipdir)
  unzip(zipfile, exdir = zipdir) # files="" so extract all
  files <- list.files(zipdir)
  if (is.null(filename)) {
    if (length(files) == 1) {
      filename <- files
    } else {
      stop("multiple files in zip, but no filename specified: ", paste(files, collapse = ", "))
    }
  } else { # filename specified
    stopifnot(length(filename) ==1)
    stopifnot(filename %in% files)
  }
  file <- paste(zipdir, files[1], sep="/")
  do.call(FUN, args = c(list(file.path(zipdir, filename)), list(...)))
}
head(read.zip.url(“http://www.cms.gov/Medicare/Coding/ICD9ProviderDiagnosticCodes/Downloads/ICD-9-CM-v32-master-descriptions.zip,filename=“CMS32\u DESC\u LONG\u DX.txt”))

read.zip.url我刚刚基于top read.zip编写了一个函数,它可能会帮助

read.zip <- function(zipfile, internalfile=NA, read.function=read.delim, verbose=TRUE, ...) {
    # function based on http://stackoverflow.com/questions/8986818/automate-zip-file-reading-in-r

    # check the files within zip
    unzfiles <- unzip(zipfile, list=TRUE)
    if (is.na(internalfile) || is.numeric(internalfile)) {
        internalfile <- unzfiles$Name[ifelse(is.na(internalfile),1,internalfile[1])]
    }
    # Create a name for the dir where we'll unzip
    zipdir <- tempfile()
    # Create the dir using that name
    if (verbose) catf("Directory created:",zipdir,"\n")
    dir.create(zipdir)
    # Unzip the file into the dir
    if (verbose) catf("Unzipping file:",internalfile,"...")
    unzip(zipfile, file=internalfile, exdir=zipdir)
    if (verbose) catf("Done!\n")
    # Get the full name of the file
    file <- paste(zipdir, internalfile, sep="/")
    if (verbose) 
        on.exit({ 
            catf("Done!\nRemoving temporal files:",file,".\n") 
            file.remove(file)
            file.remove(zipdir)
            }) 
    else
        on.exit({file.remove(file); file.remove(zipdir);})
    # Read the file
    if (verbose) catf("Reading File...")
    read.function(file, ...)
}

read.zip这里是我使用的一种方法,它主要基于@Corned Beef哈希映射。以下是我所做的一些更改:

  • 我的方法使用了
    data.table
    包的
    fread()
    ,它 可以很快(一般来说,如果是拉链式的,尺寸可能会很大,所以 站在这里获得很多速度!)

  • 我还调整了输出格式,使其成为命名列表,其中 列表中的每个元素都以文件命名。对我来说,这是一个巨大的挑战 非常有用的补充

  • 而不是使用正则表达式来筛选文件 通过list.files,我使用了
    list.file()
    模式
    争论

  • 最后,我通过依赖
    fread()
    和使
    模式成为
    参数,您可以为其提供类似于
    NULL的内容
    
    ,您可以使用它读取多种类型的数据文件;事实上 您可以一次读取多种类型的内容(如果.zip包含 .csv、.txt中,您想要两者,例如)。如果只有一些类型的 如果需要文件,也可以指定仅使用这些文件的模式

以下是实际功能:

read.csv.zip <- function(zipfile, pattern="\\.csv$", ...){

    # Create a name for the dir where we'll unzip
    zipdir <- tempfile()

    # Create the dir using that name
    dir.create(zipdir)

    # Unzip the file into the dir
    unzip(zipfile, exdir=zipdir)

    # Get a list of csv files in the dir
    files <- list.files(zipdir, rec=TRUE, pattern=pattern)

    # Create a list of the imported csv files
    csv.data <- sapply(files, 
        function(f){
            fp <- file.path(zipdir, f)
            dat <- fread(fp, ...)
            return(dat)
        }
    )

    # Use csv names to name list elements
    names(csv.data) <- basename(files)

    # Return data
    return(csv.data)
}

read.csv.zip另一种方法,使用data.table包中的
fread

fread.zip <- function(zipfile, ...) {
  # Function reads data from a zipped csv file
  # Uses fread from the data.table package

  ## Create the temporary directory or flush CSVs if it exists already
  if (!file.exists(tempdir())) {dir.create(tempdir())
  } else {file.remove(list.files(tempdir(), full = T, pattern = "*.csv"))
  }

  ## Unzip the file into the dir
  unzip(zipfile, exdir=tempdir())

  ## Get path to file
  file <- list.files(tempdir(), pattern = "*.csv", full.names = T)

  ## Throw an error if there's more than one
  if(length(file)>1) stop("More than one data file inside zip")

  ## Read the file
  fread(file, 
     na.strings = c(""), # read empty strings as NA
     ...
  )
}
fread.zip解压文件位置

这正是我要找的!我试图使用
system(“ls”)
,但它没有返回一个R对象,比如向量。谢谢@JoãoDaniel
system(“ls”)
不是这里的方法,但是
system(“ls”,intern=TRUE)
可能是您希望的复制品?在:;实际上,第一个链接与此无关,因为我的问题不是解压缩文件,而是获取zip中文件的名称。但是,是的,第二个显示的是
list.files
命令,我(到目前为止)还不知道该命令。@jdanielnd:您可以使用
unzip(file,list=TRUE)
来获得zip文件中的文件名,就像我在回答中使用的那样。我必须在
list.files()
中使用
recursive=TRUE
;另外,您可以简单地使用
列表中的
模式
参数,而不是在
文件的第二个定义中使用
grep()
来子集。当我写R的时候,我还是个新手,所以我不知道如何寻找像
pattern
recursive
这样的选项。我怀疑我是否会编辑我的答案,但我很乐意看到你的代码。谢谢