簡體   English   中英

卸載(刪除)具有依賴項的 R 包

[英]Uninstall (remove) R package with dependencies

我想嘗試一些新的包。 我安裝了它,它需要很多依賴項,所以它安裝了很多其他包。 我試過了,並沒有給我留下深刻的印象 - 現在我想卸載包括所有依賴項在內的包!

有沒有辦法刪除給定的包,包括系統中任何其他包不需要的所有依賴項?

我查看了?remove.packages但沒有選擇這樣做。

這里有一些代碼可以讓你刪除一個包及其不需要的依賴項。 請注意,它對“不需要的”依賴包的解釋是該包所依賴但未在任何其他包中使用的包的集合。 這意味着它也會默認建議卸載沒有反向依賴關系的包。 因此,我將它實現為交互式菜單(如在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

注意: recursive選項可能特別有用。 如果包依賴進一步依賴於其他不需要的包,設置recursive = TRUE是至關重要的。 如果依賴關系很淺(即,僅在依賴關系樹下一級),則可以將其保留為FALSE (默認值)。

實際上有一個函數remove.packages()在基礎 R 中,但它在包utils ,您需要先加載它:

library(utils)
remove.packages()

我並不完全清楚這個函數做了多少遞歸清理。

有一些base R 方法來處理這個問題,但我將推薦一個包(我知道你正試圖擺脫這些)。 我推薦這個包有兩個原因 (1) 它解決了你遇到的兩個問題 & (2) Dason K. 我正在開發這個包(完全披露)。 這個包的價值在於函數更容易記住一致的名稱。 它還執行一些組合操作。 請注意,您可以在 base 中完成所有這些操作,但這個問題已經非常本地化,因此我將使用一種工具來簡化回答。

這個包將:

  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)

卸載包

我們將第一部分中的包名稱分配給package或者 OP 可以使用他們安裝的不需要的包並將其分配給package (我的隨機包碰巧是package <- "OrdinalLogisticBiplot" )。 理想情況下,這個刪除過程應該在沒有加載附加包( pacman除外)的干凈 R 會話中完成。

## 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)

這種方法做出了一些重大假設。

從一開始就采用更好的方法

p_temp(package_to_try)

這使您可以先嘗試一下,而不會將它弄臟您的本地圖書館。

如果您對pacman ,可以使用上述方法將其刪除。

這是查看任何其他本地安裝的軟件包不需要的軟件包的快速解決方案。

library(pacman)
ip <- installed.packages()[,1]
deps <- lapply(1:length(ip), function(i) tryCatch(p_depends(ip[i], local = TRUE)$Imports, error = function(e) return(NULL)))
packages.on.which.things.depend <- sort(unique(unlist(deps)))
packages.on.which.nothing.depends <- setdiff(ip, packages.on.which.things.depend)
packages.on.which.nothing.depends

然后,快速查看它並刪除您不使用的那些(請小心,不要嘗試卸載base )。

在確定使用哪些和不使用哪些之后,您可以繼續進行類似的操作

i.need <- c("AER", "car", "devtools", "glmnet", "gmm", "Hmisc", "pacman", "plm", "RcppArmadillo", "RcppEigen", "rmarkdown", "rugarch", "base", "datasets")
un <- setdiff(packages.on.which.nothing.depends, i.need)
un
remove.packages(un)

沖洗並重復,直到沒有不需要的孤兒包。 R 不應允許您刪除內置系統包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM