R中的掩蔽方法
Masking methods in R
and in particular 提出了以下问题:如何获得有关 R 中方法屏蔽的警告?
如果您在干净的 R 会话中 运行 以下代码,您会注意到加载 dplyr
会更改 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
如果附加包 dplyr
,您会收到多个屏蔽对象的警告,但不会收到有关 lag
被屏蔽的默认方法的警告。原因是调用 lag
时,调用了 stats
包中的通用函数。
lag
## function (x, ...)
## UseMethod("lag")
## <bytecode: 0x000000000c072188>
## <environment: namespace:stats>
而methods(lag)
只是告诉我有一个方法lag.default
。我可以看到有两种使用 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
但这需要我知道检查默认 lag
方法是否被 dplyr
更改。有没有办法检查方法是否被屏蔽?或许有这样一个功能:
checkMethodMasking(dplyr)
## The following methods are masked from 'package:dplyr':
## lag.default
注意:当我用 require(dplyr)
加载 dplyr
时,仅仅有警告是不够的。如果我只是加载名称空间而不附加包(例如,我调用 dplyr::mutate
,或者甚至我使用另一个包中的函数调用使用 [=29 导入的 dplyr
函数,该方法也会重载=]).
更新 现在 github 上有一个 R 包试图解决这些问题。它离理想的解决方案还很远,但它对解决问题有一定的帮助。它目前具有函数 require
、library
和 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
这只是关于如何找到屏蔽 S3 方法的一种想法。这绝不是一个完美的解决方案,但我想在有人想出更好的主意之前它至少会有助于调试。
#' 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), ]
}
从干净的工作区调用(具有上述功能,但未加载包),然后您可以观察到以下内容:
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>
这只是告诉你这里有两个 lag.default
方法。它实际上并没有告诉你,哪个在掩盖另一个。它只是指出潜在的问题。
conflicted
包(参见 here) now offers a potential solution to this problem. With conflicted
loaded, you get more explicit error messages about conflicting function names. You also can use conflict_prefer
(details here)指定默认情况下要使用的包的功能以及应屏蔽的功能。
例如,这是我最近在尝试使用 nFactors
包中的函数 parallel
时遇到的错误:
# Error: [conflicted] `parallel` found in 2 packages.
# Either pick the one you want with `::`
# * nFactors::parallel
# * lattice::parallel
# Or declare a preference with `conflict_prefer()`
# * conflict_prefer("parallel", "nFactors")
# * conflict_prefer("parallel", "lattice")
然后我添加了
conflict_prefer("parallel", "nFactors")
代码在脚本开头加载我的库之后,以确保 parallel
会在我的代码中调用 nFactors::parallel
。
如果您在干净的 R 会话中 运行 以下代码,您会注意到加载 dplyr
会更改 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
如果附加包 dplyr
,您会收到多个屏蔽对象的警告,但不会收到有关 lag
被屏蔽的默认方法的警告。原因是调用 lag
时,调用了 stats
包中的通用函数。
lag
## function (x, ...)
## UseMethod("lag")
## <bytecode: 0x000000000c072188>
## <environment: namespace:stats>
而methods(lag)
只是告诉我有一个方法lag.default
。我可以看到有两种使用 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
但这需要我知道检查默认 lag
方法是否被 dplyr
更改。有没有办法检查方法是否被屏蔽?或许有这样一个功能:
checkMethodMasking(dplyr)
## The following methods are masked from 'package:dplyr':
## lag.default
注意:当我用 require(dplyr)
加载 dplyr
时,仅仅有警告是不够的。如果我只是加载名称空间而不附加包(例如,我调用 dplyr::mutate
,或者甚至我使用另一个包中的函数调用使用 [=29 导入的 dplyr
函数,该方法也会重载=]).
更新 现在 github 上有一个 R 包试图解决这些问题。它离理想的解决方案还很远,但它对解决问题有一定的帮助。它目前具有函数 require
、library
和 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
这只是关于如何找到屏蔽 S3 方法的一种想法。这绝不是一个完美的解决方案,但我想在有人想出更好的主意之前它至少会有助于调试。
#' 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), ]
}
从干净的工作区调用(具有上述功能,但未加载包),然后您可以观察到以下内容:
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>
这只是告诉你这里有两个 lag.default
方法。它实际上并没有告诉你,哪个在掩盖另一个。它只是指出潜在的问题。
conflicted
包(参见 here) now offers a potential solution to this problem. With conflicted
loaded, you get more explicit error messages about conflicting function names. You also can use conflict_prefer
(details here)指定默认情况下要使用的包的功能以及应屏蔽的功能。
例如,这是我最近在尝试使用 nFactors
包中的函数 parallel
时遇到的错误:
# Error: [conflicted] `parallel` found in 2 packages.
# Either pick the one you want with `::`
# * nFactors::parallel
# * lattice::parallel
# Or declare a preference with `conflict_prefer()`
# * conflict_prefer("parallel", "nFactors")
# * conflict_prefer("parallel", "lattice")
然后我添加了
conflict_prefer("parallel", "nFactors")
代码在脚本开头加载我的库之后,以确保 parallel
会在我的代码中调用 nFactors::parallel
。