卸载(删除)具有依赖项的R包

TMS*_*TMS 30 r

我想尝试一些新包装.我安装它,它需要很多依赖,所以它安装了很多其他的包.我试过了,我没有留下深刻印象 - 现在我想卸载包括所有依赖项的包!

有没有办法删除给定的包,包括系统中任何其他包不需要的所有依赖项?

我看了,?remove.packages但没有选择这样做.

Tho*_*mas 18

这里有一些代码可以删除一个包及其不需要的依赖项.请注意,它对"不需要的"依赖包的解释是此包依赖的包的集合,但未在任何其他包中使用.这意味着它还默认建议卸载没有反向依赖关系的包.因此,我已将其实现为交互式菜单(如in update.packages),以便您控制要卸载的内容.

library("tools")

removeDepends <- function(pkg, recursive = FALSE){
    d <- package_dependencies(,installed.packages(), recursive = recursive)
    depends <- if(!is.null(d[[pkg]])) d[[pkg]] else character()
    needed <- unique(unlist(d[!names(d) %in% c(pkg,depends)]))
    toRemove <- depends[!depends %in% needed]
    if(length(toRemove)){
         toRemove <- select.list(c(pkg,sort(toRemove)), multiple = TRUE,
                                 title = "Select packages to remove")
         remove.packages(toRemove)
         return(toRemove)
    } else {
        invisible(character())
    }
}

# Example
install.packages("YplantQMC") # installs an unneeded dependency "LeafAngle"
c("YplantQMC","LeafAngle") %in% installed.packages()[,1]
## [1] TRUE TRUE
removeDepends("YplantQMC")
c("YplantQMC","LeafAngle")  %in% installed.packages()[,1]
## [1] FALSE FALSE
Run Code Online (Sandbox Code Playgroud)

注意:该recursive选项可能特别有用.如果包依赖性进一步依赖于其他不需要的包,则设置recursive = TRUE至关重要.如果依赖关系很浅(即依赖关系树中只有一个级别),则可以将其保留为FALSE(默认值).


And*_*rie 9

实际上remove.packages()在基本R中有一个函数,但它在包中utils,您需要先加载:

library(utils)
remove.packages()
Run Code Online (Sandbox Code Playgroud)

我不完全清楚这个函数做了多少递归清理.


Tyl*_*ker 6

baseR方法可以解决这个问题,但我会推荐一个包(我知道你正试图摆脱这些).我推荐这个包有两个原因(1)它解决了你遇到的两个问题&(2)Dason K.我正在开发这个包(完全披露).这个包的价值在于函数更容易记住一致的名称.它还做了一些组合操作.请注意,你可以在基础上完成所有这些,但这个问题已经非常本地化,因此我将使用一种工具,使回答更容易.

这个包将:

  1. 允许您删除包和依赖项
  2. 允许您在临时目录而不是主库中安装包

需要注意的是,您不能100%确定用户先前已安装的软件包依赖项尚未存在.因此,我会谨慎对待此解决方案的每一步,您不会删除重要的内容.该解决方案依赖于2个因素(1)pacman(2)file.info.我们假设在某个(用户定义的)时间阈值内修改的依赖关系确实是不需要的包.请注意这里的词假设.

我为家里的人们制作了这个可重现性,答案是从CRAN中随机安装一个带有附加依赖项的软件包(这将安装一个你本地没有3个或更多依赖项的软件包;随机使用不单独输出任何软件包).

制作一个可重复的例子

library(pacman)

(available <- p_cran())
(randoms <- setdiff(available,  p_lib()))
(mypackages <- p_lib())

ndeps <- 1
while(ndeps < 3) {

    package <- sample(randoms, 1)
    deps <- unlist(p_depends(package, character.only=TRUE), use.names=FALSE)
    ndeps <- length(setdiff(deps,  mypackages))

}  

package
p_install(package, character.only = TRUE)
Run Code Online (Sandbox Code Playgroud)

卸载包

我们将从第一部分分配包名称,package或者OP可以使用他们安装的不需要的包并将其分配给package(我的随机包恰好是package <- "OrdinalLogisticBiplot").理想情况下,此删除过程应在干净的R会话中完成,不加载附加包(除外pacman).

## function to grab file info date/time modified
infograb <- function(x) file.info(file.path(p_path(), x))[["mtime"]]

## determine the differences in times modified for "package" 
## and all other packages in library
diffs <- as.numeric(infograb(package)) -  sapply(p_lib(), infograb)

## user defined threshold
threshold <- 15

## determine packages just installed within the time frame of the unwanted package 
(delete_deps <- diffs[diffs < threshold & diffs >= 0])

## recursively find all packages that could have been installed 
potential_depends <- unlist(lapply(unlist(p_depends(package, character=TRUE)), 
    p_depends, character=TRUE, recursive=TRUE))

## delete packages that are both on the lists of (1) installed within time
## frame of unwanted package and a dependency of that package
p_delete(intersect(names(delete_deps), potential_depends), character.only = TRUE)
Run Code Online (Sandbox Code Playgroud)

这种方法做出了一些重大假设.

从一开始就有更好的方法

p_temp(package_to_try)
Run Code Online (Sandbox Code Playgroud)

这允许您先尝试一下,而不是让您的本地图书馆变得混乱.

如果您pacman对此不感兴趣,可以使用上述方法将其删除.