2011-05-28 73 views
22

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

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

+0

我不知道你是怎么做进度条的,但你有没有考虑过至少要显示一个计时器?我发现运行的定时器运行会让等待更快,然后我知道程序仍在响应。你可以显示一条消息,比如“你一直在等待1:32,等待通常是~3分钟。喝杯咖啡' – 2011-05-29 05:00:40

+0

前两次的问题:http://stackoverflow.com/questions/5423760/how-do-you-create-a-progress-bar-when-using-the-foreach-function-in-r/ 6170107#6170107和http://stackoverflow.com/q/3820402/583830建议'txtProgressBar'和'gtkProgressBar'。后者来自RGtk2软件包。这些是你在找什么? – jthetzel 2011-05-29 20:36:12

+0

对不起,我错过了你已经知道'txtProgressBar'函数,你的问题实际上是关于加载.Rdata文件。 – jthetzel 2011-05-29 20:40:35

回答

12

我想出了以下解决方案,这将对于文件工作尺寸小于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 

因此,虽然上述方法的工作,我觉得它是完全无用的,因为文件大小的限制。进度条仅用于需要很长时间阅读的大文件。

如果有人能想出比这个解决方案更好的东西,那将会很棒!

3

也许,这样不需要一个进度条,而不是我建议加快负载(并保存)的时间?如果读取一个矩阵是“快速”,那么您可能会报告每个读取矩阵之间的进展(如果有很多)。

这里的一些测量。通过简单地设置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定义如下。他们目前不处理暗淡名称和其他属性,但可以轻松添加。

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) 
} 
+0

我们只需要加载一个单一的矩阵,这是几个(3 +)演唱会的大小。我认为把矩阵分成几个部分,然后单独阅读,但这是一个丑陋的解决方案,不值得为进度条带来复杂性。 – Nixuz 2011-06-18 23:51:56

+0

...那么上面的loadMatrix应该可以大大加快事物的速度......你试过了吗? – Tommy 2011-06-22 17:33:57

+0

用于保存和加载非常大的数字矩阵的[bigmemory库](http://cran.r-project.org/web/packages/bigmemory/index.html),也是一个很好且快速的解决方案。 – Nixuz 2013-02-27 04:25:34