在R中工作时分离所有软件包


101

在解决另一个问题时,我遇到了这个问题:

我可以通过以下方法删除所有R对象:

rm(list = ls(all = TRUE))

是否有等效的命令可以在工作会话期间分离已安装的软件包?

> sessionInfo()
R version 2.12.2 (2011-02-25)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=English_United States.1252 
[2] LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base 

要求(ggplot2)

Loading required package: ggplot2
Loading required package: reshape
Loading required package: plyr

Attaching package: 'reshape'

The following object(s) are masked from 'package:plyr':

    round_any

Loading required package: grid
Loading required package: proto

sessionInfo()

R version 2.12.2 (2011-02-25)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=English_United States.1252 
[2] LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
[1] ggplot2_0.8.9 proto_0.3-9.1 reshape_0.8.4 plyr_1.4 

我尝试过这种方法,尽管即使它不能在全局解决方案中工作:

pkg <- c("package:ggplot2_0.8.9", "package:proto_0.3-9.1", "package:reshape_0.8.4",  "package:plyr_1.4")

 detach(pkg, character.only = TRUE)

Error in detach(pkg, character.only = TRUE) : invalid 'name' argument
In addition: Warning message:
In if (is.na(pos)) stop("invalid 'name' argument") :
  the condition has length > 1 and only the first element will be used

我想要的是全球性的东西:

  rm(list = ls(all = TRUE))

对于对象,期望它不会删除附加的基本包

谢谢;


3
并非您的问题无效,但为什么不重新启动R?
亚伦(Aaron)

5
@Aaron,因为您不应该这样做;-)传递R CMD check一个包应该可以完全卸载自身,因此R Core希望这样做是可行的,并且有人希望这样做。
加文·辛普森,

@Aaron,我认为有时候在某些程序包引起或可能引起干扰的情况下让会话继续进行很有用,但在先前的步骤中使用了这些方法
John Clark

5
无法将R返回到新的状态。我已经与约翰·钱伯斯(John Chambers)讨论过这一点,对于S4类/方法注册,这尤其困难。
hadley 2011年

Answers:


98

因此,有人应该简单地回答以下问题。

lapply(paste('package:',names(sessionInfo()$otherPkgs),sep=""),detach,character.only=TRUE,unload=TRUE)

(编辑:6-28-19)在最新版本的R 3.6.0中,请改用。

invisible(lapply(paste0('package:', names(sessionInfo()$otherPkgs)), detach, character.only=TRUE, unload=TRUE))

请注意,不需要使用invisible(*),但对于防止NULL回复垂直向R窗口发送垃圾邮件非常有用。

(编辑:9/20/2019)在3.6.1版中

names(sessionInfo()$loadedOnly)先将仅加载的文件转换为显式附加的程序包,然后再分离这些程序包可能会有所帮助。

lapply(names(sessionInfo()$loadedOnly), require, character.only = TRUE)
invisible(lapply(paste0('package:', names(sessionInfo()$otherPkgs)), detach, character.only=TRUE, unload=TRUE, force=TRUE))

可以尝试通过$ basePkgs卸载基本软件包,也可以尝试使用unloadNamespace(loadedNamespaces())。但是,这些通常充满错误,并且可能破坏基本功能,例如导致sessionInfo()仅返回错误。这通常是由于原始包装设计中缺乏可逆性而发生的。timeDate例如,当前可能无法恢复。


3
我认为,由于其简单性,因此值得推荐,并且不需要其他软件包。
Antonio Serrano

这对我没有用。我运行它得到警告,然后运行session.info()所有包仍然存在。
dxander

1
是的,在最新版本的R 3.6.0中,应该使用以下内容。invisible(lapply(paste0('package:',names(sessionInfo()$ otherPkgs)),detach,character.only = TRUE,unload = TRUE))请注意,不需要使用invisible(*)但可以防止NULL垂直向窗口发送垃圾邮件。
mmfrgmpds

使用invisible(lapply(paste0('package:', names(sessionInfo()$otherPkgs)), detach, character.only=TRUE, unload=TRUE))结果Error in FUN(X[[i]], ...) : invalid 'name' argument出错
dvanic

Error in FUN(X[[i]], ...)...仅存在NULL值时,经常发生该错误。可以使用进行测试names(sessionInfo()$otherPkgs)。如果返回NULL,这就是原因。
mmfrgmpds

57

请尝试以下方法:

detachAllPackages <- function() {

  basic.packages <- c("package:stats","package:graphics","package:grDevices","package:utils","package:datasets","package:methods","package:base")

  package.list <- search()[ifelse(unlist(gregexpr("package:",search()))==1,TRUE,FALSE)]

  package.list <- setdiff(package.list,basic.packages)

  if (length(package.list)>0)  for (package in package.list) detach(package, character.only=TRUE)

}

detachAllPackages()

4
以防万一您搞砸了plyrdplyr这似乎是唯一的方法。谢谢!
JelenaČuklina

29

你近了 请注意?detach关于第一个参数name的说明detach()

参数:

name: The object to detach.  Defaults to ‘search()[pos]’.  This can
      be an unquoted name or a character string but _not_ a
      character vector.  If a number is supplied this is taken as
      ‘pos’.

因此,我们需要为的detach()每个元素重复调用一次pkg。为了使它起作用,我们需要指定其他几个参数。第一个是character.only = TRUE,它允许函数假定它name是一个字符串-没有它就无法工作。其次,我们可能还希望卸载任何关联的名称空间。可以通过设置来实现unload = TRUE。因此,解决方案是例如:

pkg <- c("package:vegan","package:permute")
lapply(pkg, detach, character.only = TRUE, unload = TRUE)

这是一个完整的示例:

> require(vegan)
Loading required package: vegan
Loading required package: permute
This is vegan 2.0-0
> sessionInfo()
R version 2.13.1 Patched (2011-09-13 r57007)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_GB.utf8       LC_NUMERIC=C             
 [3] LC_TIME=en_GB.utf8        LC_COLLATE=en_GB.utf8    
 [5] LC_MONETARY=C             LC_MESSAGES=en_GB.utf8   
 [7] LC_PAPER=en_GB.utf8       LC_NAME=C                
 [9] LC_ADDRESS=C              LC_TELEPHONE=C           
[11] LC_MEASUREMENT=en_GB.utf8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods  
[7] base     

other attached packages:
[1] vegan_2.0-0   permute_0.7-0

loaded via a namespace (and not attached):
[1] grid_2.13.1     lattice_0.19-33 tools_2.13.1   
> pkg <- c("package:vegan","package:permute")
> lapply(pkg, detach, character.only = TRUE, unload = TRUE)
[[1]]
NULL

[[2]]
NULL

> sessionInfo()
R version 2.13.1 Patched (2011-09-13 r57007)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_GB.utf8       LC_NUMERIC=C             
 [3] LC_TIME=en_GB.utf8        LC_COLLATE=en_GB.utf8    
 [5] LC_MONETARY=C             LC_MESSAGES=en_GB.utf8   
 [7] LC_PAPER=en_GB.utf8       LC_NAME=C                
 [9] LC_ADDRESS=C              LC_TELEPHONE=C           
[11] LC_MEASUREMENT=en_GB.utf8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods  
[7] base     

loaded via a namespace (and not attached):
[1] grid_2.13.1     lattice_0.19-33 tools_2.13.1

如果要将其转换为函数,请研究其中的代码sessionInfo()以查看其如何标识被标记为“其他附加包:”的内容。将这些代码与上面的想法结合在一个函数中,您将无所事事。不过,我会留给您。


12
您可以通过添加pkgs = names(sessionInfo()$otherPkgs)pkgs = paste('package:', pkgs, sep = "")
Ramnath

2
@Ramnath +1确实是-但我不想帮忙;-)
Gavin Simpson

4
您可能还需要添加force=TRUE以防软件包具有依赖关系。
詹姆斯

26

nothing

可能值得添加RomainFrançois提供的解决方案。加载后,该软件包nothing(当前可在GitHub上下载)将卸载所有已加载的软件包。如Romain提供的示例:

loadedNamespaces()
[1] "base"      "datasets"  "grDevices" "graphics"  "methods"   "stats"
[7] "utils"

require(nothing, quietly = TRUE)

loadedNamespaces()
[1] "base"

安装

使用devtools包装:

devtools::install_github("romainfrancois/nothing")

pacman

一种替代方法是使用pacman可通过CRAN获得的软件包:

pacman::p_unload(pacman::p_loaded(), character.only = TRUE)

4
看着小插图(trinker.github.io/pacman/vignettes/Introduction_to_pacman.html)也许pacman::p_unload("all")也可以工作吗?
钱德勒

10

建立在加文的答案之上但并不完全是完整的功能,将是以下顺序:

sess.pkgs <- function (package = NULL) 
{   z <- list()
       if (is.null(package)) {
        package <- grep("^package:", search(), value = TRUE)
        keep <- sapply(package, function(x) x == "package:base" || 
            !is.null(attr(as.environment(x), "path")))
        package <- sub("^package:", "", package[keep])
    }
    pkgDesc <- lapply(package, packageDescription)
    if (length(package) == 0) 
        stop("no valid packages were specified")
    basePkgs <- sapply(pkgDesc, function(x) !is.null(x$Priority) && 
        x$Priority == "base")
    z$basePkgs <- package[basePkgs]
    if (any(!basePkgs)) {
        z$otherPkgs <-  package[!basePkgs]
    }
    z
}

lapply(paste("package:",sess.pkgs()$otherPkgs, sep=""), detach, 
                             character.only = TRUE, unload = TRUE)

2
我可以单线地以某种方式做同样的事情lapply(paste("package:", names(sessionInfo()$otherPkgs), sep=""), detach, character.only = TRUE, unload = TRUE)。如果没有您的回答,将永远无法到达那里!
Ufos

4

或者,如果您拥有RStudio,只需取消选中“软件包”选项卡中的所有复选框即可分离


1
如果您有很多已加载的软件包,那么手动取消选中每个软件包将很麻烦。
斯波江

3
#Detach all  packages
detachAllPackages <- function() {

  basic.packages <- c("package:stats","package:graphics","package:grDevices","package:utils","package:datasets","package:methods","package:base")

  package.list <- search()[ifelse(unlist(gregexpr("package:",search()))==1,TRUE,FALSE)]

  package.list <- setdiff(package.list,basic.packages)

  if (length(package.list)>0)  for (package in package.list) detach(package, character.only=TRUE)

}

detachAllPackages()

这样可以确保将所有软件包与基本软件包分开


与@mjaniec答案有
什么

1

大多数情况下,它是plyrvs dplyr问题。在代码开头使用此代码:

detach("package:plyr", unload=TRUE)

因此,每当脚本运行时,它都会清除plyr程序包


0

如果您在名称相似的函数相互冲突的程序包中遇到问题,则始终可以引用您想要的函数的程序包的名称空间。

pkg_name::function_i_want()

这是评论,而不是对所提问题的答案。
锡伯江

假设我应该将此设置为先前的plyr v。dplyr答案的注释,是否可以移动它?我仍在这里学习惯例。
M. Wood,

0

结合各种答案中的一些内容,可以找到我能找到的最强大的解决方案...

packs <- c(names(sessionInfo()$otherPkgs), names(sessionInfo()$loadedOnly))
if(length(packs) > 0){ 
  message('Unloading packages -- if any problems occur, please try this from a fresh R session')
  while(length(packs) > 0){
    newpacks <- c()
    for(packi in 1:length(packs)){
      u=try(unloadNamespace(packs[packi]))
      if(class(u) %in% 'try-error') newpacks <- c(newpacks,packs[packi])
    }
    packs <- newpacks
    Sys.sleep(.1)
  }
}
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.