“以下对象被‘package:xxx’遮蔽”是什么意思?

105

当我加载一个包时,会出现一条消息:

"The following object is masked from 'package:xxx'
例如,如果我加载了 testthat,然后是 assertive,我将获得以下结果:
library(testthat)
library(assertive)  
## Attaching package: ‘assertive’
## 
## The following objects are masked from ‘package:testthat’:
## 
##     has_names, is_false, is_less_than, is_null, is_true

这个消息是什么意思,我该如何防止它出现?

2个回答

144

该消息的意思是,这两个软件包中具有相同名称的函数。在这种情况下,testthatassertive软件包包含五个相同名称的函数。

当两个函数具有相同的名称时,哪个会被调用?

R将通过search路径查找函数,并使用它找到的第一个函数。

search()
 ##  [1] ".GlobalEnv"        "package:assertive" "package:testthat" 
 ##  [4] "tools:rstudio"     "package:stats"     "package:graphics" 
 ##  [7] "package:grDevices" "package:utils"     "package:datasets" 
 ## [10] "package:methods"   "Autoloads"         "package:base"

在这种情况下,由于assertive是在testthat之后加载的,它出现在搜索路径中较早的位置,因此该包中的函数将被使用。

is_true
## function (x, .xname = get_name_in_parent(x)) 
## {
##     x <- coerce_to(x, "logical", .xname)
##     call_and_name(function(x) {
##         ok <- x & !is.na(x)
##         set_cause(ok, ifelse(is.na(x), "missing", "false"))
##     }, x)
## }
<bytecode: 0x0000000004fc9f10>
<environment: namespace:assertive.base>

testthat中的函数不能以通常的方式访问;也就是说,它们已经被掩盖了。

如果我想要使用其中一个被掩盖的函数怎么办?

你可以在调用函数时显式提供包名称,使用双冒号操作符::。例如:

testthat::is_true
## function () 
## {
##     function(x) expect_true(x)
## }
## <environment: namespace:testthat>

如何抑制这个消息?

如果您了解函数名称冲突并且不想再次看到它,请通过将warn.conflicts = FALSE传递给library来抑制该消息。

library(testthat)
library(assertive, warn.conflicts = FALSE)
# No output this time

或者使用suppressPackageStartupMessages函数来抑制该消息:

library(testthat)
suppressPackageStartupMessages(library(assertive))
# Also no output

R的启动程序对函数屏蔽的影响

如果您更改了R的某些启动配置选项(请参见?Startup),则可能会遇到与您预期不同的函数屏蔽行为。如?Startup中所述的事情发生的精确顺序应该解决大多数问题。

例如,文档中指出:

  

请注意,在源代码时只加载基础包,因此需要通过例如utils::dump.frames引用其他包中的对象,或在显式加载相关包后引用。

这意味着,当通过像.Rprofile这样的文件加载第三方包时,如果您在R的启动过程完成之后加载第三方包,则可能会看到来自那些默认包(如stats)的函数掩盖那些来自第三方包的函数,而不是相反。

如何列出所有被屏蔽的函数?

首先,获取搜索路径上所有环境的字符向量。为方便起见,我们将此向量的每个元素命名为其自身的值。

library(dplyr)
envs <- search() %>% setNames(., .)

获取每个环境导出的函数(和其他变量)。

fns <- lapply(envs, ls)

将此转换为数据框,以便使用dplyr更加方便。

fns_by_env <- data_frame(
  env = rep.int(names(fns), lengths(fns)),
  fn  = unlist(fns)
)

查找对象出现超过一次的情况。

fns_by_env %>% 
  group_by(fn) %>% 
  tally() %>% 
  filter(n > 1) %>% 
  inner_join(fns_by_env)

为了测试这一点,可以尝试加载一些已知冲突的软件包(例如HmiscAnnotationDbi)。

如何防止名称冲突错误?

conflicted软件包会抛出一个带有有用错误信息的错误,每当你尝试使用一个有歧义的变量时。

library(conflicted)
library(Hmisc)
units
## Error: units found in 2 packages. You must indicate which one you want with ::
##  * Hmisc::units
##  * base::units

如果库掩盖了“base”包中的对象,例如Hmisc::units,我需要将其放在搜索路径的开头才能像这样使用:units(df$age)<-'y'。有没有相应的方法? - Adam Ryczkowski
有没有一种方法可以知道在某个时间发生的所有掩码操作? - Johannes Wentu
1
@AdamRyczkowski 使用 base::units(),就像使用其他任何软件包一样。 - Richie Cotton
@JohannesWentu 我已经更新了我的答案,解释了如何做到这一点。 - Richie Cotton
2
“Package conflicted”(https://github.com/r-lib/conflicted#conflicted)也许对这种情况有帮助。 - aosmith

0

我有同样的问题。我使用remove.packages("Package making this confusion")来避免它,它有效。在我的情况下,我不需要第二个包,所以那不是一个很好的主意。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接