div - Métodos de enmascaramiento en R
sidebarpanel shiny (1)
Esta pregunta y en particular esta respuesta trajeron la siguiente pregunta: ¿Cómo puedo obtener una advertencia sobre el enmascaramiento de los métodos en R?
Si ejecuta el siguiente código en una sesión R limpia, notará que cargar dplyr
cambia el método predeterminado para el lag
.
lag(1:3, 1)
## [1] 1 2 3
## attr(,"tsp")
## [1] 0 2 1
require(dplyr)
lag(1:3, 1)
## [1] NA 1 2
Si adjunta el paquete dplyr
, obtendrá avisos para varios objetos enmascarados, pero no hay ninguna advertencia sobre el método predeterminado para el lag
enmascarado. El motivo es que al llamar a lag
, se llama a la función genérica del paquete de stats
.
lag
## function (x, ...)
## UseMethod("lag")
## <bytecode: 0x000000000c072188>
## <environment: namespace:stats>
Y los methods(lag)
simplemente me dicen que hay un método lag.default
. Puedo ver que hay dos métodos usando getAnywhere
:
getAnywhere(lag.default)
## 2 differing objects matching ‘lag.default’ were found
## in the following places
## registered S3 method for lag from namespace dplyr
## namespace:dplyr
## namespace:stats
## Use [] to view one of them
Pero esto requiere que yo sepa si el método de lag
predeterminado fue cambiado por dplyr
. ¿Hay alguna forma de verificar si los métodos fueron enmascarados? Quizás hay una función como esta:
checkMethodMasking(dplyr)
## The following methods are masked from ''package:dplyr'':
## lag.default
NB: No es suficiente tener una advertencia cuando se carga dplyr
con require(dplyr)
. El método también se sobrecarga si solo cargo el espacio de nombres sin adjuntar el paquete (por ejemplo, llamo a dplyr::mutate
, o incluso uso una función de otro paquete que llama a una función de dplyr
que se importó usando importFrom
).
Actualización Ahora hay un paquete R en github que intenta resolver estos problemas. Todavía está lejos de ser una solución ideal, pero se dirige hacia la solución del problema. Actualmente tiene funciones require
, library
y warnS3Methods
.
devtools::install_github("blasern/warnS3")
require(warnS3)
# Examples
require2(dplyr)
## Loading required package: dplyr
##
## Attaching package: ‘dplyr’
##
## The following object is masked from ‘package:stats’:
##
## filter
##
## The following objects are masked from ‘package:base’:
##
## intersect, setdiff, setequal, union
##
## The following methods are masked by ''package:dplyr'':
##
## ''lag.default'' from ''package:stats''
require2(roxygen2)
## Loading required package: roxygen2
## The following methods are masked by ''package:roxygen2'':
##
## ''escape.character'' from ''package:dplyr''
warnS3Methods()
## The following methods are available in multiple packages:
##
## ''escape.character'' in packages: dplyr, roxygen2
## ''lag.default'' in packages: dplyr, stats
Esta es solo una idea de cómo se pueden encontrar métodos S3 enmascarados. De ninguna manera es una solución perfecta, pero supongo que hasta que alguien tenga una mejor idea, al menos ayudará con la depuración.
#'' Get all S3 methods from a package
#''
#'' Find all S3 methods from a package
#''
#'' @param pkg can be either the name of an installed package
#'' or the path of a package
getPkgS3Methods <- function(pkg){
if (basename(pkg) == pkg) pkg <- path.package(pkg)
ns <- parseNamespaceFile(basename(pkg),
dirname(pkg),
mustExist = FALSE)
if (length(ns$S3methods) == 0) return(NULL)
df <- cbind.data.frame(basename(pkg), ns$S3methods)
colnames(df) <- c("package", "method", "class", "other")
df
}
#'' Get masked S3 methods
#''
#'' Finds all S3 methods that are currently available that are
#'' duplicated
getMaskedS3Methods <- function(){
paths <- as.character(gtools::loadedPackages(silent = TRUE)[, "Path"])
lst <- lapply(paths, getPkgS3Methods)
all_methods <- do.call(rbind, lst)
duplicates <-
duplicated(all_methods[, c("method", "class")]) |
duplicated(all_methods[, c("method", "class")], fromLast = TRUE)
res <- all_methods[duplicates, ]
res[order(res$method, res$class, res$package), ]
}
Llamado desde un área de trabajo limpia (con las funciones anteriores, pero sin paquetes cargados), puede observar lo siguiente:
getMaskedS3Methods()
## [1] package method class other
## <0 rows> (or 0-length row.names)
require(dplyr)
getMaskedS3Methods()
## package method class other
## 143 dplyr lag default <NA>
## 438 stats lag default <NA>
Eso te dice que aquí hay dos métodos lag.default
. En realidad no te dice cuál de las dos está enmascarando a la otra. Simplemente señala problemas potenciales.