如果R中的语句评估更快

时间:2014-01-21 02:58:32

标签: r performance if-statement

所以我想弄清楚是否有更好的方法将多个条件语句添加到R中的if子句以加快进程。下面是我编写的一些代码,它们在简单的情况下在大型数据集上运行得非常快,而在不那么简单的情况下运行速度不是很快。任何建议都非常感谢!此外,tic-toc函数位于问题的最底层,以防您想自己运行它并查看函数运行的速度。

另外,为了给出代码正在做什么的直觉,第一个块只是确定是否有任何x和y的值比其他x和y的值都大。

第二块代码正在做同样的事情,但是,它添加了任何x值实际上彼此相等的条件,然后检查哪个具有最低的y值。同样,如果任何y值彼此相等,则检查哪个值具有最低x值。

因此,在简单的情况下运行代码我有以下内容:

tic()

x = runif(10000)
y = runif(10000)

front = 1:length(x)

for(i in 1:length(x)){
    for(n in 1:length(x)){
        if((x[i]>x[n]  &  y[i]>y[n])){
            front[i] = NA
            break
        }
    }
}

toc()

正如您所看到的,我只评估x[i]>x[n] & y[i]>y[n]

的单一条件
  

TOC()       过去          1.28

并且上面的代码在1.28秒内运行。 现在,当我有三个条件要检查时运行代码我有以下内容:

tic()

x = runif(10000)
y = runif(10000)

front = 1:length(x)

for(i in 1:length(x)){
    for(n in 1:length(x)){
        if((x[i]>x[n]  &  y[i]>y[n]) | (x[i]==x[n] & y[i]!=min(y[which(x==x[i])])) | (y[i]==y[n] & x[i]!=min(x[which(y==y[i])]))){
            front[i] = NA
            break
        }
    }
}


toc()

所以你可以看到,我现在必须在if语句中检查三个条件,即

(x[i]>x[n]  &  y[i]>y[n]) | (x[i]==x[n] & y[i]!=min(y[which(x==x[i])])) | (y[i]==y[n] & x[i]!=min(x[which(y==y[i])]))
然而,这会导致R中的巨大计算负担并使代码变得更慢。

> toc()
elapsed 
  74.47

我们看到运行新改编的代码现在大大减慢到74.47秒。现在我正在寻找可以加速我的代码的替代函数调用,或者只是以“更好”的方式重写代码并不是那么慢。

如果需要,以下是tic-toc功能的代码:

tic <- function(gcFirst = TRUE, type=c("elapsed", "user.self", "sys.self"))
{
   type <- match.arg(type)
   assign(".type", type, envir=baseenv())
   if(gcFirst) gc(FALSE)
   tic <- proc.time()[type]         
   assign(".tic", tic, envir=baseenv())
   invisible(tic)
}

toc <- function()
{
   type <- get(".type", envir=baseenv())
   toc <- proc.time()[type]
   tic <- get(".tic", envir=baseenv())
   print(toc - tic)
   invisible(toc)
}

为sashkello编辑

所以我的代码现在看起来像这样:

library(mvtnorm)
#Here are the variables I will be working with 

> x
 [1] 0.53137100 0.75357474 0.87904120 0.29727488 0.00000000 0.00000000
 [7] 0.00000000 0.00000000 0.00000000 0.04059217
> y
 [1]  4.873500  3.896917  1.258215  5.776484 12.475491  5.273784 13.803158
 [8]  4.472204  2.629839  6.689242
> front
 [1] NA NA  3 NA NA NA NA NA  9 NA
> all.preds
[1] 0.596905183 0.027696850 1.005666896 0.007688514 3.900000000

    x = x[!is.na(front)]
    y = y[!is.na(front)]

    mu = c(all.preds[1],all.preds[3])
    sigma = matrix(c(all.preds[2],0,0,all.preds[4]),nrow=2)

    z = rmvnorm(10000,mu,sigma)
    z[,1] = sapply(z[,1],function(x){max(x,0)})

    points(z,col="black",pch=19,cex=.01)
    temp = 1:nrow(z)

    for(i in 1:length(temp)){
        cond1 = z[i,2]!=min(z[which(z[,1]==z[i,1]),2])
        cond2 = z[i,1]!=min(z[which(z[,2]==z[i,2]),1])
        for(n in 1:length(x)){
            if((z[i,1]>x[n]  &  z[i,2]>y[n]) | (z[i,1]==x[n] & cond1) | (z[i,2]==y[n] & cond2)){
                temp[i] = NA
                break
            }
        }
    }
    prop = sum(!is.na(temp))/length(temp)

并且cond1和cond2声明仍然花费了很长时间。有什么建议吗?

2 个答案:

答案 0 :(得分:3)

您可以在第二个循环之前放置y[i]!=min(y[which(x==x[i])])x[i]!=min(x[which(y==y[i])]),因为它们都只涉及i

for(i in 1:length(x)){
    cond1 = y[i]!=min(y[which(x==x[i])])
    cond2 = x[i]!=min(x[which(y==y[i])])
    for(n in 1:length(x)){
        if((x[i]>x[n]  &  y[i]>y[n]) | (x[i]==x[n] & cond1) | (y[i]==y[n] & cond2)){

这会显着加快速度,因为minwhich都非常慢,而且每次都在第二个循环中运行它们。

答案 1 :(得分:2)

由于您要求它,这是在cond1循环之外计算for的有效方法(您可能根本不需要):

#some data_
set.seed(42)
z <- matrix(sample(1:5, 200, TRUE), ncol=2)

#your loop
cond1 <- logical(100)

for (i in 1:100) {
cond1[i] = z[i,2]!=min(z[which(z[,1]==z[i,1]),2])
}

#alternative
library(data.table)
DT <- data.table(z)
DT[, id:=.I]

DT[, cond1:=V2!=min(V2), by=V1]

#compare results
identical(DT[, cond1], cond1)
#[1] TRUE