R version: 3.5.3, 3.6.3
更新日期: 2020-9-10html
你們測試後多提建議哈, 有問題我會持續更新的node
在工做中,咱們使用的服務器一般是不能聯外網的,這在安裝R包的時候產生了巨大的不便。網上有不少帖子使用tools::package_dependencies
這個工具下載依賴,可是這個工具是有坑的,相信嘗試過的同窗依然會發現有些依賴包在下載時被漏掉了,查了不少帖子,這個問題一直沒有很好的解決。web
今天,我就來解決這個問題,一來,方便本身,二來,服務他人。服務器
咱們就用R本身來解決本身的問題吧!網絡
在本地有網絡的環境中下載須要的R包:函數
library(rvest) library(stringi) library(stringr) dir <- 'c:/work/R/packages/' # 設置一個空目錄存放R包 pknames <- c('Seurat') # 這是想要安裝的包名稱,能夠設定多個包哦
第一個函數,用於生成repo的下載地址:工具
get_addr <- function(name,repo='https://cloud.r-project.org/'){ addr <- paste0(repo,'web/packages/',name,'/index.html') return(addr) }
第二個函數,得到一個包的次級依賴:測試
get_dep <- function(name){ addr <- get_addr(name) gettry <- try(page <- read_html(addr),silent = T) if('try-error' %in% class(gettry)){ return('-') } gettry <- try(pkg_table <- page %>% html_node("table") %>% html_table(fill = TRUE),silent = T) if('try-error' %in% class(gettry)){ return('-') } dep_pkgs1 <- c() dep_pkgs2 <- c() if(length(which(pkg_table[,1]=='Imports:'))>0 ){ tmp <- str_replace_all(pkg_table[which(pkg_table[,1]=='Imports:'),2],'\\(.*?\\)','') tmp <- str_split(tmp,'\\,')[[1]] tmp <- str_replace_all(tmp,'\\(.*\n.*\\)','') dep_pkgs1 <- trimws(tmp, which = c("both", "left", "right")) # return(dep_pkgs) } if( length(which(pkg_table[,1]=='LinkingTo:'))>0 ){ tmp <- str_replace_all(pkg_table[which(pkg_table[,1]=='LinkingTo:'),2],'\\(.*?\\)','') tmp <- str_split(tmp,'\\,')[[1]] tmp <- str_replace_all(tmp,'\\(.*\n.*\\)','') dep_pkgs2 <- trimws(tmp, which = c("both", "left", "right")) } if( length(dep_pkgs1)>0 & length(dep_pkgs2)>0 ){ return( c(dep_pkgs1,dep_pkgs2) ) }else if(length(dep_pkgs1)>0 & length(dep_pkgs2)==0){ return( dep_pkgs1 ) }else if(length(dep_pkgs1)==0 & length(dep_pkgs2)>0){ return( dep_pkgs2 ) }else{ return('-') } }
第三個函數,得到須要安裝的全部包的所有依賴:code
get_all_dep <- function(pknames){ all_list <- c() all_list <- c(all_list,pknames) top <- 1 for (i in 1:length(all_list)) { one <- get_dep(all_list[i]) if(all(one != '-')){ all_list <- c(all_list,one) } top <- top + 1 } while(top <= length(all_list)){ cat('finding dep of',all_list[top],'...\n') cat( 'length=',length(all_list),'\n' ) cat( 'top=',top,'\n' ) if( all_list[top] %in% all_list[(top+1):length(all_list)] ){ top <- top + 1 next }else{ one <- get_dep(all_list[top]) if(length(one) == 1 && one == '-'){ top <- top + 1 next }else{ all_list <- c(all_list,one) top <- top + 1 } } } res_list <- c() for (i in length(all_list):1) { if( ! all_list[i] %in% res_list ){ res_list <- c(all_list[i],res_list) } } return(res_list) }
好了,如今在聯網的環境下調用這個函數:htm
res <- get_all_dep(pknames) # 不要管報錯,沒啥問題
如今下載res
中的記錄的包,路徑就是dir
:
download.packages(res,destdir = dir) split_list <- str_split(list.files(dir),'_') download_pkgs1 <- unlist(split_list)[seq(1,length(split_list)*2,2)] download_pkgs2 <- unlist(split_list)[seq(2,length(split_list)*2,2)] res <- cbind(res,NA) for (i in 1:length(res[,1])) { if( res[i,1] %in% download_pkgs1 ){ name <- download_pkgs1[which(download_pkgs1 == res[i,1])] version <- download_pkgs2[which(download_pkgs1 == res[i,1])] res[i,2] <- paste0(name,'_',version ) } } save(res,file= paste0(dir,'install_list.RData') )
本地的工做結束了,如今將dir目錄打包上傳到服務器,用服務器上的R運行如下代碼,將服務器對應的目錄設置爲wdir
:
wdir <- '/home/you/packages/' load(file = paste0(wdir,'install_list.RData')) installed_packages <- row.names(installed.packages()) for (i in length(res[,1]):1) { if( res[i,1] %in% installed_packages | is.na(res[i,2]) ){ next }else{ install.packages(pkgs=paste0(wdir,res[i,2]),repos = NULL,type = 'source') } # a = readline('continue?') # if(a != ''){ # break # } # 這裏能夠註釋掉,我要裝131個包,一個個敲回車太累了,能夠先運行一遍,再去掉註釋運行一遍,以防某些依賴庫缺失的狀況 }
不出意外的話,全部的包就裝好了,反正個人好了哈哈,之後就用這個啦。