【问题标题】:How do I create a progress bar for data loading in R?如何在 R 中为数据加载创建进度条?
【发布时间】:2011-09-04 03:18:21
【问题描述】:

是否可以使用load()为加载到 R 中的数据创建进度条?

对于一个数据分析项目,大型矩阵从 .RData 文件加载到 R 中,这需要几分钟才能加载。我想要一个进度条来监控加载数据之前需要多长时间。 R 已经集成了很好的progress bar 功能,但是 load() 没有用于监控已读取数据量的挂钩。如果我不能直接使用负载,有没有间接的方法可以创建这样一个进度条?也许将 .RData 文件加载到夹头中并将它们放在一起用于 R。有人对此有任何想法或建议吗?

【问题讨论】:

  • 我不知道你是怎么做进度条的,但你有没有考虑过至少显示一个计时器?我发现正在运行的计时器运行使等待时间更快,然后我知道程序仍在响应。您可以显示类似You've been waiting 1:32 and the wait is normally ~3 minutes. Grab a coffee! 的消息
  • 前两个问题:stackoverflow.com/questions/5423760/…stackoverflow.com/q/3820402/583830 建议 txtProgressBargtkProgressBar。后者来自 RGtk2 包。这些是您要找的吗?
  • 抱歉,我错过了您已经知道 txtProgressBar 函数,并且您的问题实际上是关于加载 .Rdata 文件。
  • load 没有进度条挂钩 - R 是开源的,所以你可以通过一些编程来添加它们...

标签: file r load progress-bar binary-data


【解决方案1】:

我想出了以下解决方案,它适用于小于 2^32 - 1 字节的文件。

R 对象需要被序列化并保存到文件中,如下代码所示。

saveObj <- function(object, file.name){
    outfile <- file(file.name, "wb")
    serialize(object, outfile)
    close(outfile)
}

然后我们分块读取二进制数据,跟踪读取了多少并相应地更新进度条。

loadObj <- function(file.name){
    library(foreach)
    filesize <- file.info(file.name)$size
    chunksize <- ceiling(filesize / 100)
    pb <- txtProgressBar(min = 0, max = 100, style=3)
    infile <- file(file.name, "rb")
    data <- foreach(it = icount(100), .combine = c) %do% {
        setTxtProgressBar(pb, it)
        readBin(infile, "raw", chunksize)
    }
    close(infile)
    close(pb)
    return(unserialize(data))
}

代码可以如下运行:

> a <- 1:100000000
> saveObj(a, "temp.RData")
> b <- loadObj("temp.RData")
  |======================================================================| 100%
> all.equal(b, a)
[1] TRUE

如果我们将进度条方法与读取单个块中的文件进行基准测试,我们会发现进度条方法稍微慢一些,但还不足以担心。

> system.time(unserialize(readBin(infile, "raw", file.info("temp.RData")$size)))
   user  system elapsed
  2.710   0.340   3.062
> system.time(b <- loadObj("temp.RData"))
  |======================================================================| 100%
   user  system elapsed
  3.750   0.400   4.154

所以虽然上述方法有效,但由于文件大小的限制,我觉得它完全没用。进度条只对需要很长时间才能读入的大文件有用。

如果有人能想出比这个解决方案更好的东西,那就太好了!

【讨论】:

    【解决方案2】:

    我是否可以建议加快加载(和保存)时间,以便不需要进度条?如果读取一个矩阵“快速”,那么您可能会报告每个读取矩阵之间的进度(如果您有很多)。

    这是一些测量值。通过简单地设置compress=FALSE,加载速度加倍。但是通过编写一个简单的矩阵串行器,加载速度几乎快了 20 倍。

    x <- matrix(runif(1e7), 1e5) # Matrix with 100k rows and 100 columns
    
    system.time( save('x', file='c:/foo.bin') ) # 13.26 seconds
    system.time( load(file='c:/foo.bin') ) # 2.03 seconds
    
    system.time( save('x', file='c:/foo.bin', compress=FALSE) ) # 0.86 seconds
    system.time( load(file='c:/foo.bin') ) # 0.92 seconds
    
    system.time( saveMatrix(x, 'c:/foo.bin') ) # 0.70 seconds
    system.time( y <- loadMatrix('c:/foo.bin') ) # 0.11 seconds !!!
    identical(x,y)
    

    其中 saveMatrix/loadMatrix 定义如下。它们目前不处理 dimnames 和其他属性,但可以轻松添加。

    saveMatrix <- function(m, fileName) {
        con <- file(fileName, 'wb')
        on.exit(close(con))
        writeBin(dim(m), con)
        writeBin(typeof(m), con)
        writeBin(c(m), con)
    }
    
    loadMatrix <- function(fileName) {
        con <- file(fileName, 'rb')
        on.exit(close(con))
        d <- readBin(con, 'integer', 2)
        type <- readBin(con, 'character', 1)
        structure(readBin(con, type, prod(d)), dim=d)
    }
    

    【讨论】:

    • 我们只需要加载一个大小为几个 (3+) gigs 的矩阵。我考虑将矩阵分成几个部分,然后分别读取它们,但这是一个丑陋的解决方案,不值得仅仅为了一个进度条而复杂。
    • ...那么上面的 loadMatrix 应该会大大加快速度...你试过了吗?
    • bigmemory library 用于保存和加载非常大的数字矩阵,这也是一个很好且快速的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2020-01-12
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    • 2017-03-24
    相关资源
    最近更新 更多