17

この質問、特にこの回答は、次の質問を提起しました: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。を使用した 2 つの方法があることがわかります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

dplyr注意: をロードするときに警告を表示するだけでは十分ではありませんrequire(dplyr)。パッケージをアタッチせずに名前空間をロードしただけでも、メソッドはオーバーロードされます (たとえば、 を呼び出したり、 を使用してインポートされdplyr::mutateた関数を呼び出す別のパッケージの関数を使用したりします)。dplyrimportFrom

4

2 に答える 2

8

更新これらの問題を解決しようとするR パッケージがgithubに追加されました。理想的な解決策にはまだほど遠いですが、問題の解決に向けてある程度進んでいます。現在、関数requirelibraryおよびがあり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>

これは、ここに 2 つのlag.default方法があることを示しています。どちらが他方を隠しているかは実際にはわかりません。潜在的な問題を指摘しているだけです。

于 2015-06-04T16:23:52.747 に答える
1

conflictedパッケージ (ここを参照)、この問題に対する潜在的な解決策を提供するようになりました。ロードするとconflicted、競合する関数名に関するより明確なエラー メッセージが表示されます。conflict_prefer(詳細はこちら) を使用して、デフォルトで使用するパッケージの機能とマスクする必要のある機能を指定することもできます。

たとえばparallelnFactorsパッケージの関数を使用しようとしたときに最近発生したエラーは次のとおりです。

# 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にします。

于 2020-02-21T22:15:11.310 に答える