R命名空间访问和match.fun

7
我正在开发一个R软件包,其中一个函数包含了对导入到软件包命名空间中的包中函数的match.fun调用。但是,在加载软件包时,match.fun调用无法找到函数名称。根据Hadley Wickham的描述,我认为我的做法没有问题,但明显不是这种情况。
示例:
# in the package file header, for creation of the NAMESPACE via roxygen2:
##` @import topicmodels

# The function declaration in the package
ModelTopics <- function(doc.term.mat, num.topics, topic.method="LDA"){
  topic.fun <- match.fun(topic.method)
  output <- topic.fun(doc.term.mat, k=num.topics)
  return(output)

}    

然后在R中:

> library(mypackage)
> sample.output <- ModelTopics(my.dtm, topic.method="LDA", num.topics=5)
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'LDA' of mode 'function' was not found

据我理解,命名空间(namespaces)的作用是使 match.fun 调用能够访问包命名空间,其中应该包括 topicmodels 函数。但是这里似乎不是这种情况。如果我将 topicmodels 直接导入到 R 会话的全局命名空间中,则可以正常工作。
非常感谢任何帮助。这是在运行OS X上的 R64 2.14.1。
更新: 该包位于此处 关于 DESCRIPTION 文件,可能存在问题:roxygen2 不会使用 Imports: 语句更新 DESCRIPTION 文件。但是,其他软件包也没有列在那里,只有 match.fun 调用似乎受到影响。
关于 NAMESPACE 提取,这是导入部分:
import(catspec)
import(foreach)
import(gdata)
import(Hmisc)
import(igraph)
import(lsa)
import(Matrix)
import(plyr)
import(RecordLinkage)
import(reshape)
import(RWeka)
import(stringr)
import(tm)
import(topicmodels)

+1 很好的问题。你的包在Github或其他地方可以看到代码吗? - Andrie
请问您能否添加以下内容:1)从NAMESPACE文件中提取显示“topicmodels”被导入的部分,2)从DESCRIPTION文件中提取显示“Imports: topicmodels”的部分? - Andrie
2个回答

9
我认为这是一个作用域问题。虽然你已经导入了 topicmodels 以及 LDA,但你没有导出这些函数,所以它们在搜索路径中不可用。
?match.fun 中可以看到:

match.fun 不应该在顶层使用,因为它会在调用者的父级中进行匹配。

因此,由于你在全局环境中使用了 ModelTopics,而 LDA 在全局环境中不可用,所以 match.fun 调用失败了。
对我来说,你有两个选择:
选项1:使用 get 另一种选择是使用 get,其中你可以指定环境。请考虑以下内容:尝试使用 match.funggplot2 包中查找 print.ggplot
match.fun("print.ggplot")
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'print.ggplot' of mode 'function' was not found

由于 print.ggplot 没有被导出,match.fun 找不到它。

然而,get 可以找到它:

get("print.ggplot", envir=environment(ggplot))
function (x, newpage = is.null(vp), vp = NULL, ...) 
{
    set_last_plot(x)
    if (newpage) 
        grid.newpage()
    data <- ggplot_build(x)
    gtable <- ggplot_gtable(data)
    if (is.null(vp)) {
        grid.draw(gtable)
    }
    else {
        if (is.character(vp)) 
            seekViewport(vp)
        else pushViewport(vp)
        grid.draw(gtable)
        upViewport()
    }
    invisible(data)
}
<environment: namespace:ggplot2>

选项2:从topicmodels中导出所需的函数

如果你将来自topicmodels的必要函数导出到你的NAMESPACE中,你的代码也应该能够运行。

有两种方法可以实现:

  • 使用@export选择性地将LDA和其他函数导出到名称空间中
  • 声明依赖项,使用Depends: topicmodels - 这与在全局环境中调用library(topicmodels)相同。这将工作,但可能是一种比较粗暴的方法。它还意味着任何后续的library调用都可以遮盖你的LDA函数,从而导致意外的结果。

0
回答自己的问题:在重新运行更新代码后,DESCRIPTION文件没有更新Imports:Depends:字段。因此出现了match.fun问题。出于好奇,为什么这会影响match.fun,但不影响其他地方对导入包函数的一系列函数调用?


你是使用 Imports:topicmodels 还是 Depends:topicmodels - Andrie
我正在使用 Depends:topicmodels - markhuberty

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