2013-09-16 9 views
0

나는 시계열 데이터를 취하여 최대 값으로 제한 한 코드를 원래 데이터와 "확장 된"데이터의 합계까지 앞으로 늘리려 고합니다. 동일합니다.loop-carrying 값이있는 루프의 속도가 빨라짐 R

저는 100k 행에서 6 시간이 걸리는 이보다 복잡한 버전이 있습니다. 이전 행에서 계산 된 값을 사용하기 때문에 이것이 벡터화 할 수 있다고 생각하지 않습니다. 맞습니까?

x <- c(0,2101,3389,3200,1640,0,0,0,0,0,0,0) 
dat <- data.frame(x=x,y=rep(0,length(x))) 
remainder <- 0 
upperlimit <- 2000 
for(i in 1:length(dat$x)){ 
    if(dat$x[i] >= upperlimit){ 
    dat$y[i] <- upperlimit 
    } else { 
    dat$y[i] <- min(remainder,upperlimit) 
    } 
    remainder <- remainder + dat$x[i] - dat$y[i] 
} 
dat 

난 당신이 ifelse을 사용할 수 이해하지만 cumsum가 나머지를 이월하는 데 사용할 수 있다고 생각하지 않습니다 - apply은 도움이되지 않습니다 내가 아는 한. Rcpp에 의지해야합니까? 대단히 감사합니다.

+2

'upperlimit'은 절대 변경되지 않으므로,'dat $ x> = upperlimit'를 먼저 계산하면 성능이 크게 향상됩니다. –

+1

일반적인 조언 : data.frame 하위 설정이 느립니다. 루프의 벡터를 사용하여 결과를 마지막에 data.frame에 결합하십시오. – Roland

답변

0

내가 나서서 Rcpp이 구현하고 R 기능에 일부 조정을했다 :

require(Rcpp);require(microbenchmark);require(ggplot2); 

limitstretchR <- function(upperlimit,original) { 
    remainder <- 0 
    out <- vector(length=length(original)) 
    for(i in 1:length(original)){ 
    if(original[i] >= upperlimit){ 
     out[i] <- upperlimit 
    } else { 
     out[i] <- min(remainder,upperlimit) 
    } 
    remainder <- remainder + original[i] - out[i] 
    } 
    out 
} 

Rcpp 기능 :

cppFunction(' 
    NumericVector limitstretchC(double upperlimit, NumericVector original) { 
    int n = original.size(); 
    double remainder = 0.0; 
    NumericVector out(n); 
    for(int i = 0; i < n; ++i) { 
     if (original[i] >= upperlimit) { 
      out[i] = upperlimit; 
     } else { 
      out[i] = std::min<double>(remainder,upperlimit); 
     } 
     remainder = remainder + original[i] - out[i]; 
    } 
    return out; 
    } 
') 

테스트 그들 :

x <- c(0,2101,3389,3200,1640,0,0,0,0,0,0,0) 
original <- rep(x,20000) 
upperlimit <- 2000 
system.time(limitstretchR(upperlimit,original)) 
system.time(limitstretchC(upperlimit,original)) 

그 80.655와 0.001 초를 되찾았다. 광적으로. 네이티브 R은 이것에 상당히 나쁜 것입니다. 그러나 microbenchmark (작은 벡터 사용)을 실행하고 혼란스러운 결과를 얻었습니다.

res <- microbenchmark(list= 
    list(limitstretchR=limitstretchR(upperlimit,rep(x,10000)), 
    limitstretchC=limitstretchC(upperlimit,rep(x,10000))), 
     times=110, 
     control=list(order="random",warmup=10)) 
print(qplot(y=time, data=res, colour=expr) + scale_y_log10()) 
boxplot(res) 
print(res) 

실행하려면 두 기능 모두 거의 동일한 결과가 나타납니다. 이것은 처음으로 microbenchmark, 어떤 팁을 사용하고 있습니까?

+0

그 뒤를 따라,'data.frame'을 사용한 원래 버전이 마침내 끝났습니다. 그것은 1317.996 초 걸렸다. – ideamotor

관련 문제