Modo elegante per verificare la mancanza di pacchetti e installarli?

In questi giorni sembra che condivido molto codice con i coautori. Molti di loro sono utenti principianti / intermedi R e non si rendono conto che devono installare pacchetti che non hanno già.

C’è un modo elegante per chiamare installed.packages() , confrontarlo con quelli che sto caricando e installando se mancante?

Sì. Se hai il tuo elenco di pacchetti, confrontalo con l’output di installed.packages()[,"Package"] e installa i pacchetti mancanti. Qualcosa come questo:

 list.of.packages < - c("ggplot2", "Rcpp") new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])] if(length(new.packages)) install.packages(new.packages) 

Altrimenti:

Se inserisci il tuo codice in un pacchetto e ne crei dipendenze, verranno automaticamente installati al momento dell'installazione del pacchetto.

Dason K. e io abbiamo il pacchetto pacman che può farlo bene. La funzione p_load nel pacchetto fa questo. La prima riga serve solo a garantire che Pacman sia installato.

 if (!require("pacman")) install.packages("pacman") pacman::p_load(package1, package2, package_n) 

Puoi semplicemente usare il valore di ritorno di require :

 if(!require(somepackage)){ install.packages("somepackage") library(somepackage) } 

Uso la library dopo l’installazione perché genera un’eccezione se l’installazione non ha avuto successo o il pacchetto non può essere caricato per qualche altro motivo. Rendi questo più robusto e riutilizzabile:

 dynamic_require < - function(package){ if(eval(parse(text=paste("require(",package,")")))) return True install.packages(package) return eval(parse(text=paste("require(",package,")"))) } 

Lo svantaggio di questo metodo è che devi passare il nome del pacchetto tra virgolette, cosa che non fai per il vero require .

Sebbene la risposta di Shane sia davvero buona, per uno dei miei progetti ho dovuto rimuovere i messaggi di output, gli avvisi e installare i pacchetti in modo automatico . Sono finalmente riuscito a ottenere questo script:

 InstalledPackage < - function(package) { available <- suppressMessages(suppressWarnings(sapply(package, require, quietly = TRUE, character.only = TRUE, warn.conflicts = FALSE))) missing <- package[!available] if (length(missing) > 0) return(FALSE) return(TRUE) } CRANChoosen < - function() { return(getOption("repos")["CRAN"] != "@CRAN@") } UsePackage <- function(package, defaultCRANmirror = "http://cran.at.r-project.org") { if(!InstalledPackage(package)) { if(!CRANChoosen()) { chooseCRANmirror() if(!CRANChoosen()) { options(repos = c(CRAN = defaultCRANmirror)) } } suppressMessages(suppressWarnings(install.packages(package))) if(!InstalledPackage(package)) return(FALSE) } return(TRUE) } 

Uso:

 libraries < - c("ReadImages", "ggplot2") for(library in libraries) { if(!UsePackage(library)) { stop("Error!", library) } } 

Questa soluzione prenderà un vettore di caratteri con nomi di pacchetti e tenterà di caricarli, oppure installarli se il caricamento fallisce. Si basa sul comportamento di ritorno di require di fare questo perché …

require resi (invisibili) un logico che indica se il pacchetto richiesto è disponibile

Quindi possiamo semplicemente vedere se siamo stati in grado di caricare il pacchetto richiesto e, in caso contrario, installarlo con le dipendenze. Quindi, dato un vettore di caratteri di pacchetti che desideri caricare …

 foo < - function(x){ for( i in x ){ # require returns TRUE invisibly if it was able to load package if( ! require( i , character.only = TRUE ) ){ # If package was not able to be loaded then re-install install.packages( i , dependencies = TRUE ) # Load package after installing require( i , character.only = TRUE ) } } } # Then try/install packages... foo( c("ggplot2" , "reshape2" , "data.table" ) ) 
 if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2') 

“ggplot2” è il pacchetto. Controlla se il pacchetto è installato, se non lo installa lo installa. Quindi carica il pacchetto indipendentemente dal ramo utilizzato.

Molte delle risposte sopra (e sui duplicati di questa domanda) si basano su pacchetti installed.packages che sono di ctriggers forma. Dalla documentazione:

Questo può essere lento quando si installano migliaia di pacchetti, quindi non usare questo per scoprire se un pacchetto con nome è installato (usa system.file o find.package) né per sapere se un pacchetto è utilizzabile (la chiamata richiede e controlla il valore di ritorno) né per trovare i dettagli di un piccolo numero di pacchetti (utilizzare packageDescription). Ha bisogno di leggere diversi file per pacchetto installato, che sarà lento su Windows e su alcuni file system montati in rete.

Quindi, un approccio migliore è provare a caricare il pacchetto usando require e installarlo se il caricamento non riesce (il comando require FALSE se non viene trovato). Preferisco questa implementazione:

 using< -function(...) { libs<-unlist(list(...)) req<-unlist(lapply(libs,require,character.only=TRUE)) need<-libs[req==FALSE] if(length(need)>0){ install.packages(need) lapply(need,require,character.only=TRUE) } } 

che può essere usato in questo modo:

 using("RCurl","ggplot2","jsonlite","magrittr") 

In questo modo carica tutti i pacchetti, quindi torna indietro e installa tutti i pacchetti mancanti (che se vuoi, è un posto comodo dove inserire un prompt per chiedere se l’utente vuole installare i pacchetti). Invece di chiamare install.packages separatamente per ogni pacchetto, passa l’intero vettore di pacchetti disinstallati una sola volta.

Ecco la stessa funzione ma con una finestra di dialogo di Windows che chiede se l’utente vuole installare i pacchetti mancanti

 using< -function(...) { libs<-unlist(list(...)) req<-unlist(lapply(libs,require,character.only=TRUE)) need<-libs[req==FALSE] n<-length(need) if(n>0){ libsmsg< -if(n>2) paste(paste(need[1:(n-1)],collapse=", "),",",sep="") else need[1] print(libsmsg) if(n>1){ libsmsg< -paste(libsmsg," and ", need[n],sep="") } libsmsg<-paste("The following packages could not be found: ",libsmsg,"\n\r\n\rInstall missing packages?",collapse="") if(winDialog(type = c("yesno"), libsmsg)=="YES"){ install.packages(need) lapply(need,require,character.only=TRUE) } } } 
 # List of packages for session .packages = c("ggplot2", "plyr", "rms") # Install CRAN packages (if not already installed) .inst < - .packages %in% installed.packages() if(length(.packages[!.inst]) > 0) install.packages(.packages[!.inst]) # Load packages into session lapply(.packages, require, character.only=TRUE) 

Sicuro.

È necessario confrontare “pacchetti installati” con “pacchetti desiderati”. Questo è molto vicino a quello che faccio con CRANberries, perché ho bisogno di confrontare “pacchetti conosciuti memorizzati” con “pacchetti attualmente conosciuti” per determinare pacchetti nuovi e / o aggiornati.

Quindi fai qualcosa come

 AP < - available.packages(contrib.url(repos[i,"url"])) # available t repos[i] 

per ottenere tutti i pacchetti noti, chiamate simulari per i pacchetti attualmente installati e confrontarli con un determinato set di pacchetti di destinazione.

Questo è lo scopo del pacchetto rbundler : fornire un modo per controllare i pacchetti installati per un progetto specifico. In questo momento il pacchetto funziona con la funzionalità devtools per installare i pacchetti nella directory del progetto. La funzionalità è simile al bundler di Ruby.

Se il tuo progetto è un pacchetto (consigliato), allora tutto ciò che devi fare è caricare rbundler e raggruppare i pacchetti. La funzione bundle esaminerà il file DESCRIPTION del pacchetto per determinare quali pacchetti raggruppare.

 library(rbundler) bundle('.', repos="http://cran.us.r-project.org") 

Ora i pacchetti verranno installati nella directory .Rbundle.

Se il tuo progetto non è un pacchetto, allora puoi simularlo creando un file DESCRIPTION nella directory radice del tuo progetto con un campo Depends che elenca i pacchetti che vuoi installare (con le informazioni sulla versione opzionale):

 Depends: ggplot2 (>= 0.9.2), arm, glmnet 

Ecco il repository github per il progetto se sei interessato a contribuire: rbundler .

La seguente semplice funzione funziona come un fascino:

  usePackage< -function(p){ # load a package if installed, else load after installation. # Args: # p: package name in quotes if (!is.element(p, installed.packages()[,1])){ print(paste('Package:',p,'Not found, Installing Now...')) install.packages(p, dep = TRUE)} print(paste('Loading Package :',p)) require(p, character.only = TRUE) } 

(non mio, ho trovato questo sul web qualche tempo fa e lo usavo da allora. Non sono sicuro della fonte originale)

Io uso la seguente funzione per installare il pacchetto se require("") termina con errore non trovato del pacchetto. Interrogherà entrambi i repository CRAN e Bioconductor per il pacchetto mancante.

Tratto dal lavoro originale di Joshua Wiley, http://r.789695.n4.nabble.com/Install-package-automatically-if-not-there-td2267532.html

 install.packages.auto < - function(x) { x <- as.character(substitute(x)) if(isTRUE(x %in% .packages(all.available=TRUE))) { eval(parse(text = sprintf("require(\"%s\")", x))) } else { #update.packages(ask= FALSE) #update installed packages. eval(parse(text = sprintf("install.packages(\"%s\", dependencies = TRUE)", x))) } if(isTRUE(x %in% .packages(all.available=TRUE))) { eval(parse(text = sprintf("require(\"%s\")", x))) } else { source("http://bioconductor.org/biocLite.R") #biocLite(character(), ask=FALSE) #update installed packages. eval(parse(text = sprintf("biocLite(\"%s\")", x))) eval(parse(text = sprintf("require(\"%s\")", x))) } } 

Esempio:

 install.packages.auto(qvalue) # from bioconductor install.packages.auto(rNMF) # from CRAN 

PS: update.packages(ask = FALSE) e biocLite(character(), ask=FALSE) aggiornerà tutti i pacchetti installati sul sistema. Questo può richiedere molto tempo e considerarlo come un aggiornamento R completo che potrebbe non essere garantito per tutto il tempo!

Puoi semplicemente usare la funzione setdiff per ottenere i pacchetti che non sono installati e quindi installarli. Nell’esempio seguente, controlliamo se i pacchetti ggplot2 e Rcpp sono installati prima di installarli.

 unavailable < - setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())) install.packages(unavailable) 

In una riga, quanto sopra può essere scritto come:

 install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))) 

Ho implementato la funzione per installare e caricare silenziosamente i pacchetti R richiesti. La speranza potrebbe aiutare. Ecco il codice:

 # Function to Install and Load R Packages Install_And_Load < - function(Required_Packages) { Remaining_Packages <- Required_Packages[!(Required_Packages %in% installed.packages()[,"Package"])]; if(length(Remaining_Packages)) { install.packages(Remaining_Packages); } for(package_name in Required_Packages) { library(package_name,character.only=TRUE,quietly=TRUE); } } # Specify the list of required packages to be installed and load Required_Packages=c("ggplot2", "Rcpp"); # Call the Function Install_And_Load(Required_Packages); 

Riguardo al tuo objective principale “installare librerie che non hanno già” e indipendentemente dall’uso di “instllaed.packages ()”. La seguente funzione maschera la funzione originale di require. Prova a caricare e controllare il pacchetto denominato “x”, se non è installato, installarlo direttamente includendo le dipendenze; e infine caricarlo normalmente. si rinomina il nome della funzione da ‘require’ a ‘library’ per mantenere l’integrità. L’unica limitazione è che i nomi dei pacchetti devono essere citati.

 require < - function(x) { if (!base::require(x, character.only = TRUE)) { install.packages(x, dep = TRUE) ; base::require(x, character.only = TRUE) } } 

Quindi puoi caricare e installare il pacchetto in modo che la vecchia maniera di R. richieda ("ggplot2") require ("Rcpp")

Abbastanza di base.

 pkgs = c("pacman","data.table") if(length(new.pkgs < - setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs) 

Ho pensato di contribuire con quello che uso:

 testin < - function(package){if (!package %in% installed.packages()) install.packages(package)} testin("packagename") 

Usa packrat modo che le librerie condivise siano esattamente le stesse e non packrat l’ambiente altrui.

In termini di eleganza e buone pratiche, penso che fondamentalmente tu stia andando nel modo sbagliato. il pacchetto packrat stato progettato per questi problemi. È sviluppato da RStudio da Hadley Wickham. Invece di dover installare dipendenze e possibilmente rovinare l’ambiente di qualcuno, system packrat usa la propria directory e installa tutte le dipendenze per i propri programmi e non tocca l’ambiente di qualcuno.

Packrat è un sistema di gestione delle dipendenze per R.

Le dipendenze del pacchetto R possono essere frustranti. Hai mai dovuto usare trial-and-error per capire quali pacchetti R devi installare per far funzionare il codice di qualcun altro, e poi essere lasciato con quei pacchetti installati a livello globale per sempre, perché ora non sei sicuro se ne hai bisogno ? Hai mai aggiornato un pacchetto per far funzionare il codice in uno dei tuoi progetti, solo per scoprire che il pacchetto aggiornato rende il codice in un altro progetto smesso di funzionare?

Abbiamo creato packrat per risolvere questi problemi. Usa packrat per rendere i tuoi progetti R più:

  • Isolato: l’installazione di un pacchetto nuovo o aggiornato per un progetto non infrange gli altri progetti e viceversa. Questo perché packrat offre a ciascun progetto la propria libreria di pacchetti privata.
  • Portatile: trasporta facilmente i tuoi progetti da un computer a un altro, anche su piattaforms diverse. Packrat semplifica l’installazione dei pacchetti da cui dipende il tuo progetto.
  • Riproducibile: Packrat registra le esatte versioni del pacchetto da cui dipende e garantisce che quelle versioni esatte siano quelle che vengono installate ovunque tu vada.

https://rstudio.github.io/packrat/

Io uso quanto segue che controllerà se il pacchetto è installato e se le dipendenze sono aggiornate, quindi carica il pacchetto.

 p< -c('ggplot2','Rcpp') install_package<-function(pack) {if(!(pack %in% row.names(installed.packages()))) { update.packages(ask=F) install.packages(pack,dependencies=T) } require(pack,character.only=TRUE) } for(pack in p) {install_package(pack)} completeFun <- function(data, desiredCols) { completeVec <- complete.cases(data[, desiredCols]) return(data[completeVec, ]) } 

Ecco il mio codice per questo:

 packages < - c("dplyr", "gridBase", "gridExtra") package_loader <- function(x){ for (i in 1:length(x)){ if (!identical((x[i], installed.packages()[x[i],1])){ install.packages(x[i], dep = TRUE) } else { require(x[i], character.only = TRUE) } } } package_loader(packages) 
  48 lapply_install_and_load < - function (package1, ...) 49 { 50 # 51 # convert arguments to vector 52 # 53 packages <- c(package1, ...) 54 # 55 # check if loaded and installed 56 # 57 loaded <- packages %in% (.packages()) 58 names(loaded) <- packages 59 # 60 installed <- packages %in% rownames(installed.packages()) 61 names(installed) <- packages 62 # 63 # start loop to determine if each package is installed 64 # 65 load_it <- function (p, loaded, installed) 66 { 67 if (loaded[p]) 68 { 69 print(paste(p, "loaded")) 70 } 71 else 72 { 73 print(paste(p, "not loaded")) 74 if (installed[p]) 75 { 76 print(paste(p, "installed")) 77 do.call("library", list(p)) 78 } 79 else 80 { 81 print(paste(p, "not installed")) 82 install.packages(p) 83 do.call("library", list(p)) 84 } 85 } 86 } 87 # 88 lapply(packages, load_it, loaded, installed) 89 } 
 library < - function(x){ x = toString(substitute(x)) if(!require(x,character.only=TRUE)){ install.packages(x) base::library(x,character.only=TRUE) }} 

Funziona con nomi di pacchetti non quotati ed è abbastanza elegante (vedere la risposta di GeoObserver)

 source("https://bioconductor.org/biocLite.R") if (!require("ggsci")) biocLite("ggsci") 

Nel mio caso, volevo un solo liner che potessi eseguire dalla riga di comando (in realtà tramite un Makefile). Ecco un esempio di installazione di “VGAM” e “feather” se non sono già installati:

 R -e 'for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")' 

Da dentro R sarebbe solo:

 for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org") 

Non c’è niente qui oltre le soluzioni precedenti tranne che:

  • Lo tengo a una sola riga
  • Ho programmato con cura il parametro repos (per evitare qualsiasi popup che chiedesse informazioni sul mirror da usare)
  • Non mi preoccupo di definire una funzione da utilizzare altrove

Nota anche l’importante character.only=TRUE (senza di essa, il require proverà a caricare il pacchetto p ).

Utilizzando la famiglia lapply e l’approccio alla funzione anonima puoi:

  lib.names < - c("plyr", "psych", "tm") sapply(lib.names, function(x) require(x, character.only = TRUE) || {install.packages(x); require(x, character.only = TRUE)}) plyr psych tm TRUE TRUE TRUE 
  1. Prova ad albind tutti i pacchetti elencati.
  2. Installa solo mancante (usando || valutazione lazy).
  3. Carica quelli mancanti / appena installati.
  4. Stampa un riepilogo totale (VERO / FALSO) dello stato di caricamento di ciascun pacchetto.

prova questo:

 if (!require(MyDesiredLibrary)) { install.packages("MyDesiredLibrary") }