如何在其他脚本中包含(源)R脚本

raf*_*ufo 105 r

我已经创建了一个实用程序R脚本util.R,我想从我项目中的其他脚本中使用它.确保此脚本定义的函数可用于我的其他脚本的正确方法是什么?

我正在寻找类似于require函数的东西,它只在尚未加载的情况下加载一个包.我不想打电话,source("util.R")因为每次调用脚本都会加载脚本.

我知道我会得到一些答案,告诉我创建一个包,就像在组织R源代码中一样 :)但我不会创建一些将在其他地方使用的东西,它只是一个独立的项目.

And*_*rie 90

这是一种可能的方式.使用该exists函数检查util.R代码中的唯一内容.

例如:

if(!exists("foo", mode="function")) source("util.R")
Run Code Online (Sandbox Code Playgroud)

(编辑包括mode="function",正如Gavin Simpson指出的那样)

  • 很好地使用`exists()` - 需要`mode ="function"`添加使它变得万无一失 (4认同)

mbq*_*mbq 18

内置没有这样的东西,因为R不跟踪调用source,也无法弄清楚从哪里加载的内容(使用包时不是这种情况).然而,您可以使用与C .h文件相同的想法,即将整体包装在:

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

 #Code

}
Run Code Online (Sandbox Code Playgroud)


Rei*_*son 10

util.R产生一个功能foo().您可以检查此功能是否在全局环境中可用,如果不是,则来源脚本:

if(identical(length(ls(pattern = "^foo$")), 0))
    source("util.R")
Run Code Online (Sandbox Code Playgroud)

那会找到任何名字foo.如果你想找到一个函数,那么(如@Andrie所提到的)exists()是有帮助的,但需要确切地告诉你要查找什么类型的对象,例如

if(exists("foo", mode = "function"))
    source("util.R")
Run Code Online (Sandbox Code Playgroud)

这是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
Run Code Online (Sandbox Code Playgroud)


Jos*_*ich 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
  }
}
Run Code Online (Sandbox Code Playgroud)


Kei*_*ley 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, ...)
  }
}
Run Code Online (Sandbox Code Playgroud)

它非常健谈(很多电话message())所以如果你愿意,你可以把这些线路拿出去.任何资深R用户的建议表示赞赏; 我是R的新手