我应该从MS-SQL服务器下载一个表.
行数大于600万.服务器无法一次返回整个数据.
所以,我写了一个代码,一次下载10,000行.并且,它绑定循环中的行.
假设getData()
函数一次返回一个包含10000行的数据帧.(伪代码)
for(i in 1:600)
{
tempValue <- getData()
wannagetValue <- rbind(wannagetValue,tempValue)
print(i)
}
Run Code Online (Sandbox Code Playgroud)
问题是随着时间的推移它会变慢.
我认为像这样使用rbind并不是一个好主意.
任何建议都会非常有帮助.先感谢您.
Dav*_*vid 34
以下是一些我认为可能会更好的选择:
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)
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,使用data.table
's rbindlist()
是对基础R的一个很大的改进,rbind()
并且在一次追加行而不是在交互中有很大的好处,但是如果存在内存问题则可能无法实现.您可能还会注意到,随着数据大小的增加,速度的提升远不及线性.
> 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
Run Code Online (Sandbox Code Playgroud)
正如上面所指出的,默认情况下,R 将其所有对象存储在 RAM 中,因此对于如此大量的数据,您将遇到一些问题。
我想补充两点: 1)一般来说,如果你不想使用data.table,你可以使用rbind.fill
Hadley's plyr
package中的函数,它也非常快。永远不要使用rbind
上面的方法,在“for”循环中,分别附加每一行。每次添加一行时,它都会强制 R 制作数据框对象的副本,这很慢。
2)与其中R比-RAM较大数据工作,看看在部分多内存和外的存储器中的数据在http://cran.r-project.org/web/views/HighPerformanceComputing.html,也许这个bigmemory
包是你需要的。