다른 스크립트에 (소스) R 스크립트를 포함하는 방법


108

프로젝트의 다른 스크립트에서 사용하려는 유틸리티 R 스크립트 util.R을 만들었습니다. 이 스크립트가 정의하는 함수를 다른 스크립트에서 작동 할 수 있도록하는 적절한 방법은 무엇입니까?

require아직로드되지 않은 경우에만 패키지를로드하는 함수 와 유사한 것을 찾고 있습니다. 호출 source("util.R")할 때마다 스크립트를로드하므로 호출하고 싶지 않습니다 .

R 소스 코드 구성 에서와 같이 패키지를 생성하라는 몇 가지 답변을받을 수 있다는 것을 알고 있습니다. 하지만 다른 곳에서 사용할 무언가를 만드는 것이 아니라 독립형 프로젝트 일뿐입니다.


37
저는 항상 독립형 프로젝트 용 패키지를 만듭니다. 많은 일이 아니고 혜택도 엄청납니다. 에 이동, 당신은 ... 당신이 그것을하고 싶지 알
Andrie

답변:


93

가능한 한 가지 방법이 있습니다. exists함수를 사용 하여 util.R코드 에서 고유 한 것을 확인하십시오 .

예를 들면 :

if(!exists("foo", mode="function")) source("util.R")

( mode="function"Gavin Simpson이 지적한대로 를 포함하도록 편집 됨 )


4
의 좋은 사용 exists()- 요구 사항 mode = "function"추가는 바보 - 증거 만들려면
개빈 심슨

1
exists()R 3.0.2에서 하나를 반환하는 것을 제외하고는 오류가 발생하는 것 같습니다.
Michael Schubert

올바른 사용법은`exists ( "foo")이고 대답은 편집되었습니다.
Andrie 2015

18

R은 호출을 추적하지 않고 source어디에서로드되었는지 파악할 수 없기 때문에 내장 된 그런 것은 없습니다 (패키지를 사용할 때는 해당되지 않습니다). 그러나 C .h파일 에서와 동일한 아이디어를 사용할 수 있습니다 . 즉, 전체를 다음으로 래핑합니다.

if(!exists('util_R')){
 util_R<-T

 #Code

}

그런 다음 코드 source("util.R")내에서 전화 하십시오 if.
rafalotufo 2011-06-23

1
@rafalotufo 평소처럼 소스 ( "util.R")를 사용합니다. mbq 게시물의 코드는 util.R 이동합니다. 지금 당장 util.R에있는 내용의 전체 본문을 거대한 if () 문에 넣습니다.
Keith Twombley 2013 년

10

Say util.R는 함수를 생성합니다 foo(). 이 함수가 전역 환경에서 사용 가능한지 확인하고 그렇지 않은 경우 스크립트를 소싱 할 수 있습니다.

if(identical(length(ls(pattern = "^foo$")), 0))
    source("util.R")

이름을 가진 모든 것을 찾을 수 foo있습니다. 함수를 찾고 싶다면 (@Andrie exists()가 언급했듯이) 도움이되지만 찾을 객체의 유형을 정확히 알아야합니다.

if(exists("foo", mode = "function"))
    source("util.R")

다음은 exists()실행 중입니다.

> exists("foo", mode = "function")
[1] FALSE
> foo <- function(x) x
> exists("foo", mode = "function")
[1] TRUE
> rm(foo)
> foo <- 1:10
> exists("foo", mode = "function")
[1] FALSE

이 경우 grepl(..., value=TRUE)검색어가 정규식이 아닐 수 있으므로 사용하는 것이 좋습니다. 그건 그렇고 +1.
Andrie 2011-06-23

?? grepl()인수가없는 value,하지만 난 아마에서 정규 표현식 수정해야 ls()...
개빈 심슨

미안 해요, 제 실수입니다. 나는 의미fixed=TRUE
Andrie

@Andrie-아, 알았어. 어쨌든 작동하지 않았습니다. 이것을 숙고하는 동안 끌려 갔다. exists()더 낫지 만 그 동안 그러한 답변을 게시 한 것을 확인했습니다.
Gavin Simpson

5

파일 이름과 환경 이름을 사용하는 함수를 작성하고 파일이 환경에로드되었는지 확인하고 sys.source그렇지 않은 경우 파일을 소싱하는 데 사용 합니다.

다음은 빠르고 테스트되지 않은 기능입니다 (개선을 환영합니다!).

include <- function(file, env) {
  # ensure file and env are provided
  if(missing(file) || missing(env))
    stop("'file' and 'env' must be provided")
  # ensure env is character
  if(!is.character(file) || !is.character(env))
    stop("'file' and 'env' must be a character")

  # see if env is attached to the search path
  if(env %in% search()) {
    ENV <- get(env)
    files <- get(".files",ENV)
    # if the file hasn't been loaded
    if(!(file %in% files)) {
      sys.source(file, ENV)                        # load the file
      assign(".files", c(file, files), envir=ENV)  # set the flag
    }
  } else {
    ENV <- attach(NULL, name=env)      # create/attach new environment
    sys.source(file, ENV)              # load the file
    assign(".files", file, envir=ENV)  # set the flag
  }
}

5

여기 내가 작성한 함수가 있습니다. base::source라는 전역 환경 목록에 소스 파일 목록을 저장하는 함수를 래핑합니다 sourced. 소스 .force=TRUE호출에 인수를 제공하는 경우에만 파일 을 리소스합니다. 인수 서명은 그렇지 않으면 실제와 동일 source()하므로 이것을 사용하기 위해 스크립트를 다시 작성할 필요가 없습니다.

warning("overriding source with my own function FYI")
source <- function(path, .force=FALSE, ...) {
  library(tools)
  path <- tryCatch(normalizePath(path), error=function(e) path)
  m<-md5sum(path)

  go<-TRUE
  if (!is.vector(.GlobalEnv$sourced)) {
    .GlobalEnv$sourced <- list()
  }
  if(! is.null(.GlobalEnv$sourced[[path]])) {
    if(m == .GlobalEnv$sourced[[path]]) {
      message(sprintf("Not re-sourcing %s. Override with:\n  source('%s', .force=TRUE)", path, path))
      go<-FALSE
    }
    else {
      message(sprintf('re-sourcing %s as it has changed from: %s to: %s', path, .GlobalEnv$sourced[[path]], m))
      go<-TRUE
    }
  } 
  if(.force) {
    go<-TRUE
    message("  ...forcing.")
  }
  if(go) {
    message(sprintf("sourcing %s", path))
    .GlobalEnv$sourced[path] <- m
    base::source(path, ...)
  }
}

꽤 수다 스럽기 때문에 (에 대한 많은 전화 message()) 관심이 있다면 그 라인을 제거 할 수 있습니다. 베테랑 R 사용자의 조언을 주시면 감사하겠습니다. 저는 R을 처음 접했습니다.


0

내 코드가있는 전체 주소를 사용하여 문제를 해결했습니다. 이전 :

if(!exists("foo", mode="function")) source("utils.r")

후:

if(!exists("foo", mode="function")) source("C:/tests/utils.r")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.