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

时间:2019-03-27 13:37:34

标签: r namespaces

这个问题是对this question的跟进。 考虑以下示例

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

到目前为止很好:由于R现在不对类stats::fitted的对象使用Arima,所以返回零。

接下来,在我的代码中,我需要forecast包中的一个函数。我没有附加包装,只是使用::表示法加载。 在下面的代码中,我将直接使用requireNamespace加载它。

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

突然之间,同一命令返回了不同的结果。 我了解为什么会发生这种情况(希望我说的没错):通过加载forecast包,将通用函数fitted(即fitted.Arima)的新方法加载到名称空间中结果不同。

对我来说,这种行为很烦人:是否可以选择fitted的特定方法? 我读过this chapter,但不知道如何解决此问题。

我还尝试从名称空间中卸载forecast包,但没有成功:

unloadNamespace("forecast")
length(stats::fitted(y))
[1] 10

似乎一旦加载了软件包,就无法使用旧的方法fitted。 我想知道如何处理这些情况。

编辑

我在unloadNamespace("forecast")之后的评论中指出

isNamespaceLoaded("forecast")
[1] FALSE

但是methods仍然包含fitted.Arima

2 个答案:

答案 0 :(得分:6)

我从R devel找到了this thread。 R Core的Brian Ripley说:

  

卸载名称空间不会取消注册其方法(并且   注册没有堆栈,所以R不可能知道那里有什么   之前)。

然后线程注意到?unloadNamespace将您指向?detach

  

请参阅帮助中的注释以分离有关以下方面的问题   卸载和重新加载名称空间。

最终会说出以下内容(强调我的意思)

  

如果程序包具有名称空间,则在默认情况下不会卸载它   命名空间(甚至可能没有使用unload = TRUE),并分离   通常不会卸载任何动态加载的已编译代码   (DLL)。此外,从名称空间注册的 S3方法将不会   已删除

因此,我的理解是,在加载名称空间(例如,通过使用::)时,会注册S3方法,这些方法从不链接到它们从其加载的名称空间,因此,卸载名称空间也无法取消注册方法。从methods()清除它们的唯一方法是重新启动R。

RolandASc noted一样,如果要避免调度到stats:::fitted.default,则可以选择使用fitted.Arima来调用默认方法。

答案 1 :(得分:5)

@Calum您完全正确地指出,卸载名称空间不会删除为另一个包中定义的S3泛型注册的S3方法。如果您有兴趣,这里更详细地介绍了这种情况以及原因。

加载预测程序包时,它定义的所有方法都“注册”在各种不同名称空间的数据库中。遵循的规则R是方法在定义其S3泛型的包的名称空间中注册。由于fitted()泛型是在 stats 中定义的,因此在称为.__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"

(有关问题和解答,see here。)