【问题标题】:Masking methods in RR中的掩蔽方法
【发布时间】:2015-08-18 22:11:50
【问题描述】:

This question 尤其是this answer 提出了以下问题:如何获得有关 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,或者甚至我使用另一个包中的一个函数,该函数调用使用importFrom 导入的dplyr 函数),该方法也会过载。

【问题讨论】:

  • FWIW dplyr 在下一个版本中不会覆盖该方法

标签: r dplyr r-package


【解决方案1】:

更新现在github 上有一个 R 包试图解决这些问题。它距离理想的解决方案还很远,但它对解决问题有一定的帮助。它目前具有requirelibrarywarnS3Methods 功能。

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 方法。它实际上并没有告诉你,哪个掩盖了另一个。它只是指出潜在的问题。

【讨论】:

  • 我真的不明白为什么会造成这种混乱,因为(非常好)dplyr 包的作者合并了冲突的对象名称而导致了这么多问题
【解决方案2】:

conflicted 包(请参阅here)现在提供了解决此问题的潜在解决方案。加载 conflicted 后,您会收到有关函数名称冲突的更明确的错误消息。你也可以使用conflict_prefer(详情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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 2017-12-07
    相关资源
    最近更新 更多