我在R中遇到了一个很大的性能问题。我写了一个遍历data.frame
对象的函数。它只是向data.frame
添加了一个新列,并累积了一些内容。(操作简单)。data.frame
大约有850K行。我的电脑还在工作(大约10小时),我对运行时间一无所知。
dayloop2 <- function(temp){
for (i in 1:nrow(temp)){
temp[i,10] <- i
if (i > 1) {
if ((temp[i,6] == temp[i-1,6]) & (temp[i,3] == temp[i-1,3])) {
temp[i,10] <- temp[i,9] + temp[i-1,10]
} else {
temp[i,10] <- temp[i,9]
}
} else {
temp[i,10] <- temp[i,9]
}
}
names(temp)[names(temp) == "V10"] <- "Kumm."
return(temp)
}
有什么想法可以加速这个操作吗?
发布于 2011-06-28 14:55:05
如果你使用的是for
循环,你很可能会把R当作C、Java或其他东西来编码。经过适当向量化的R代码速度非常快。
以这两个简单的代码为例,按顺序生成一个包含10,000个整数的列表:
第一个代码示例是如何使用传统的编码范例编写循环。需要28秒才能完成
system.time({
a <- NULL
for(i in 1:1e5)a[i] <- i
})
user system elapsed
28.36 0.07 28.61
您可以通过预先分配内存的简单操作获得近100倍的性能提升:
system.time({
a <- rep(1, 1e5)
for(i in 1:1e5)a[i] <- i
})
user system elapsed
0.30 0.00 0.29
但是使用基本的R向量操作,使用冒号运算符:
,这个操作几乎是瞬间的:
system.time(a <- 1:1e5)
user system elapsed
0 0 0
发布于 2010-05-26 06:15:28
这可以通过使用索引或嵌套的ifelse()
语句跳过循环来更快地完成。
idx <- 1:nrow(temp)
temp[,10] <- idx
idx1 <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3]))
temp[idx1,10] <- temp[idx1,9] + temp[which(idx1)-1,10]
temp[!idx1,10] <- temp[!idx1,9]
temp[1,10] <- temp[1,9]
names(temp)[names(temp) == "V10"] <- "Kumm."
发布于 2016-08-03 11:37:48
我不喜欢重写代码...当然,ifelse和lapply是更好的选择,但有时很难使其适合。
我经常像使用df$var[i]
这样的列表一样使用data.frames
下面是一个虚构的例子:
nrow=function(x){ ##required as I use nrow at times.
if(class(x)=='list') {
length(x[[names(x)[1]]])
}else{
base::nrow(x)
}
}
system.time({
d=data.frame(seq=1:10000,r=rnorm(10000))
d$foo=d$r
d$seq=1:5
mark=NA
for(i in 1:nrow(d)){
if(d$seq[i]==1) mark=d$r[i]
d$foo[i]=mark
}
})
system.time({
d=data.frame(seq=1:10000,r=rnorm(10000))
d$foo=d$r
d$seq=1:5
d=as.list(d) #become a list
mark=NA
for(i in 1:nrow(d)){
if(d$seq[i]==1) mark=d$r[i]
d$foo[i]=mark
}
d=as.data.frame(d) #revert back to data.frame
})
data.frame版本:
user system elapsed
0.53 0.00 0.53
列表版本:
user system elapsed
0.04 0.00 0.03
使用向量列表比使用data.frame快17倍。
对于为什么内部data.frames在这方面如此缓慢,有什么评论吗?有人会认为它们像列表一样运作……
要获得更快的代码,请使用class(d)='list'
代替d=as.list(d)
和class(d)='data.frame'
system.time({
d=data.frame(seq=1:10000,r=rnorm(10000))
d$foo=d$r
d$seq=1:5
class(d)='list'
mark=NA
for(i in 1:nrow(d)){
if(d$seq[i]==1) mark=d$r[i]
d$foo[i]=mark
}
class(d)='data.frame'
})
head(d)
https://stackoverflow.com/questions/2908822
复制相似问题