programing

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

closeapi 2023. 6. 15. 21:53
반응형

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

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

저는 그와 비슷한 것을 찾고 있습니다.require아직 로드되지 않은 경우에만 패키지를 로드하는 함수입니다.전화하기 싫어요source("util.R")호출될 때마다 스크립트가 로드되기 때문입니다.

는 R 소스 코드 정리에서처럼 패키지를 만들라는 답을 얻을 수 있다는 것을 알고 있습니다 :) 하지만 나는 다른 곳에서 사용될 무언가를 만드는 것이 아니라 단지 독립적인 프로젝트일 뿐입니다.

여기 가능한 한 가지 방법이 있습니다.사용exists당신의 고유한 것을 확인하는 기능util.R암호를

예:

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

(포함하도록 편집)mode="function"개빈 심슨이 지적했듯이)

R은 호출을 추적하지 않으므로 기본 제공되지 않습니다.source패키지를 사용할 때는 그렇지 않습니다.하지만 C와 같은 아이디어를 사용할 수 있습니다..h파일, 즉 전체를 랩으로 감습니다.

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

 #Code

}

말합니다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

파일 이름과 환경 이름을 사용하여 파일이 환경에 로드되었는지 확인하고 사용하는 기능을 작성할 수 있습니다.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
  }
}

여기 제가 쓴 기능이 있습니다.그것은 끝입니다.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이 꽤 생소합니다.

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

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

이후:

if(!exists("foo", mode="function")) source("C:/tests/utils.r")

언급URL : https://stackoverflow.com/questions/6456501/how-to-include-source-r-script-in-other-scripts

반응형