gpt4 book ai didi

r - 在不解压缩到磁盘的情况下读取zip文件中的RDS文件

转载 作者:行者123 更新时间:2023-12-03 17:11:32 28 4
gpt4 key购买 nike

是否有原因我无法直接从zip文件中读取RDS文件,而不必先将其解压缩到磁盘上的临时文件中?

假设这是zip文件:

saveRDS(cars, "cars.rds")
saveRDS(iris, "iris.rds")
write.csv(iris, "iris.csv")
zip("datasets.zip", c("cars.rds", "iris.rds", "iris.csv"))
file.remove("cars.rds", "iris.rds", "iris.csv")

对于csv文件,我可以像这样直接读取它:
iris2 <- read.csv(unz("datasets.zip", "iris.csv"))

但是,我不明白为什么我不能直接将 unz()readRDS()一起使用:
iris3 <- readRDS(unz("datasets.zip", "iris.rds"))

这给了我错误:
Error: unknown input format

我也想了解为什么会这样。我知道我可以执行以下操作,例如 this question:
path <- unzip("datasets.zip", "iris.rds")
iris4 <- readRDS(path)
file.remove(path)

但是,这似乎不太有效,我需要经常处理大量文件,因此I/O效率低下很重要。是否有任何解决方法来读取rds文件而不将其提取到磁盘中?

最佳答案

在我阅读readRDS()的正文之前,要跟踪它有点棘手。看来您需要做的是

  • 使用.zip打开到unz()存档及其内部文件的连接
  • 使用gzcon()
  • 将GZIP减压应用于此连接
  • 最后将这个解压缩的连接传递给readRDS()

  • 这是一个示例,用于说明在zip存档 mat中使用以下序列化矩阵 matrix.zip
    mat <- matrix(1:9, ncol = 3)
    saveRDS(mat, "matrix.rds")
    zip("matrix.zip", "matrix.rds")

    打开与 matrix.zip的连接
    con <- unz("matrix.zip", filename = "matrix.rds")

    现在,使用 gzcon()将GZIP解压缩应用于此连接
    con2 <- gzcon(con)

    最后,从连接中读取
    mat2 <- readRDS(con2)

    总的来说,我们有
    con <- unz("matrix.zip", filename = "matrix.rds")
    con2 <- gzcon(con)
    mat2 <- readRDS(con2)
    close(con2)

    这给
    > con <- unz("matrix.zip", filename = "matrix.rds")
    > con2 <- gzcon(con)
    > mat2 <- readRDS(con2)
    > close(con2)
    > mat2
    [,1] [,2] [,3]
    [1,] 1 4 7
    [2,] 2 5 8
    [3,] 3 6 9
    > all.equal(mat, mat2)
    [1] TRUE

    为什么?

    我必须在 ?readRDS中描述为什么要经历这个复杂的额外步骤:

    Compression is handled by the connection opened when file is a file name, so is only possible when file is a connection if handled by the connection. So e.g. url connections will need to be wrapped in a call to gzcon.



    如果您查看 readRDS()的内部信息,我们会看到:
    > readRDS
    function (file, refhook = NULL)
    {
    if (is.character(file)) {
    con <- gzfile(file, "rb")
    on.exit(close(con))
    }
    else if (inherits(file, "connection"))
    con <- file
    else stop("bad 'file' argument")
    .Internal(unserializeFromConn(con, refhook))
    }
    <bytecode: 0x2841998>
    <environment: namespace:base>

    如果 file是文件名的字符串,则使用 gzile()对对象进行解压缩以创建与我们要读取的 .rds的连接。请注意,如果您按需通过 file传递连接,则R绝对不会解压缩该连接。只是将 file分配给 con,然后将其传递给内部函数 unserializeFromConn。因此,将 gzcon()包裹在 unz创建的连接周围即可。

    基本上,当 unserializeFromConn从连接中读取时,它希望将其解压缩,但是只有当您将 readRDS()传递给文件名而不是连接时,解压缩才会自动发生。

    关于r - 在不解压缩到磁盘的情况下读取zip文件中的RDS文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33289973/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com