2010-11-03 12 views
203

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à.Modo elegante per verificare la presenza di pacchetti mancanti e installarli?

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

+1

@krlmlr E la risposta accettata non è aggiornata e richiede una revisione? Funziona per me (per alcuni test rapidi) sotto 'R versione 3.0.2 (2013-09-25) x86_64-w64-mingw32/x64 (64-bit)'. –

+1

@BrianDiggs: sono comparsi almeno tre pacchetti che risolvono questo problema, solo uno è referenziato di seguito. C'è ancora di più - questa è la domanda. – krlmlr

+2

@krlmlr Sembra esserci un po 'di ironico problema di pollo e uova sull'utilizzo di un pacchetto per garantire (altri) pacchetti necessari. Ma certamente vale la pena di avere una persona che sa di loro scrivere una risposta. –

risposta

193

Sì. Se hai il tuo elenco di pacchetti, confrontalo con l'output di installed.packages()[,"Package"] e installa i pacchetti mancanti. Qualcosa di simile a 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 mettete il vostro codice in un pacchetto e renderli dipendenze, allora verrà installato automaticamente quando si installa il pacchetto.

+6

Penso che la sintassi corretta sia: ' if (length (new.packages)> 0) {install.packages (new.packages) } ' –

+3

@psql, Shine ha ragione, poiché"> 0 "è" implicito "nella condizione if. esegui questo per verificarlo: 'new.packages <- c (1,2)' 'lunghezza (nuovi.packages)' 'if (length (new.packages)) {print (" ciao! ") } else {print ("oh no!")} ' –

+5

Il documento di installed.packages afferma:" Questo può essere lento quando sono installati migliaia di pacchetti, quindi non usare questo per scoprire se un pacchetto con nome è installato (usare system.file o find.package) ... " –

5

Sicuro.

È necessario confrontare "pacchetti installati" con "pacchetti desiderati". Questo è molto vicino a quello che faccio con CRANberries in quanto ho bisogno di confrontare "pacchetti conosciuti memorizzati" con "pacchetti attualmente conosciuti" per determinare pacchetti nuovi e/o aggiornati.

Quindi fare qualcosa di simile

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

per ottenere tutti i pacchetti noti, call simular per i pacchetti attualmente installati e si confronti con un dato insieme di pacchetti di destinazione.

15

Sebbene la risposta di Shane sia davvero buona, per uno dei miei progetti ho dovuto rimuovere i messaggi di uscita, gli avvisi e installare i pacchetti automaticamente. 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"] != "@[email protected]") 
} 

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

Usa:

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

Io uso il seguente che controllerà se il pacchetto è installato e se le dipendenze sono aggiornati, 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, ]) 
} 
5

Questo è lo scopo della rbundler package: 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 a quella di Ruby bundler.

Se il progetto è un pacchetto (consigliato), tutto ciò che dovete 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 progetto non è un pacchetto, allora si può fingere con la creazione di un file DESCRIPTION nella directory principale del progetto con un campo Depends in cui sono elencati i pacchetti che si desidera installare (opzionale informazioni sulla versione):

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

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

10

Questa soluzione richiederà un vettore di caratteri dei nomi dei pacchetti e tenta di caricarli oppure installarli se il caricamento non riesce. Essa si basa sul comportamento ritorno di require di fare questo perché ...

require rendimenti (invisibile) di un logico che indica se il pacchetto richiesto è disponibile

Quindi possiamo semplicemente vedere se siamo sono stati in grado di caricare il pacchetto richiesto e, in caso contrario, installarlo con le dipendenze. Quindi, dato un vettore carattere di pacchetti che si desidera 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")) 
+0

Non vorresti richiamare 'require' di nuovo dopo l'installazione? – krlmlr

+0

@krlmlr No, perché affinché l'istruzione 'if' sia valutata deve prima valutare' require', il cui effetto collaterale sta caricando il pacchetto se è disponibile! –

+1

SimonO101: Penso che krlmlr significhi nell'istruzione if, dopo la chiamata a 'install.packages', in quanto in realtà non caricarebbe quel pacchetto. Ma (a @krlmlr) sospetto che l'intento sia che questo frammento di codice venga chiamato una sola volta; non lo scriverai ogni volta che hai richiesto il pacchetto. Invece lo eseguirai una volta prima e poi chiamerai 'require' come al solito, se necessario. – Aaron

37

Si può semplicemente utilizzare il valore di ritorno di require:

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

Io uso library dopo l'installazione perché sarà un'eccezione se l'installazione non ha avuto successo o il pacchetto non può essere caricato per qualche altro motivo. Fate questo più robusto e riutilizzabili:

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

    install.packages(package) 
    return eval(parse(text=paste("require(",package,")"))) 
} 

L'aspetto negativo di questo metodo è che si deve passare il nome del pacchetto tra virgolette, che non si fanno per il vero require.

+1

Puoi semplificare la tua vita molto usando 'character.only = TRUE' in' require', ma poi immagino che non ci sia nulla che possa differenziare la tua risposta dalla mia. –

+0

Che cos'è "[Questa risposta]"? – Mars

+0

@Mars Penso che sia stato un collegamento a una risposta che non esiste più (o forse un collegamento che non è mai esistito perché ho dimenticato di riempirlo nuovamente). – Livius

136

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) 
+10

Sembra un pacchetto utile lì. Tutti dovrebbero dirlo ai loro amici! – Dason

+1

Qual è lo stato del pacchetto? Non riesco a vedere in C-RAN. – MERose

+1

@Dason e io siamo stati piuttosto impegnati con la scrittura della tesi. Abbiamo deciso di rilasciare il 14 febbraio a CRAN. –

2

Per quanto riguarda il vostro obiettivo principale "per installare le librerie che non hanno già." E indipendentemente utilizzando "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) 
    } 
} 

Così si può caricare e pacchetto installato il vecchio modo di moda di R. richiedono ("ggplot2") richiedono ("Rcpp")

+0

Se non ti piace più la tua risposta, non vandalizzarla, basta eliminarla. –

+0

Beh, ci ho provato, ma non potevo. Penso che la mia estensione NoScript di FF lo disabiliti o che non disponga dei diritti e dei crediti per cancellare la mia risposta. LoL Tuttavia, penso che Livius sia abbastanza vicino alla mia risposta, pensò senza mascherarsi. Grazie Michele Petrotta. per la notifica. – GeoObserver

+0

Dovresti vedere un link 'delete' sopra questi commenti. Se non lo fai, e vuoi comunque eliminarlo, usa il link 'flag', seleziona" altro "e spiega a un moderatore che vorresti rimuovere la risposta. –

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

provare questo:

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

Essenzialmente un duplicato della risposta di Livio nella parte superiore. – Gregor

3

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); 
4

La seguente funzione semplice 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 la mia, ha trovato questo sul web qualche tempo fa e aveva iniziato ad usare da allora non è sicuro della fonte originale)

1

Ecco il mio codice per esso:

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

io uso seguente funzione t o installa il pacchetto se le uscite require("<package>") con errore del pacchetto non trovato. Interrogherà entrambi i repository CRAN e Bioconductor per il pacchetto mancante.

Adattato 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) & 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!

+0

Potrebbe essere migliorato controllando se i pacchetti sono effettivamente disponibili su cran o bc. Inoltre, dovrebbe utilizzare la libreria alla fine per generare un errore se l'installazione non è riuscita o se un pacchetto non esiste. Vedi la mia versione migliorata chiamata 'loadpack()' su https://raw.githubusercontent.com/holgerbrandl/datautils/master/R/core_commons.R –

1
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 } 
2

Abbastanza semplice.

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

Ho pensato di contribuire quello che uso:

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

si può semplicemente utilizzare la funzione setdiff per ottenere i pacchetti che non sono installati e poi installarli. Nell'esempio seguente, verifichiamo se i pacchetti ggplot2 e sono installati prima di installarli.

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

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

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

Io uso lo stesso approccio. Possiamo anche usare 'installed.packages() [, 'Package']' invece di 'rownames (installed.packages())'. – Scudelletti

1
library <- function(x){ 
    x = toString(substitute(x)) 
if(!require(x,character.only=TRUE)){ 
    install.packages(x) 
    base::library(x,character.only=TRUE) 
}} 

Questo funziona con i nomi dei pacchetti non quotati ed è abbastanza elegante (cfr risposta di GeoObserver)

6
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.

2

Utilizzare packrat in modo che le librerie condivise siano esattamente uguali e non cambino 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 il sistema di ambiente di qualcuno, packrat utilizza la propria directory e installa tutte le dipendenze per i propri programmi e non tocca l'ambiente di qualcuno.

Packrat è un sistema di gestione dipendenza per R.

dipendenze R può essere frustrante. 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 piattaforme 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/

6

Un sacco di risposte di cui sopra (e su duplicati di questa domanda) si basano su installed.packages che è di cattivo gusto. Dalla documentazione:

Questo può essere lento quando sono installate migliaia di pacchetti, in modo da non utilizzare questo per scoprire se è installato un pacchetto chiamato (uso system.file o find.package), né per scoprire se un pacchetto è utilizzabile (richiede la chiamata e controlla il valore restituito) e non trova i dettagli di un piccolo numero di pacchetti (usa 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 è quello di tentare di caricare il pacchetto utilizzando require e installare e se il caricamento non riesce (require tornerà FALSE se non si trova). Io 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 utilizzato in questo modo:

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

In questo modo si carica tutti i pacchetti, poi torna e installa tutti i pacchetti mancanti (che se si vuole, è un posto a portata di mano per 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) 
     } 
    } 
} 
1
source("https://bioconductor.org/biocLite.R") 
if (!require("ggsci")) biocLite("ggsci") 
0

Nel mio caso, ho voluto un uno di linea che ho potuto eseguire da linea di comando (in realtà tramite un Makefile). Ecco un esempio l'installazione di "VGAM" e "piuma", 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")' 

Dall'interno 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") 

Qui non c'è nulla al di là delle soluzioni precedenti, ad eccezione che:

  • lo tengo ad una singola linea
  • ho codificare il parametro repos (per evitare eventuali popup che chiedono abo ut specchio utilizzare)
  • non si preoccupano di definire una funzione da utilizzare altrove

noti inoltre l'importante character.only=TRUE (senza di essa, il require avrebbe cercato di caricare il pacchetto p).

Problemi correlati