所以我想弄清楚是否有更好的方法将多个条件语句添加到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声明仍然花费了很长时间。有什么建议吗?
答案 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)){
这会显着加快速度,因为min
和which
都非常慢,而且每次都在第二个循环中运行它们。
答案 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