Yves Deville deville.yves@alpestat.com
{pax} eases the management of a suite of R packages by analysing
possible sources of conflicts. Examples of conflicts are
-
Several packages exporting an object with the same name. Although this can most of time be solved by using
::, this may be avoided. -
S3 generic functions defined several times across the suite. This can make the packages impossible to use simultaneously. Assume that a generic say
funis defined in packagespkg1andpkg2which are attached in this order. Whenpkg2is attached, the generic function is re-defined masking the existing function. This re-initialises the register of methods for the generic hence the methods defined inpkg1can no longer be used.
Let us call package suite a list of “packages” that are likely to be
used in a same session. {pax} analyses the DESCRIPTION and the
NAMESPACE files to detect some possible problems. The requirement is
for now that a “package” is a directory containing these two files. So
this can be: a source package or an installed package in one of the
directory known in .libPaths()
library(pax)## Le chargement a nécessité le package : data.table
## Use (assumedly) installed packages
pkgs <- c("evd", "ismev", "extRemes", "mev", "POT")
L <- pkgList(pkgs)## package: evd Using `.libPaths()[1]`
## package: ismev Using `.libPaths()[1]`
## package: extRemes Using `.libPaths()[1]`
## package: mev Using `.libPaths()[1]`
## package: POT Using `.libPaths()[1]`
res <- newS3generics(L$NS)## Warning in newS3generics(L$NS): package 'ismev' has no exports. The analysis
## may be misleading
## Warning in newS3generics(L$NS): package 'extRemes' has no exports. The analysis
## may be misleading
## Some new generics are defined in more than one package
## Multi Generic Pkg
## [1,] blockmaxxer extRemes
## [2,] bvcpp evd
## [3,] bvdens evd
## [4,] bvdp evd
## [5,] bvh evd
## [6,] bvqc evd
## [7,] ci extRemes
## [8,] convassess POT
## [9,] datagrabber extRemes
## [10,] decluster extRemes
## [11,] X dens evd, POT
## [12,] distill extRemes
## [13,] findpars extRemes
## [14,] fpois extRemes
## [15,] initializer extRemes
## [16,] pextRemes extRemes
## [17,] postmode extRemes
## [18,] X pp evd, POT
## [19,] profile2d evd
## [20,] X qq evd, POT
## [21,] retlev POT
## [22,] return.level extRemes
## [23,] rextRemes extRemes
## [24,] rl evd
## [25,] setup.design extRemes
## [26,] std.errors evd
## [27,] strip extRemes
## [28,] trans extRemes
So we see that some generics such as pp are defined several times
library(evd)
uvdata <- rgev(100, loc = 0.13, scale = 1.1, shape = 0.2)
fit <- fgev(uvdata)
pp(fit)head(getS3method("pp", class = "gev"))##
## 1 function (x, ci = TRUE, cilwd = 1, a = 0, main = "Probability Plot",
## 2 xlab = "Empirical", ylab = "Model", ...)
## 3 {
## 4 ppx <- ppoints(x$n, a = a)
## 5 probs <- pgev(sort(x$tdata), loc = x$loc, scale = x$param["scale"],
## 6 shape = x$param["shape"])
library(POT)## Registered S3 methods overwritten by 'POT':
## method from
## print.bvpot evd
## plot.bvpot evd
##
## Attachement du package : 'POT'
## Les objets suivants sont masqués depuis 'package:evd':
##
## dens, dgpd, exiplot, mrlplot, pgpd, pp, qgpd, qq, rgpd, tcplot
pp(fit)##
## Call: fgev(x = uvdata)
## Deviance: 351.2626
##
## Estimates
## loc scale shape
## 0.1363 1.0238 0.2683
##
## Standard Errors
## loc scale shape
## 0.11704 0.09693 0.08897
##
## Optimization Information
## Convergence: successful
## Function Evaluations: 40
## Gradient Evaluations: 13
try(getS3method("pp", class = "gev"))## Error in getS3method("pp", class = "gev") :
## Méthode S3 'pp.gev' introuvable
The problem is that when a generic is re-defined, the corresponding S3
methods are lost because the register of S3 methods is cleared or
re-initialised. So once {POT} has been attached, the `pp S3
method no longer exists for the class "gev" and pp(fit) calls the
default method as implemented by the pp.default function.
POT:::pp.default## function (object, ...)
## return(object)
## <bytecode: 0x5c2506765450>
## <environment: namespace:POT>
We see that this method simply returns a copy of the object.
So, it is not possible to use simultaneously all the functionalities of
the two packages. One possibility to avoid this problem would have been
to make {POT}* import the function pp from {evd}. Anyway,
new S3 generic functions should only defined with parsimony and care.
