簡體   English   中英

如何通過調用在其名稱空間中沒有它的函數來找到未附加包中的非導入方法?

[英]How can a non-imported method in a not-attached package be found by calls to functions not having it in their namespace?

R命名空間充當其關聯包中所有函數的直接環境。 換句話說,當來自包foo的函數bar()調用另一個函數時,R計算器首先在<environment: namespace:foo>搜索另一個函數,然后在"imports.foo"<environment: namespace:base><environment: R_GlobalEnv> ,依此類推,鍵入search()返回的搜索列表。

命名空間的一個很好的方面是它們可以使包充當更好的公民: <environment: namespace:foo>未導出函數和imports:foo函數imports:foo僅可用:(a) foo中的函數; (b)從foo進口的其他包裹; 或者(c)通過完全限定的函數調用,如foo:::bar()

或者直到最近才想到......

行為

這個最近的SO問題突出了一個案例,其中通過調用看似無關的函數找到了一個隱藏在其包的名稱空間中的函數:

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 ,它被調度到第二次調用transform() T1T2不同,因為第一個是由stats:::reorder.default()計算的,第二個是由gdata:::reorder.factor()

我的問題

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

(答案應該包括對范圍規則的解釋,這些規則從涉及統計數據基礎包中的函數的調用引導到gdata中看似隱藏得很好的方法。)


還可能有用的細節

  1. gdata:::reorder.factorgdata包都不是由gmodels顯式導入的。 以下是gmodelsNAMESPACE文件中的import*指令:

     importFrom(MASS, ginv) importFrom(gdata, frameApply) importFrom(gdata, nobs) 
  2. <environment: namespace:gmodels>中沒有reorder()transform()方法,也沒有"imports:gmodels"

     ls(getNamespace("gmodels")) ls(parent.env(getNamespace("gmodels"))) 
  3. 分離gmodels不會恢復reorder()的行為: gdata:::reorder.factor()仍然會被調度:

     detach("package:gmodels") T3 <- transform(data, group=reorder(group,-num)) identical(T3, T2) # [1] TRUE 
  4. reorder.factor()未存儲在基本環境中的S3方法列表中:

     grep("reorder", ls(.__S3MethodsTable__.)) # integer(0) 

過去幾天的R聊天線程包括一些額外的想法。 感謝Andrie,Brian Diggs和Gavin Simpson(和其他人一起)應該隨意編輯或添加可能的impt。 這個問題的細節。

我不確定我是否正確理解了你的問題,但重點是group是字符向量而data$group是因子。

附加gmodelsreorder(factor)調用reorder(factor)調用gdata:::reorder.factor 所以, reorder(factor(group))調用它。

transform ,函數在第一個參數的環境中進行評估,因此在T2 <- transform(data, group = reorder(group,-num))group是factor。

更新

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

首先在調用泛型函數的環境中,然后在定義泛型的環境的注冊數據庫中(通常是命名空間)。

然后, 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

可能這是整個場景。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM