如何在其他脚本中包含(源)R脚本
我已经创建了一个实用程序R脚本util.R,我想从项目中的其他脚本使用它。 确保此脚本定义的函数在我的其他脚本中可用的正确方法是什么 我正在寻找类似于如何在其他脚本中包含(源)R脚本,r,R,我已经创建了一个实用程序R脚本util.R,我想从项目中的其他脚本使用它。 确保此脚本定义的函数在我的其他脚本中可用的正确方法是什么 我正在寻找类似于require函数的东西,该函数仅在尚未加载包时才加载包。我不想调用source(“util.R”),因为每次调用脚本时都会加载脚本 我知道我会得到一些答案,告诉我创建一个包,如:) 但是我并没有创建将在其他地方使用的东西,它只是一个独立的项目。比如说util.R生成一个函数foo()。您可以检查此函数在全局环境中是否可用,如果不可用,则为脚本提供
require
函数的东西,该函数仅在尚未加载包时才加载包。我不想调用source(“util.R”)
,因为每次调用脚本时都会加载脚本
我知道我会得到一些答案,告诉我创建一个包,如:)
但是我并没有创建将在其他地方使用的东西,它只是一个独立的项目。比如说
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
>存在(“foo”,mode=“function”)
[1] 假的
>foo存在(“foo”,mode=“function”)
[1] 真的
>rm(foo)
>foo存在(“foo”,mode=“function”)
[1] 假的
没有内置的功能,因为R不跟踪对源代码的调用,也无法找出从何处加载的内容(使用包时不是这种情况)。但是,您可以使用与C.h
文件相同的想法,即将整个文件包装在:
if(!exists('util_R')){
util_R<-T
#Code
}
如果(!存在('util_R')){
util\u R这里有一种可能的方法。使用exists
函数检查util.R
代码中是否存在唯一的内容
例如:
if(!exists("foo", mode="function")) source("util.R")
(如Gavin Simpson所指出的,编辑为包含mode=“function”
)您可以编写一个函数,该函数采用文件名和环境名称,检查文件是否已加载到环境中,如果未加载,则使用sys.source
来获取文件的源代码
这里有一个快速且未经测试的函数(欢迎改进!):
include这是我编写的一个函数。它包装了base::source
函数,将源文件列表存储在名为sourceed
的全局环境列表中。只有在调用源代码时提供.force=TRUE
参数,它才会重新生成文件。它的参数签名与真正的相同e> 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, ...)
}
}
警告(“用我自己的函数覆盖源代码仅供参考”)
source我使用我的代码所在的整个地址解决了我的问题:
之前:
之后:
if(!exists("foo", mode="function")) source("C:/tests/utils.r")
我一直在为独立项目创建包。这不需要做很多工作,而且好处巨大。继续,你知道你想这么做……在这种情况下,你可能需要使用grepl(…,value=TRUE)
,因为你的搜索词可能不是正则表达式。+1,顺便说一下。??grepl()
没有参数值
,但我可能应该在ls()
中修复regexp…对不起,我的错误。我的意思是fixed=TRUE
@Andrie-啊,好吧。反正它不起作用。在考虑这个问题时被拖走了。存在()
更好,但我现在看到你同时发布了这样一个答案。很好地使用了exists()
-需要mode=“function”
添加以使其成为傻瓜exists()
除了在R3.0.2中返回一个之外,似乎抛出了一个错误。正确的用法是`exists(“foo”),并且答案已编辑。然后调用source(“util.R”)
在if
代码中,对吗?@rafalotufo你会像往常一样源代码(“util.R”)。mbq帖子中的代码会进入util.R。如果有意义的话,你只需将util.R中的全部内容放入一个巨大的if()语句中。
if(!exists("foo", mode="function")) source("utils.r")
if(!exists("foo", mode="function")) source("C:/tests/utils.r")