2012-11-20 2 views
1

실행하는 데 오랜 시간이 걸리는 코드 조각에 대한 문제점이 있습니다.이 코드의 실행 시간을 최적화하기위한 핵심 트릭이 무엇인지 궁금합니다. 입력 data.frame은 중요하며 (140,000 개의 행), 출력 data.frame은 약 220,000 개의 행임을 인정해야합니다.중첩 된 while 루프로 다음 코드를 최적화하는 방법은 무엇입니까? 멀티 코어 옵션?

입력 data.frame의 샘플 : 루프로 연장된다

head(extremes) 
X_BusinessIDDescription  min   max   month 
ID105      2007-12-01 2008-06-01 2007-12-01 
ID206      2007-12-01 2009-07-01 2007-12-01 
ID204      2007-12-01 2008-02-01 2007-12-01 
ID785      2008-07-01 2010-08-01 2008-07-01 
ID125      2007-11-01 2008-07-01 2007-11-01 
ID107      2007-11-01 2011-06-01 2007-11-01 

data.frame. data.frame이 시작되어 구조를 가져옵니다. 이 코드는 꽤 빨리 실행 행의 소수를 들어

while (IDcounter <= IDmax){ 
    start <- extremes$min[IDcounter] 
    end <- extremes$max[IDcounter] # add three months 
    while(start <= end){ 
     output[linecounter,] <- extremes[IDcounter,] 
     output$month[linecounter] <- start 
     linecounter <- linecounter+1 
     start <- seq(start, by ="month", length=2)[2] 
    } 
    IDcounter <- IDcounter + 1 
} 

을, 그러나 그것은 그것 같이 보인다

output <- extremes[1,] 
output 
X_BusinessIDDescription  min   max   month 
ID105      2007-12-01 2008-06-01 2007-12-01 

다른 값

IDcounter <- 1 
IDmax <- nrow(extremes) 
linecounter <- 1 

내가 좋아하는 것 동안 루프 최적화하기 출력이 늘어남에 따라 속도가 느려지고 있습니다.

출력이 같은 같습니다 극단적 파일의 최소 및 최대 간격에 매달

head(output) 
X_BusinessIDDescription  min   max   month 
ID105      2007-12-01 2008-06-01 2007-12-01 
ID105      2007-12-01 2008-06-01 2008-01-01 
ID105      2007-12-01 2008-06-01 2008-02-01 
ID105      2007-12-01 2008-06-01 2008-03-01 
ID105      2007-12-01 2008-06-01 2008-04-01 
ID105      2007-12-01 2008-06-01 2008-05-01 

를 생성 한 행이다.

또한이 코드가 여러 컴퓨팅 리소스 코어를 사용할 수 있음을 알 수 있습니다. 좋습니다. 저는 이것이 실제로 최적화는 아니지만 실행 시간을 줄이는 것은 중요하다고 생각합니다. @CarlWitthoft으로

Jochem

+0

있습니까? – Jochem

+1

'for'와 'while'사이에 (중요한) 속도 차이가 없습니다. – Shahbaz

+2

루프 안에서 오브젝트를 성장시키는 추기경 범죄를 저지르고 있습니다. 전체 220k 행 data.frame을 먼저 초기화하고 부분 집합을 통해 관련 행에 결과를 삽입하십시오. –

답변

2

이미 때문에 많은 중복 데이터의 데이터 구조를 다시 생각해야 언급했다. 당신의 접근 방식에

## create all possible ranges of months 
    ranges <- mapply(function(mi, ma) {seq(from=mi, to=ma, by="month")}, mi=extremes$min, ma=extremes$max) 

    ## how many months per ID? 
    n <- unlist(lapply(ranges, length)) 

    ## create new data.frame 
    output <- data.frame(X_BusinessIDDescription=rep(extremes$X_BusinessIDDescription, n), 
         min=rep(extremes$min, n), 
         max=rep(extremes$max, n), 
         month=as.Date(unlist(ranges), origin="1970-01-01"), stringsAsFactors=FALSE) 

비교 :

은 여기 간단한 벡터화 방법을 찾을 수`for`와`while` 사이의 속도 차이가

extremes <- data.frame(X_BusinessIDDescription=c("ID105", "ID206", "ID204", "ID785", "ID125", "ID107"), 
         min=as.Date(c("2007-12-01", "2007-12-01", "2007-12-01", "2008-07-01", "2007-11-01", "2007-11-01")), 
         max=as.Date(c("2008-06-01", "2009-07-01", "2008-02-01", "2010-08-01", "2008-07-01", "2011-06-01")), 
         month=as.Date(c("2007-12-01", "2007-12-01", "2007-12-01", "2008-07-01", "2007-11-01", "2007-11-01")), 
         stringsAsFactors=FALSE) 

approachWhile <- function(extremes) { 
    output <- data.frame(X_BusinessIDDescription=NA, min=as.Date("1970-01-01"), max=as.Date("1970-01-01"), month=as.Date("1970-01-01"), stringsAsFactors=FALSE) 
    IDcounter <- 1 
    IDmax <- nrow(extremes) 
    linecounter <- 1 
    while (IDcounter <= IDmax){ 
    start <- extremes$min[IDcounter] 
    end <- extremes$max[IDcounter] # add three months 
    while(start <= end){ 
     output[linecounter,] <- extremes[IDcounter,] 
     output$month[linecounter] <- start 
     linecounter <- linecounter+1 
     start <- seq(start, by ="month", length=2)[2] 
    } 
    IDcounter <- IDcounter + 1 
    } 
    return(output) 
} 

approachMapply <- function(extremes) {      
    ranges <- mapply(function(mi, ma) {seq(from=mi, to=ma, by="month")}, mi=extremes$min, ma=extremes$max) 

    n <- unlist(lapply(ranges, length)) 

    output <- data.frame(X_BusinessIDDescription=rep(extremes$X_BusinessIDDescription, n), 
         min=rep(extremes$min, n), 
         max=rep(extremes$max, n), 
         month=as.Date(unlist(ranges), origin="1970-01-01"), stringsAsFactors=FALSE) 
    return(output) 
} 

identical(approachWhile(extremes), approachMapply(extremes)) ## TRUE 

library("rbenchmark") 

benchmark(approachWhile(extremes), approachMapply(extremes), order="relative") 
#      test replications elapsed relative user.self sys.self 
#2 approachMapply(extremes)   100 0.176  1.00  0.172 0.000 
#1 approachWhile(extremes)   100 6.102 34.67  6.077 0.008 
관련 문제