“以下对象被'package:xxx'屏蔽了”是什么意思?


76

加载程序包时,出现一条消息,指出:

"The following object is masked from 'package:xxx'

例如,如果我加载testthatthen 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

此消息是什么意思,我该如何预防?

Answers:


104

该消息表示两个软件包都具有相同名称的功能。在这种特殊情况下,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进行引用,或者在显式加载相关软件包之后进行引用。

这意味着当通过第三方文件加载第三方软件包时,如果在R的启动过程完成后加载第三方软件包,则.Rprofile可能会看到这些软件包中的函数被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

如果库屏蔽了“基本”包中的对象,该Hmisc::units怎么办?我需要把它放到搜索路径的开始使用它是这样的:units(df$age)<-'y'。有办法吗?
亚当·里奇科夫斯基

有没有办法知道在某个特定时间发生的所有掩蔽?
Johannes Wentu

1
@AdamRyczkowskibase::units()与其他任何软件包一样使用。
Richie Cotton

@JohannesWentu我已经更新了我的答案以解释如何执行此操作。
Richie Cotton

2
程序包冲突对于这种情况也可能有用。
aosmith '18

0

我也有同样的问题。我避免使用它remove.packages("Package making this confusion")并且它起作用。就我而言,我不需要第二个软件包,所以这不是一个好主意。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.