在指定环境中加载 R 包

5

我是R包开发和堆栈溢出的新手,但我在任何地方都找不到这些信息。

我正在尝试加载R包mice,但不要让它污染我的命名空间。我已经尝试过只导入我使用的函数,但没有成功。所以,我将接受在一个特定环境中加载整个软件包的解决方案:

e <- new.env()
load_package_into_environment(e, package = "mice")
eval(mice(data, m = m, maxit = max.iter, printFlag = F), envir = e)

然而,我还没有找到替换"load_package_into_environment"占位符的实际功能。如果有的话,哪个函数能够完成这个任务?

编辑:以下是我正在处理的文件和遇到的问题,以提供更多细节。

文件:DESCRIPTION

Package: bug.example2
Title: Example of Package Loading Bug
Version: 0.0.0.9000
Authors@R: person("R", "Woodbridge", email = "example@gmail.com", role = c("aut", "cre"))
Description: Creates a wrapper function for mice::mice function.
Depends:
    R (>= 3.2.3),
    data.table (>= 1.9.6)
License:
LazyData: true
Imports: mice
RoxygenNote: 5.0.1

文件: NAMSPACE (自动由Roxygen生成)


该文件是Roxygen自动生成的命名空间文件。
import(data.table)
importFrom(mice,mice)
importFrom(mice,mice.impute.logreg)
importFrom(mice,mice.impute.pmm)
importFrom(mice,mice.impute.polr)
importFrom(mice,mice.impute.polyreg)

文件: impute.R (使用mice包中的mice函数)

#' @import data.table
#' @importFrom mice mice
#' @importFrom mice mice.impute.pmm
#' @importFrom mice mice.impute.logreg
#' @importFrom mice mice.impute.polyreg
#' @importFrom mice mice.impute.polr
#' @export
impute <- function(data, m = 5, max.iter = 5){

mice_environment <- new.env()


#Impute missing data using mice function, output format is mids object
mice.out <- mice(data, m = m, maxit = max.iter, printFlag = F)

#save the m imputed data.frames as a list of data.tables
return.list <- lapply(1:m, function(x){
                                    as.data.table(complete(mice.out, x))
                                      })
names(return.list) <- paste0("imp.",1:m)
return.list
}

文件:test-impute.R(使用testthat包测试impute函数)

context("Impute missing values")
test_that("Output format is a list of lenght m and each element is a data.table",{
#Set up data
set.seed(200)
data <- iris
data$Species[runif(nrow(data)) < .1] <- NA
data$Sepal.Width[runif(nrow(data)) < .2] <- NA
setDT(data)

#Create imputed data
M <- 5
impute.output <- impute(data, m = M)

#Test output format
expect_is(impute.output, "list")
expect_equal(length(impute.output), M)
lapply(impute.output,expect_is, "data.table")
})

来自testthat的错误输出

1. Error: Output format is a list of lenght m and each element is a data.table -
The following functions were not found: mice.impute.pmm, mice.impute.polyreg
1: withCallingHandlers(eval(code, new_test_environment), error = capture_calls, message = function(c) invokeRestart("muffleMessage"))
2: eval(code, new_test_environment)
3: eval(expr, envir, enclos)
4: impute(data, m = M) at test-impute.R:12
5: mice(data, m = m, maxit = max.iter, printFlag = F) at          C:\repos\bug.example2/R/impute.R:11
6: check.method(setup, data)
7: stop(paste("The following functions were not found:", paste(fullNames[notFound], 
   collapse = ", ")))

一个包被加载到一个专用环境中。你所说的“污染”是什么意思? - nicola
importFrom 是我的第一种尝试,但我已经导入了我调用的所有函数和所有相关的依赖函数,但是当我尝试构建包时仍然会收到一条消息,指出某些这些依赖函数未找到。我认为这是 mice 构建方式的结果。 - r.woodbridge
请参阅https://dev59.com/Gpvga4cB1Zd3GeqP5a23#40830959,并阅读有关`import`包的内容,它几乎完全符合您的要求。我还没有尝试过的唯一一件事是,您是否可以创建自己的环境而不是指定新环境的名称。另一个区别可能是`import`将环境附加到搜索路径中,这可能不是您想要的(您可以通过取消附加来修复)。 - R Yoda
2个回答

1

'mice'包内部调用全局环境中的插补方法。根据作者的说法,这样做是为了允许提供自己的定制插补方法。因此,该包必须在全局环境中公开其默认实现。我认为这是一个很好的纯判断的例子——仅通过全局环境才能识别内部方法。这违背了首先将代码封装成包的目的。如果想要允许使用外部函数,则只需为将它们传递给包提供API。

您看到的错误消息是由函数'mice:::check_method'触发的:

notFound <- !vapply(fullNames, exists, logical(1), mode = "function", inherits = TRUE)

我的解决方法是从我的自己的包中重新导出“mice”内部使用的方法(就像您的一样,内部也使用“mice”)。只需在其中一个R文件中放置并对其运行roxygen2即可:

#' @importFrom mice mice

#' @export
mice.impute.pmm <- mice::mice.impute.pmm

#' @export
mice.impute.polyreg <- mice::mice.impute.polyreg

当然,如果您的数据使用了其他方法,则需要导出这些方法。我的观点是,如果我需要污染全局环境,我会尽可能地减少污染,只导出“mice”所需的函数。

0
昨天我遇到了同样的错误,并提出了类似的问题(顺便说一下,已经被踩了)。今天我找到了一个解决方案,希望它对你也有用,也许你(或其他人)可以更详细地解释一下。
我正在开发一个R包,并使用roxygen2来记录函数。由于我必须使用mice::mice函数,所以在描述文件中的导入部分中列出了mice。在构建和检查包时,一切都很顺利,直到我实际运行调用mice::mice的函数时,此时我得到了与你相同的错误。
据我所知,这是问题的原因: 在使用mice的函数的文档部分中,您需要添加以下内容:
#' @importMethodsFrom mice
#' @importFrom mice mice

请注意,到目前为止我使用过的大多数软件包,以下一行代码已经足够了:
#' @importFrom mice mice

显然,使用mice需要添加@importMethodsFrom指令。 我猜这是因为它正在使用S4类,但我对它们知之甚少,所以我只知道这种方式可以工作。

我通过阅读此页面的"S4"部分http://r-pkgs.had.co.nz/namespace.html#imports发现了这一点。

因此,针对您的特定情况,我的猜测是您的函数文档应该类似于此:

#' @import data.table
#' @importFrom mice mice
#' @importMethodsFrom mice
#' @export
impute <- function(data, m = 5, max.iter = 5){...}

这对我很有效,希望对你也有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接