2013-08-12 3 views
3

R에서 작업 할 때 일반적으로 코드를 실행하는 동안 저장된 중간 데이터 프레임을 여러 개 만듭니다. 이렇게하면 스크립트를 다시 시작해야하거나 충돌이 발생하면 중간 데이터 프레임을 다시 계산하지 않아도됩니다. 내 코드는 보통 중간 데이터 프레임이 이미 존재하는지 확인하기 위해 이러한 추악한 if/else 검사를 많이합니다.R에서 데이터 재 계산을 피하는 방법

data <- NULL 
pathToData <- "work/data.rds" 
if(file.exists(pathToData)) { 
    # load the previously calculated data 
    data <- readRDS(pathToData) 

} else { 
    # calculate the data 
    data <- ... 
    saveRDS(data, pathToData) 
} 

더 간단하고 쉬운 방법이 있습니까? 이상적으로 이것은 코드에서 투명하게 수행 될 수 있습니다.

+0

정확히 "오프 저장하기"무엇을 의미하는지

result <- cache("foo", foo()) 

또는 더 복잡한 식/코드 블록 ... ... 나 역시 캐시를 하나의 함수 호출 할 수 있습니다 (파일을 보내거나 ...)? 단순히 작업 공간을 저장하는 것은 어떻습니까? – PascalVKooten

+0

파일 이름과 함수를 사용하여 데이터를 계산하는 함수를 정의하고 파일에서 데이터를 반환하는 함수를 정의하여이를 정리할 수 있습니다. 그렇지 않으면 함수의 결과를 파일에 저장하고 반환합니다. – Cirdec

답변

0

드류 스틴의 답변이 진짜 가깝습니다. 나는 그의 함수 정의를 eval()의 제안 된 사용과 짝을 지었다. 이것은 내가 찾고 있었던 바로 그 것이다.

cache <- function(cacheName, expr, cacheDir="work", clearCache=F) { 
    result <- NULL 

    # create the cache directory, if necessary 
    dir.create(path=cacheDir, showWarnings=FALSE) 
    cacheFile <- sprintf("%s/%s.rds", cacheDir, cacheName) 

    # has the result already been cached? 
    if(file.exists(cacheFile) && clearCache==F) { 
     result <- readRDS(cacheFile) 

    # eval the expression and cache its result 
    } else { 
     result <- eval(expr) 
     saveRDS(result, cacheFile) 
    } 

    return(result) 
} 

results <- cache("foo", { 
    f <- foo() 
    r <- f + 2 
    return(r) 
}) 
4

하나의 옵션은 추한 코드를 하나의 함수에 랩핑하고 중간 단계를 다른 함수로 래핑하는 것입니다. 이렇게하면 테스트가 쉬워지고 스크립트를 통해 함수를 사용하는 것이 재현 가능한 데이터 분석을위한 모범 사례로 간주됩니다.

calcData <- function(...) { 
    #calculate the data 
} 

lazyCalc <- function(fn, ...) { 
    if(file.exists(fn)) { 
    data <- readRDS(fn) 
    } else { 
    calcData(...) 
    return(data) 
} 
+0

이런 식으로하려고했지만 lazyCalc에 전달 된 함수의 이름을 얻어야합니다. 구현시 캐시 파일의 이름은 전달되는 함수에 관계없이 항상 "fn"이됩니다. 그것은 작동하지 않습니다. 누구든지 인수로 전달 된 함수의 이름을 얻을 수있는 방법을 알고 있습니까? –

+0

이 게시물은 아마도 도움이 될 것입니다 - 당신은'eval()'을 사용할 것입니다. http://blog.earlh.com/index.php/2009/06/eval-in-r-running-code-from-a-string/ –

+0

그래! eval()이 답입니다. –

1

한 가지 옵션은 캐싱과 함께 knitr 패키지를 사용하는 것입니다.

스크립트 및 기타 포함 된 전체 knitr 템플릿 파일을 만들고 다시 실행하지 않으려는 청크를 설정할 수 있습니다. 그런 다음 해당 청크의 코드가 다시 실행되면 두 번째 실행됩니다 변경.

또한 스크립트 파일에서 knitr의 spin 함수를 사용할 수 있습니다. 그런 다음 knitr은 특수하게 서식이 지정된 주석을보고 knitr 옵션을 설정합니다 (기타는 본질적으로 일반 스크립트 파일로 처리됩니다). spin으로 캐시 정보를 설정하지 않았지만 잘 작동 할 수 있습니다.

관련 문제