【问题标题】:Using R alone, is it possible to have packages as a variable in a function?单独使用 R,是否可以将包作为函数中的变量?
【发布时间】:2021-08-16 21:44:41
【问题描述】:

我只是在测试加载不同的包,我编写了一个函数,我认为它可以让我根据需要添加和删除包。例如,如果我想加载 spatstat:

packagedelivery<-function(fry,leela){
  if(fry == TRUE){
    
    
    library(leela)
} else{
  detach(leela,unload=TRUE)
}
}

packagedelivery(TRUE,"spatstat")

R 抛出一个错误,声明:

 Error in library(leela) : there is no package called ‘leela’ 

我在这里遗漏了哪些步骤?

非常感谢。

【问题讨论】:

  • 非标准评价。将 'require' 与 'character.only = TRUE' 一起使用。
  • 正如怀疑的那样,函数为 TRUE 但不是 FALSE。 FALSE 条件给出Error in detach(leela, unload=TRUE) : invalid 'name' argument"
  • detach 函数也应该有一个 character.only 参数。
  • 只使用require(如果你要检查它的返回值,有或没有character.only,否则它是错误的工具。library(..., character.only=)存在。可以使用detach(paste0("package:", leela), unload=TRUE),但是只有在没有其他仍然加载的包依赖它的情况下才会起作用。(unloadNamespace 也存在此问题,因此不是 detach 独有的。)
  • 例如,通过添加一个 grepl 参数来消除所有 spatstat 包,我遇到了您所指的关于包相互依赖的内容。我不知道如何克服这个问题,也不知道这样做是否可取或安全。

标签: r function package


【解决方案1】:

library() 中有一个 character.only= 参数。要使detach() 正常工作,您只需添加要分离的内容,在本例中为'package:'

packagedelivery1 <- function(fry, leela) {
  if (fry) {
    library(leela, character.only=TRUE)
  } else {
    detach(sprintf('package:%s', leela), unload=TRUE, character.only=TRUE)
  }
}
packagedelivery1(TRUE, "matrixStats")
colSds(matrix(rnorm(9), 3, 3))
# [1] 1.6706355 0.5352099 1.4046043

packagedelivery1(FALSE, "matrixStats")  ## first unload
colSds(matrix(rnorm(9), 3, 3))
# Error in colSds(matrix(rnorm(9), 3, 3)) : 
#   could not find function "colSds"

packagedelivery2(FALSE, "lfe")          ## second unload (package not loaded)
# Error in detach(sprintf("package:%s", leela), unload = T, character.only = T) : 
#   invalid 'name' argument 

packagedelivery1(TRUE, "fooPackage")
# Error in library(leela, character.only = TRUE) : 
#   there is no package called ‘fooPackage’ 

按预期工作。并在包不可用或不再可用时抛出错误。

您还可以使用require()unloadNamespace() 创建一个不同的函数来发出警告而不是抛出错误:

packagedelivery2 <- function(fry, leela) {
  srh <- sprintf("package:%s", leela) %in% search()
  if (fry) {
    if (srh) {
      message(sprintf("Package called '%s' already loaded", leela))
    } else {
      require(leela, character.only=TRUE)
    }
  } else {
    if (!srh) {
      message(sprintf("There was no package called '%s'", leela))
    }
    unloadNamespace(leela)
  }
}

packagedelivery2(TRUE, "matrixStats")
colSds(matrix(rnorm(9), 3, 3))
# [1] 0.4954492 1.1789422 1.1264789

packagedelivery2(FALSE, "matrixStats")  ## first unload
colSds(matrix(rnorm(9), 3, 3))
# Error in colSds(matrix(rnorm(9), 3, 3)) : 
#   could not find function "colSds"

packagedelivery2(FALSE, "matrixStats")  ## second unload (package not loaded)
# There was no package called 'matrixStats'

packagedelivery2(TRUE, "fooPackage")
# Loading required package: fooPackage
# Warning message:
#   In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
#                there is no package called ‘fooPackage’

注意,require() 有一个不可见的输出,您可以使用它来安装丢失的包,只需查看this famous answer

【讨论】:

  • 这行得通,但是,我添加了一个额外的 grepl 参数来消除所有包含我的关键字的包。这表明某些包是相互依赖的,因此不能按顺序删除。我不知道比这更进一步是否可取或安全。
猜你喜欢
  • 2012-12-02
  • 2013-10-26
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 2023-03-08
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多