首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >加速R中的循环操作

加速R中的循环操作
EN

Stack Overflow用户
提问于 2010-05-26 05:55:37
回答 6查看 98.6K关注 0票数 201

我在R中遇到了一个很大的性能问题。我写了一个遍历data.frame对象的函数。它只是向data.frame添加了一个新列,并累积了一些内容。(操作简单)。data.frame大约有850K行。我的电脑还在工作(大约10小时),我对运行时间一无所知。

代码语言:javascript
复制
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)
}

有什么想法可以加速这个操作吗?

EN

回答 6

Stack Overflow用户

发布于 2011-06-28 14:55:05

如果你使用的是for循环,你很可能会把R当作C、Java或其他东西来编码。经过适当向量化的R代码速度非常快。

以这两个简单的代码为例,按顺序生成一个包含10,000个整数的列表:

第一个代码示例是如何使用传统的编码范例编写循环。需要28秒才能完成

代码语言:javascript
复制
system.time({
    a <- NULL
    for(i in 1:1e5)a[i] <- i
})
   user  system elapsed 
  28.36    0.07   28.61 

您可以通过预先分配内存的简单操作获得近100倍的性能提升:

代码语言:javascript
复制
system.time({
    a <- rep(1, 1e5)
    for(i in 1:1e5)a[i] <- i
})

   user  system elapsed 
   0.30    0.00    0.29 

但是使用基本的R向量操作,使用冒号运算符:,这个操作几乎是瞬间的:

代码语言:javascript
复制
system.time(a <- 1:1e5)

   user  system elapsed 
      0       0       0 
票数 37
EN

Stack Overflow用户

发布于 2010-05-26 06:15:28

这可以通过使用索引或嵌套的ifelse()语句跳过循环来更快地完成。

代码语言:javascript
复制
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."
票数 17
EN

Stack Overflow用户

发布于 2016-08-03 11:37:48

我不喜欢重写代码...当然,ifelse和lapply是更好的选择,但有时很难使其适合。

我经常像使用df$var[i]这样的列表一样使用data.frames

下面是一个虚构的例子:

代码语言:javascript
复制
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版本:

代码语言:javascript
复制
   user  system elapsed 
   0.53    0.00    0.53

列表版本:

代码语言:javascript
复制
   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'

代码语言:javascript
复制
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)
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2908822

复制
相关文章

相似问题

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