[英]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()
。 T1
與T2
不同,因為第一個是由stats:::reorder.default()
計算的,第二個是由gdata:::reorder.factor()
。
如何在上面的transform(data, group=reorder(...))
調用transform(data, group=reorder(...))
, reorder
的調度機制找到然后調度到gdata:::reorder.factor()
?
(答案應該包括對范圍規則的解釋,這些規則從涉及統計數據和基礎包中的函數的調用引導到gdata中看似隱藏得很好的方法。)
gdata:::reorder.factor
和gdata包都不是由gmodels顯式導入的。 以下是gmodels的NAMESPACE文件中的import*
指令:
importFrom(MASS, ginv) importFrom(gdata, frameApply) importFrom(gdata, nobs)
在<environment: namespace:gmodels>
中沒有reorder()
或transform()
方法,也沒有"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)
調用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.