R中的命名空间和通用函数

7

这个问题有些是关于此问题的后续。考虑以下示例:

set.seed(1)
x <- cumsum(rnorm(10))
y <- stats::arima(x, order = c(1, 0, 0))
length(stats::fitted(y))
[1] 0

目前为止还不错: 返回零是因为R不知道如何在Arima类的对象上使用stats::fitted

接下来,在我的代码中,我需要forecast包中的一个函数。我不会将包附加到环境中,只需使用::符号加载它即可。 在下面的代码中,我将直接使用requireNamespace加载它。

requireNamespace("forecast", quietly = TRUE)
length(stats::fitted(y))
[1] 10

突然间相同的命令返回不同的结果。我明白为什么会发生这种情况(并希望我的说法是正确的):通过加载forecast包,将新的方法fitted.Arima加载到命名空间中作为通用函数fitted的一个方法,从而导致不同的结果。
对我来说,这种行为相当令人烦恼:有没有办法选择一个特定的fitted方法?我阅读了这一章,但没有找到如何解决这个问题。
我还尝试从命名空间卸载forecast包,但没有成功。
unloadNamespace("forecast")
length(stats::fitted(y))
[1] 10

看起来,一旦我加载了这个包,就不能再使用旧的fitted方法。我想知道如何处理这些情况。

编辑

unloadNamespace("forecast")之后,正如评论中指出的那样,我得到了这个:

isNamespaceLoaded("forecast")
[1] FALSE

但是methods仍包括fitted.Arima

1
如果在使用requireNamespace之前执行methods(fitted),则会看到所有已加载的方法。在执行unloadNamespace之后,您可以执行isNamespaceLoaded("forecast"),它将返回FALSEmethods(fitted)显示的结果与之前相同。这很奇怪。 - patL
1
根据我的理解,“unloadNamespace”应该完全撤销“requireNamespace”的影响,但显然它并没有。 - Cettt
1
我现在无法核实,但您能否使用stats:::fitted.default(y)代替? - RolandASc
@RolandASc stats:::fitted.default(y) 会出现错误:"找不到函数..."。 - Cettt
3
不确定,我现在已经尝试了一下,对我来说这个方法完全可行(即 length(stats:::fitted.default(y)) 返回的是 0)。你遇到的具体错误是什么? - RolandASc
2个回答

7
我找到了R devel中的这个帖子。R核心开发者Brian Ripley表示:

卸载命名空间不会取消注册其方法(并且注册没有堆栈,因此R无法知道之前有什么)。

然后该帖子指出?unloadNamespace指向?detach

请参阅detach帮助文档中有关卸载和重新加载名称空间的一些问题的注释。

其中最终确实提到以下内容(重点在我):

如果包有一个命名空间,则分离它默认情况下不会卸载该命名空间(甚至可能即使使用unload = TRUE也不会),并且通常不会卸载任何动态加载的编译代码(DLL)。 此外,来自命名空间的已注册S3方法将不会被删除

因此,我的理解是,虽然加载命名空间(例如使用::)会注册S3方法,但这些方法从未链接到它们所加载的命名空间,因此卸载命名空间时不能取消注册这些方法。 从methods()中清除它们的唯一方法是重新启动R。
正如RolandASc所指出的,如果您想避免分派到fitted.Arima,则可以使用stats:::fitted.default调用默认方法。

谢谢你的回答。很抱歉我把悬赏给了Josh O'Brien。我发现他的回答比你的更详细一些。 - Cettt

7
@CalumYou 的观点完全正确,卸载命名空间不会删除在另一个包中定义的 S3 泛型注册的 S3 方法。如果您感兴趣,这里提供了更详细的说明及其原因。
当加载 forecast 包时,它所定义的所有方法都会在多个不同命名空间的数据库中“注册”。 R 遵循的规则是:方法在其 S3 泛型定义的包的命名空间中注册。由于 fitted() 泛型是在 stats 中定义的,因此 forecast 定义的新方法将被注册在称为 .__S3MethodsTable__ 的环境中。卸载 forecast 将保持 stats 包不变(如果您考虑一下,这可能是一个总体上明智的设计决策),但导致 fitted.Arima 方法(以及许多其他方法)仍然注册在它的 .__S3MethodsTable__ 中。
要查看如何操作,可以查看以下内容:
isNamespaceLoaded("forecast")
## [1] FALSE
ls(stats:::.__S3MethodsTable__., pattern = "fitted")
## [1] "fitted.default"       "fitted.isoreg"        "fitted.kmeans"       
## [4] "fitted.nls"           "fitted.smooth.spline"

## Loading the forecast namespace registers new 'fitted' methods ...
requireNamespace("forecast", quietly = TRUE)
isNamespaceLoaded("forecast")
## [1] TRUE
ls(stats:::.__S3MethodsTable__., pattern = "fitted")
##  [1] "fitted.ar"              "fitted.Arima"           "fitted.arma"           
##  [4] "fitted.bats"            "fitted.default"         "fitted.ets"            
##  [7] "fitted.fracdiff"        "fitted.garch"           "fitted.gls"            
## [10] "fitted.glsStruct"       "fitted.gnls"            "fitted.gnlsStruct"     
## [13] "fitted.isoreg"          "fitted.kmeans"          "fitted.lagwalk"        
## [16] "fitted.lme"             "fitted.lmeStruct"       "fitted.lmList"         
## [19] "fitted.modelAR"         "fitted.nlmeStruct"      "fitted.nls"            
## [22] "fitted.nnetar"          "fitted.quantmod"        "fitted.smooth.spline"  
## [25] "fitted.tbats"           "fitted.tslm"            "fitted.values.quantmod"

## ... which are left behind even when the forecast namespace is unloaded
unloadNamespace("forecast")
isNamespaceLoaded("forecast")
## [1] FALSE
ls(stats:::.__S3MethodsTable__., pattern = "fitted")
##  [1] "fitted.ar"              "fitted.Arima"           "fitted.arma"           
##  [4] "fitted.bats"            "fitted.default"         "fitted.ets"            
##  [7] "fitted.fracdiff"        "fitted.garch"           "fitted.gls"            
## [10] "fitted.glsStruct"       "fitted.gnls"            "fitted.gnlsStruct"     
## [13] "fitted.isoreg"          "fitted.kmeans"          "fitted.lagwalk"        
## [16] "fitted.lme"             "fitted.lmeStruct"       "fitted.lmList"         
## [19] "fitted.modelAR"         "fitted.nlmeStruct"      "fitted.nls"            
## [22] "fitted.nnetar"          "fitted.quantmod"        "fitted.smooth.spline"  
## [25] "fitted.tbats"           "fitted.tslm"            "fitted.values.quantmod"

(有关问题和答案,请参见此处。)

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