首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何加速rbind?

如何加速rbind?
EN

Stack Overflow用户
提问于 2013-10-31 10:56:20
回答 3查看 17.9K关注 0票数 21

我应该从MS-SQL服务器上下载一个表。

行数大于600万。服务器不能一次返回全部数据。

因此,我编写了一段一次下载10,000行的代码。而且,它在循环中绑定行。

假设getData()函数一次返回一个包含10000行的数据帧。(伪代码)

代码语言:javascript
复制
for(i in 1:600)
{
    tempValue <- getData()
    wannagetValue <- rbind(wannagetValue,tempValue)
    print(i)
}

问题是,随着时间的推移,它变得越来越慢。

我认为这样使用rbind不是一个好主意。

任何建议都会很有帮助。提前谢谢你。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-31 11:52:25

这里有几个我确信可以更好的选择:

代码语言:javascript
复制
library(data.table)
library(microbenchmark)

#function to generate your data
getData <- function(){
  data.frame(x=rnorm(10000),y=rnorm(10000),z=rnorm(10000))
}

#using data table's rbindlist each iteration
fDT1 <- function(n){
  dat <- getData()
  for(i in 1:n){
    dat <- rbindlist(list(dat,getData()))
  }
  return(data.frame(dat))
}

#using data table's rbindlist all at once
fDT2 <- function(n){
  return(data.frame(rbindlist(lapply(1:n,function(x) getData()))))
}

#pre-allocating a data frame
fPre <- function(n){
  dat <- data.frame(x=rep(0,n*10000),y=rep(0,n*10000),z=rep(0,n*10000))
  j <- 1
  for(i in 1:n){
    dat[j:(j+10000-1),] <- getData()
    j <- j + 10000
  }
  return(dat)
}

#standard do.call rbind
f2 <- function(n){
  return(do.call(rbind,lapply(1:n,function(x) getData())))
}

#current approach
f <- function(n){
  dat <- getData()
  for(i in 1:n){
    dat <- rbind(dat,getData())
  }
  return(dat)
}

正如你所看到的,使用data.tablerbindlist()比使用base R的rbind()有很大的改进,而且一次添加所有行而不是迭代有一个很大的好处,但是如果有内存问题,这可能是不可能的。你也可能注意到,随着数据大小的增加,速度的提高不是线性的。

代码语言:javascript
复制
 > microbenchmark(fDT2(5),fDT1(5),fPre(5),f2(5),f(5),
+                fDT2(25),fDT1(25),fPre(25),f2(25),f(25),
+                fDT2(75),fDT1(75),fPre(75),f2(75),f(75),
+                times=10)
Unit: milliseconds
     expr        min         lq     median         uq         max neval
  fDT2(5)   18.31207   18.63969   24.09943   25.45590    72.01725    10
  fDT1(5)   27.65459   29.25147   36.34158   77.79446    88.82556    10
  fPre(5)   34.96257   39.39723   41.24445   43.30319    68.75897    10
    f2(5)   30.85883   33.00292   36.29100   43.53619    93.15869    10
     f(5)   87.40869   97.97500  134.50600  138.65354   147.67676    10
 fDT2(25)   89.42274   99.39819  103.90944  146.44160   156.01653    10
 fDT1(25)  224.65745  229.78129  261.52388  280.85499   300.93488    10
 fPre(25)  371.12569  412.79876  431.80571  485.37727  1046.96923    10
   f2(25)  221.03669  252.08998  265.17357  271.82414   281.47096    10
    f(25) 1446.32145 1481.01998 1491.59203 1634.99936  1849.00590    10
 fDT2(75)  326.66743  334.15669  367.83848  467.85480   520.27142    10
 fDT1(75) 1749.83842 1882.27091 2066.95241 2278.55589  2419.07205    10
 fPre(75) 3701.16220 3968.64643 4162.70585 4234.39716  4356.09462    10
   f2(75) 1174.47546 1183.98860 1314.64585 1421.09483  1537.42903    10
    f(75) 9139.36935 9349.24412 9510.90888 9977.24621 10861.51206    10
票数 35
EN

Stack Overflow用户

发布于 2013-10-31 13:53:17

如上所述,默认情况下,R将其所有对象存储在RAM中,因此对于如此大量的数据,您将遇到一些问题。

我想补充两件事: 1)一般来说,如果您不想使用data.table,您可以使用Hadley的plyr包中的rbind.fill函数,这也是相当快的。永远不要像上面那样使用rbind,在“for”循环中,单独追加每一行。它强制R在您每次追加一行时复制数据框对象,这是很慢的。

2)要使用R处理大于内存的数据,请查看http://cran.r-project.org/web/views/HighPerformanceComputing.html上的“Large memory out-memory data”一节,也许bigmemory包就是您需要的。

票数 5
EN

Stack Overflow用户

发布于 2017-07-04 14:29:11

也许你可以执行SELECT COUNT(*) FROM table_name WHERE ...,然后为你的数据帧预先分配空间。

实际上,我不认为每10k行查询您的数据库是一个好主意。尝试通过将数据导出到本地磁盘并从本地磁盘读取数据来避免这种情况。这也会提高速度。存储很便宜,但网络带宽和内存却不便宜。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19697700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档