Manière élégante de vérifier les paquets manquants et de les installer?

il semble que je partage beaucoup de code avec les coauteurs de nos jours. Beaucoup d'entre eux sont des utilisateurs novices/intermédiaires de R et ne se rendent pas compte qu'ils doivent installer des paquets qu'ils n'ont pas encore.

Existe-t-il une façon élégante d'appeler installed.packages() , comparez cela à ceux que je charge et installe s'il manque?

241
demandé sur Jaap 2010-11-03 21:08:54

26 réponses

Oui. Si vous avez votre liste de paquets, comparez-la à la sortie de installed.packages()[,"Package"] et installez les paquets manquants. Quelque chose comme ceci:

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)

autrement:

si vous mettez votre code dans un paquet et en faites des dépendances, ils seront automatiquement installés lorsque vous installerez votre paquet.

215
répondu Shane 2010-11-03 18:13:09

Dason K. et j'ai le pacman package qui peut faire cela très bien. La fonction p_load dans le package. La première ligne est juste pour s'assurer que pacman est installé.

if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
162
répondu Tyler Rinker 2015-02-22 01:10:28

vous pouvez simplement utiliser la valeur de retour de require :

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

j'utilise library après l'installation parce qu'il va jeter une exception si l'installation n'a pas réussi ou le paquet ne peut pas être chargé pour une autre raison. Vous le rendez plus robuste et réutilisable:

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

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

l'inconvénient de cette méthode est que vous devez passer le nom du paquet entre guillemets, ce que vous ne faites pas pour le vrai require .

47
répondu Livius 2017-02-15 09:34:09

bien que la réponse de Shane soit vraiment bonne, pour un de mes projets j'ai dû supprimer les messages d'ouput, les avertissements et installer les paquets automatiquement . J'ai finalement réussi à obtenir ce 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)
}

Utiliser:

libraries <- c("ReadImages", "ggplot2")
for(library in libraries) 
{ 
    if(!UsePackage(library))
    {
        stop("Error!", library)
    }
}
15
répondu Juan Antonio Cano 2012-01-14 16:14:01

cette solution prendra un vecteur de caractères des noms de paquets et tentera de les charger, ou de les installer si le chargement échoue. Il s'appuie sur le comportement de retour de require pour le faire parce que...

require renvoie (invisiblement) une logique indiquant si le paquet requis est disponible

par conséquent, nous pouvons simplement voir si nous avons été en mesure de charger le paquet requis et si pas, de l'installer avec dépendances. Ainsi donné un vecteur de caractères des paquets que vous souhaitez charger...

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" ) )
15
répondu Simon O'Hanlon 2013-11-09 14:09:21
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')

"ggplot2" est le colis. Il vérifie pour voir si le paquet est installé, si ce n'est pas qu'il l'installe. Il charge ensuite le colis quelle que soit la branche qu'il a prise.

11
répondu user6784955 2016-09-01 21:04:34
# 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)
7
répondu Brian Spiering 2014-03-25 21:44:25

bon nombre des réponses ci-dessus (et sur des copies de cette question) reposent sur installed.packages qui est une mauvaise forme. Extrait de la documentation:

cela peut être lent lorsque des milliers de paquets sont installés, donc ne l'utilisez pas pour savoir si un paquet nommé est installé (utilisez le système.fichier ou le trouver.pour savoir si un paquet est utilisable (appeler demander et vérifier la valeur de retour) ou pour trouver les détails d'un petit nombre de paquets (utiliser packageDescription). Il a besoin de lire plusieurs fichiers par paquet installé, qui sera lent sur Windows et sur certains systèmes de fichiers montés.

ainsi, une meilleure approche est d'essayer de charger le paquet en utilisant require et et d'installer si le chargement échoue ( require retournera FALSE si elle n'est pas trouvée). Je préfère cette implémentation:

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

qui peut être utilisé comme ceci:

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

de Cette façon, il charge tous les paquets, puis remonte et installe tous les paquets manquants (qui, si vous voulez, est un endroit pratique pour insérer une invite à se demander si l'utilisateur souhaite installer des paquets). Au lieu d'appeler install.packages séparément pour chaque paquet, il passe le vecteur entier des paquets non désinstallés une seule fois.

Voici la même fonction mais avec un dialogue windows qui demande si l'utilisateur veut installer les paquets manquants

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)
        }
    }
}
7
répondu Matthew 2017-06-20 18:37:08

C'est le but du paquet rbundler : fournir un moyen de contrôler les paquets qui sont installés pour un projet spécifique. Pour l'instant, le paquet fonctionne avec la fonctionnalité devtools pour installer les paquets dans le répertoire de votre projet. La fonctionnalité est similaire à celle du bundler de Ruby .

si votre projet est un paquet (recommandé), alors tout ce que vous avez à faire est de charger rbundler et de regrouper les paquets. Le La fonction bundle examinera le fichier DESCRIPTION de votre paquet pour déterminer quels paquets regrouper.

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

Maintenant, les paquets seront installés dans le .Répertoire Rbundle.

si votre projet n'est pas un paquet, alors vous pouvez le simuler en créant un fichier DESCRIPTION dans le répertoire racine de votre projet avec un champ Depends qui liste les paquets que vous voulez installer (avec des informations de version optionnelles):

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

voici le rapport GitHub pour le projet si vous êtes intéressé à contribuer: rbundler .

6
répondu Erik Shilts 2012-12-03 13:10:42

bien sûr.

vous devez comparer 'paquets installés' avec 'paquets désirés'. C'est très proche de ce que je fais avec canneberges car je dois comparer "paquets connus stockés "avec" paquets connus actuellement " pour déterminer les paquets nouveaux et/ou mis à jour.

alors fais quelque chose comme

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

pour obtenir tous les paquets connus, appel simulaire pour les paquets actuellement installés et comparez cela à un ensemble donné de paquets cibles.

5
répondu Dirk Eddelbuettel 2010-11-03 18:14:59

la fonction simple suivante fonctionne comme un charme:

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

(pas de mine, trouvé ceci sur le web il y a quelque temps et a été utilisé depuis lors. pas sûr de la source originale)

4
répondu Anish Sugathan 2015-05-17 15:34:51

j'utilise la fonction suivante pour installer package si require("<package>") sort avec package not Found error. Il interrogera les dépôts-CRAN et Bioconducteur pour trouver le paquet manquant.

adapté de L'œuvre originale de 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)))
  }
}

exemple:

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

PS: update.packages(ask = FALSE) & biocLite(character(), ask=FALSE) mettra à jour tous les paquets installés sur le système. Cela peut prendre beaucoup de temps et considérer qu'il s'agit d'une mise à niveau complète, ce qui n'est peut-être pas toujours justifié!

4
répondu Samir 2015-07-24 22:05:20

vous pouvez simplement utiliser la fonction setdiff pour obtenir les paquets qui ne sont pas installés et ensuite les installer. Dans l'exemple ci-dessous, nous vérifions si les paquets ggplot2 et Rcpp sont installés avant de les installer.

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

dans une ligne, le dessus peut être écrit comme:

install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
4
répondu Alex Essilfie 2016-02-08 08:05:58

j'ai implémenté la fonction pour installer et charger les paquets R requis en silence. L'espoir peut vous aider. Voici le code:

# 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);
3
répondu Pratik Patil 2015-05-18 12:55:12

utiliser packrat pour que les bibliothèques partagées soient exactement les mêmes et ne changent pas l'environnement de l'autre.

en termes d'élégance et de meilleure pratique, je pense que vous vous y prenez fondamentalement de la mauvaise façon. le paquet packrat a été conçu pour ces questions. Il est développé par RStudio par Hadley Wickham. Au lieu d'avoir à installer des dépendances et éventuellement gâcher quelqu'un environnement de système packrat utilise son propre répertoire et installe tous les les dépendances pour vos programmes dans leur et ne touche pas l'environnement de quelqu'un.

Packrat est un système de gestion de dépendances pour R.

Les dépendances de paquets

R peuvent être frustrantes. Avez-vous déjà dû utiliser trial-and–error pour comprendre quels paquets R Vous devez installer pour faire fonctionner le code de quelqu'un d'autre-et ensuite avoir été laissé avec ces paquets globalement installés pour toujours, parce que maintenant vous n'êtes pas sûr d'en avoir besoin? Avez-vous vous avez déjà mis à jour un paquet pour que le code d'un de vos projets fonctionne, seulement pour trouver que le paquet mis à jour fait que le code d'un autre projet cesse de fonctionner?

nous avons construit packrat pour résoudre ces problèmes. Utilisez packrat pour rendre vos projets plus:

  • isolé: L'installation d'un nouveau paquet ou d'un paquet mis à jour pour un projet ne cassera pas vos autres projets, et vice versa. C'est parce que packrat donne à chaque projet sa propre bibliothèque de paquets privée.
  • Portable: transport facile de vos projets d'un ordinateur à l'autre, même sur différentes plateformes. Pakrat permet d'installer facilement les paquets dont dépend votre projet.
  • reproductible: Packrat enregistre les versions exactes du Paquet sur lesquelles vous comptez, et s'assure que ces versions exactes sont celles qui sont installées où que vous alliez.

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

3
répondu mtelesha 2017-11-20 15:50:37

concernant votre objectif principal " installer des bibliothèques qu'ils n'ont pas encore. "et indépendamment de l'utilisation de" instllaed.paquet." )( La fonction suivante masque la fonction originale de require. Il essaie de charger et de vérifier le paquet nommé "x" , s'il n'est pas installé, l'installer directement, y compris les dépendances; et enfin le charger normalement. vous renommez le nom de la fonction "require" en "library" pour maintenir l'intégrité . La seule limitation est que les noms des paquets doivent être cités.

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

donc vous pouvez charger et installer package l'ancienne mode de R. require ("ggplot2") require ("Rcpp")

2
répondu GeoObserver 2013-11-17 02:42:18

assez basique.

pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)
2
répondu jangorecki 2015-11-26 01:47:54

pensait que je contribuerais celui que j'utilise:

testin <- function(package){if (!package %in% installed.packages())    
install.packages(package)}
testin("packagename")
2
répondu Ben 2016-02-04 18:46:10

j'utilise ce qui suit qui vérifiera si le paquet est installé et si les dépendances sont mises à jour, puis charge le paquet.

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, ])
}
1
répondu metasequoia 2012-12-02 15:24:20

Voici mon code:

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)
1
répondu Edward Tyler 2015-06-12 16:22:47
 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 }
1
répondu ruemorgue 2015-11-07 13:36:29
library <- function(x){
  x = toString(substitute(x))
if(!require(x,character.only=TRUE)){
  install.packages(x)
  base::library(x,character.only=TRUE)
}}

cela fonctionne avec des noms de paquets non cotés et est assez élégant(cf. GeoObserver de réponse)

1
répondu s n 2017-04-20 08:33:52
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
1
répondu Shicheng Guo 2017-06-22 02:27:46

en utilisant la famille lapply et l'approche de la fonction anonyme vous pouvez:

lib <- c("plyr", "psych", "tm")
req <- expression(require(x, character.only = TRUE))
sapply(lib, function(x) eval(req) || {install.packages(x); eval(req)})

plyr psych    tm 
TRUE  TRUE  TRUE 
  1. essayez de joindre tous les paquets énumérés.
  2. Installer manquant seulement (en utilisant || évaluation paresseuse).
  3. charge D'essai encore une fois celles qui étaient manquantes à l'étape 1 et installées à l'étape 2.
  4. imprime un État de chargement total par colis ( TRUE / FALSE ).
1
répondu Georgie Shimanovsky 2018-10-11 20:29:45

dans mon cas, je voulais un liner que je pouvais exécuter depuis la ligne de commande (en fait via un Makefile). Voici un exemple d'installation de "VGAM" et" feather "si elles ne sont pas déjà installées:

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

à l'intérieur De la R il serait tout simplement:

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

il n'y a rien ici au-delà des solutions précédentes sauf que:

  • je la garde pour une seule ligne
  • I CODE dur le repos paramètre (pour éviter toute popups demandant à propos du miroir à utiliser)
  • Je ne prends pas la peine de définir une fonction à utiliser ailleurs

notez également l'important character.only=TRUE (sans lui, le require tenterait de charger le colis p ).

0
répondu user3780389 2017-12-20 19:54:21

essayez ceci:

if (!require(MyDesiredLibrary)) {
   install.packages("MyDesiredLibrary")
}
-2
répondu DiegoTorres 2015-01-29 09:30:00