2016-09-22 6 views
3

내가하는 POSIXct 일 소요 아주 간단한 기능을 가지고 올해를 추출, 나는()는에이 기능을 수행하는 sapply 사용하려고하면 날짜가 6 월 1 일날짜 벡터에서 sapply 사용 : 매우 느립니다. 왜?

library(lubridate) 
DetermineWaterYear <- function(date, 
           return.interval=FALSE){ 
    wy <- year(date) + ifelse(month(date)>=6, 0, -1) 
    if(return.interval==FALSE){ 
    return(wy) 
    } else { 
    interval <- interval(ymd(cat(wy),'06-01', sep=''), ymd(cat(wy+1),'05-31', sep='')) 
    return(interval) 
    } 
} 

전의 경우는 1을 빼는 ~ 190k 날짜의 벡터, 그것은 걸립니다. 날짜의 벡터가 길어지면,

tempdates <- rep(ymd('1956-01-01'), 190000) 


index <- seq(10000,190000,10000) 
for(i in 1:length(index)){ 
    times[i] <- system.time(sapply(tempdates[1:index[i]], DetermineWaterYear))[3] 
} 

미친 것입니다 :

sapply(temp$date, DetermineWaterYear) 

또한, 나는 다음과 같은 코드를 사용하여, 190,000에 길이 만에서 벡터의 부분 집합에 sapply을 수행 클럭 , 레코드 당 처리 시간은 엄청나게 증가합니다 ... 190k 날짜를 처리하는 데 필요한 시간은 10k 날짜에 필요한 시간의 238x입니다. 나는 충분한 기억을 가지고있다.

Plot of # of records vs. processing time

은 왜 그렇게 천천히 행동입니까? 어떻게 최적화 할 수 있습니까?

+1

이 뭔가 무거운 기계의 엄청 많이 보인다 ''ifelse'' 문을 사용하여 날짜의 문자 표현에 대해 (아마 거의 즉각적으로) 수행 될 수 있습니다 (여러분의 날짜는 모두 깨끗하고 멋지게 형식화 된 날짜라고 가정). – joran

+1

왜 사프리를 사용합니까? 체크하지 않았지만 함수가 벡터화 된 것으로 보입니다. – Roland

+0

@Roland Doh, 벡터화되었으므로, 결과를 얻으려면 DetermineWaterYear (temp $ dates)를 수행하면됩니다. 아직도 호기심이 많아서 왜 사프리가 그렇게 많이 습격했는지. – user278411

답변

0

주석에서 지적한 것처럼 날짜의 벡터를 함수에 직접 전달하는 것이 훨씬 빠릅니다. 또한 ifelse에는 1 톤의 오버 헤드가 있으므로 ifelse(month(date)>=6, 0, -1)floor((x/5.6) - (x^2)*0.001) - 1L으로 대체하는 것이 훨씬 빠릅니다. 여기

DetermineWaterYearNew <- function(date, return.interval=FALSE){ 
    x <- month(date) 
    wy <- year(date) + floor((x/5.6) - (x^2)*0.001) - 1L 
    if(return.interval==FALSE){ 
     return(wy) 
    } else { 
     interval <- interval(ymd(cat(wy),'06-01', sep=''), ymd(cat(wy+1),'05-31', sep='')) 
     return(interval) 
    } 
} 

몇 가지 벤치 마크입니다 만 날짜의 전체 영역에 벡터화 솔루션을 비교

microbenchmark(NewVectorized=DetermineWaterYearNew(tempdates[1:1000]), 
       OldVectorized=DetermineWaterYear(tempdates[1:1000]), 
       NonVectorized=sapply(tempdates[1:1000],DetermineWaterYear)) 
Unit: microseconds 
     expr  min   lq  mean  median   uq  max neval 
NewVectorized 341.954 364.1215 418.7311 395.7300 460.7955 602.627 100 
OldVectorized 417.077 437.3970 496.0585 462.8485 545.1555 802.954 100 
NonVectorized 42601.719 45148.3070 46452.6843 45902.4100 47341.2415 62898.476 100 

우리는이 :

microbenchmark(NewVectorized=DetermineWaterYearNew(tempdates[1:190000]), 
       OldVectorized=DetermineWaterYear(tempdates[1:190000])) 
Unit: milliseconds 
     expr  min  lq  mean median  uq  max neval 
NewVectorized 26.30660 27.26575 28.97715 27.84169 29.19391 102.1697 100 
OldVectorized 38.98637 40.78153 44.07461 42.55287 43.77947 114.9616 100