r - 如何通过调用在其命名空间中没有它的函数来找到未附加包中的非导入方法?

标签 r namespaces scoping

R 命名空间充当其关联包中所有函数的直接环境。换句话说,当包 foo 中的函数 bar() 调用另一个函数时,R evaluator 首先在 <environment: namespace:foo> 中搜索另一个函数,然后在 "imports.foo"<environment: namespace:base><environment: R_GlobalEnv> 等通过键入 search() 返回的搜索列表向下搜索​​。

命名空间的一个很好的方面是它们可以使包表现得像更好的公民:<environment: namespace:foo> 中未导出的函数和 imports:foo 中的函数仅可用: (a) foo 中的函数; (b) 从 foo 导入的其他包;或 (c) 通过完全限定的函数调用,如 foo:::bar()

或者直到最近我还以为...

行为

This recent SO question 强调了一个案例,在该案例中,一个隐藏在其包命名空间中的函数仍然通过调用看似无关的函数而被发现:

group <- c("C","F","D","B","A","E")
num <- c(12,11,7,7,2,1)
data <- data.frame(group,num)

## Evaluated **before** attaching 'gmodels' package
T1 <- transform(data, group = reorder(group,-num))

## Evaluated **after** attaching 'gmodels
library(gmodels)
T2 <- transform(data, group = reorder(group,-num))

identical(T1, T2) 
# [1] FALSE

其直接原因

@Andrie 回答了最初的问题,指出 gmodels 从包 gdata 导入,其中包括一个函数 reorder.factor ,该函数被分派(dispatch)到对 transform() 的第二次调用。 T1T2 不同,因为第一个由 stats:::reorder.default() 计算,第二个由 gdata:::reorder.factor() 计算。

我的问题

在上面对 transform(data, group=reorder(...)) 的调用中, reorder 的调度机制如何找到然后调度到 gdata:::reorder.factor()

(答案应包括对涉及 stats 基础 包中的函数的调用到 gdata 中看似隐藏良好的方法的调用的范围规则的解释。)

更多可能有用的细节
  • gdata:::reorder.factor gdata 包作为一个整体都不是由 gmodels 显式导入的。以下是 gmodels ' NAMESPACE 文件中的 import* 指令:
    importFrom(MASS, ginv)
    importFrom(gdata, frameApply)
    importFrom(gdata, nobs)
    
  • reorder()transform() 中没有 <environment: namespace:gmodels>"imports:gmodels" 的方法:
    ls(getNamespace("gmodels"))
    ls(parent.env(getNamespace("gmodels")))
    
  • 分离 gmodels 不会恢复 reorder() 的行为: gdata:::reorder.factor() 仍然被调度:
    detach("package:gmodels")
    T3 <- transform(data, group=reorder(group,-num))
    identical(T3, T2)
    # [1] TRUE
    
  • reorder.factor() 未存储在基础环境中的 S3 方法列表中:
    grep("reorder", ls(.__S3MethodsTable__.))
    # integer(0)
    

  • 最近几天的 R 聊天线程包括一些额外的想法。感谢 Andrie、Brian Diggs 和 Gavin Simpson,他们(与其他人)应该可以随意编辑或添加可能的 impt。这个问题的详细信息。

    最佳答案

    我不确定我是否正确理解了您的问题,但要点是 group 是字符向量,而 data$group 是因子。

    附加 gmodels 后,对 reorder(factor) 的调用调用 gdata:::reorder.factor
    所以,reorder(factor(group)) 调用它。

    transform 中,函数在第一个参数的环境中进行评估,因此在 T2 <- transform(data, group = reorder(group,-num)) 中,group 是因子。

    更新
    library 将导入包附加到加载的命名空间。

    > loadedNamespaces()
     [1] "RCurl"     "base"      "datasets"  "devtools"  "grDevices" "graphics"  "methods"  
     [8] "stats"     "tools"     "utils"    
    > library(gmodels) # here, namespace:gdata is loaded
    > loadedNamespaces()
     [1] "MASS"      "RCurl"     "base"      "datasets"  "devtools"  "gdata"     "gmodels"  
     [8] "grDevices" "graphics"  "gtools"    "methods"   "stats"     "tools"     "utils"    
    

    以防万一, reorder 泛型存在于 namespace:stats 中:
    > r <- ls(.__S3MethodsTable__., envir = asNamespace("stats"))
    > r[grep("reorder", r)]
    [1] "reorder"            "reorder.default"    "reorder.dendrogram"
    

    更多细节

    调用 reorder 将在两个环境中搜索 S3generics:

    ?UseMethod

    first in the environment in which the generic function is called, and then in the registration data base for the environment in which the generic is defined (typically a namespace).



    然后,loadNamespace 将 S3 函数注册到命名空间。

    所以,在你的情况下, library(gmodels) -> loadNamespace(gdata) -> registerS3Methods(gdata)

    在此之后,您可以通过以下方式找到它:
    > methods(reorder)
    [1] reorder.default*    reorder.dendrogram* reorder.factor*    
    
       Non-visible functions are asterisked
    

    但是,由于 reorder.factor 未附加在您的搜索路径中,因此您无法直接访问它:
    > reorder.factor
    Error: object 'reorder.factor' not found
    

    可能这就是整个场景。

    关于r - 如何通过调用在其命名空间中没有它的函数来找到未附加包中的非导入方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11004018/

    相关文章:

    flash - Actionscript-3 命名空间和动态类型?

    Javascript 并从另一个引用一个命名空间属性

    r - as(x, class(k)) 错误 : no method or default for coercing “NULL” to “data.frame”

    html - Shiny 中 selectInput 标签旁边的信息图标

    r - 修改简历包R生成的CV

    C# .NET WinForms。 Visual Studio 无法识别子文件夹中的命名空间

    r - 在循环中分配函数时的作用域问题

    matlab - (Matlab)奇怪的精度损失,同时将复杂矩阵分配给局部变量

    r - 将分钟转换为星期几和小时