web-dev-qa-db-fra.com

Un moyen élégant de vérifier les paquets manquants et de les installer?

Il me semble partager beaucoup de code avec des co-auteurs ces jours-ci. Beaucoup d’entre eux sont des utilisateurs novices/intermédiaires et ne réalisent pas qu’ils doivent installer des paquets qu’ils n’ont pas encore.

Existe-t-il un moyen élégant d’appeler installed.packages(), comparez-le à ceux que je charge et installe s’il manque?

292
Maiasaura

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

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, il sera automatiquement installé lors de l'installation de votre paquet.

252
Shane

Dason K. et moi avons le paquet pacman qui peut le faire très bien. La fonction p_load dans le package effectue cette opération. 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)
194
Tyler Rinker

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, car une exception sera levée si l'installation a échoué ou si le package ne peut pas être chargé pour une autre raison. Vous rendez ceci 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.

57
Livius

Cette solution utilisera un vecteur de caractères contenant les noms de packages et tentera de les charger ou les installera si le chargement échoue. Cela dépend du comportement de retour de require pour le faire parce que ...

require renvoie (de manière invisible) une logique indiquant si le package requis est disponible

Par conséquent, nous pouvons simplement voir si nous avons pu charger le paquet requis et, dans le cas contraire, l’installer avec des dépendances. Donc, étant donné un vecteur de caractères de 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" ) )
17
Simon O'Hanlon
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')

"ggplot2" est le paquet. Il vérifie si le paquet est installé, sinon il l'installe. Il charge ensuite le package quelle que soit la branche prise.

15
user6784955

Bien que la réponse de Shane soit vraiment bonne, pour l’un de mes projets, j’avais besoin de supprimer les messages de sortie, les avertissements et d’installer les paquets de façon automatique. 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)
}

Utilisation:

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

Beaucoup des réponses ci-dessus (et des doublons de cette question) reposent sur installed.packages qui est de mauvaise forme. De la documentation:

Cela peut être lent lorsque des milliers de paquets sont installés, ne l'utilisez donc pas pour savoir si un paquet nommé est installé (utilisez system.file ou find.package), ni pour savoir si un paquet est utilisable (appel requis et vérifier la valeur de retour) ni pour trouver les détails d’un petit nombre de paquets (utilisez packageDescription). Il doit lire plusieurs fichiers par paquet installé, ce qui sera lent sous Windows et sur certains systèmes de fichiers montés sur le réseau.

Donc, une meilleure approche consiste à essayer de charger le paquet en utilisant require et à installer si le chargement échoue (require renverra FALSE s'il n'est pas trouvé). 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 packages, puis revient en arrière et installe tous les packages manquants (qui, si vous le souhaitez, est un endroit pratique pour insérer une invite afin de demander si l'utilisateur souhaite installer des packages). Au lieu d'appeler install.packages séparément pour chaque package, il transmet le vecteur entier des packages désinstallés une seule fois.

Voici la même fonction mais avec une fenêtre de dialogue qui demande si l'utilisateur veut installer les paquetages 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)
        }
    }
}
13
Matthew
# 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)
8
Brian Spiering

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

Si votre projet est un paquet (recommandé), il vous suffit de charger rbundler et de regrouper les paquets. La fonction bundle examinera le fichier DESCRIPTION de votre paquetage pour déterminer les paquets à regrouper.

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

Maintenant, les packages seront installés dans le répertoire .Rbundle.

Si votre projet n'est pas un package, vous pouvez le simuler en créant un fichier DESCRIPTION dans le répertoire racine de votre projet avec un champ Depends qui répertorie les packages que vous souhaitez installer (avec des informations de version facultatives):

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

Voici le dépôt github du projet si vous souhaitez contribuer: rbundler .

6
Erik Shilts

Sûr.

Vous devez comparer les "paquets installés" avec les "paquets souhaités". C'est très proche de ce que je fais avec CRANberries car j'ai besoin de comparer les 'paquets connus stockés' avec les 'paquets connus actuellement' pour déterminer les nouveaux paquets et/ou les paquets mis à jour.

Alors fais quelque chose comme

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

pour obtenir tous les packages connus, appelez simular pour les packages actuellement installés et comparez-le à un ensemble donné de packages cible.

5

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 le mien, j'ai trouvé cela sur le Web il y a quelque temps et je l'utilisais depuis. je ne suis pas sûr de la source d'origine)

4
Anish Sugathan

Utilisez Packrat pour que les bibliothèques partagées soient exactement les mêmes et ne changent pas l'environnement des autres.

En termes d’élégance et de bonnes pratiques, je pense que vous vous y prenez fondamentalement de la mauvaise façon. le package Packrat a été conçu pour ces problèmes. Il est développé par RStudio par Hadley Wickham. Au lieu de devoir installer des dépendances et éventuellement gâcher un environnement système, Packrat utilise son propre répertoire et installe toutes les dépendances de vos programmes dans leur environnement et ne les touche pas.

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

Les dépendances de paquets R peuvent être frustrantes. Avez-vous déjà eu besoin d'essais et d'erreurs pour déterminer quels packages R vous devez installer pour que le code de quelqu'un d'autre fonctionne, et vous restiez avec ces packages globalement installés pour toujours, car vous n'êtes pas sûr d'en avoir besoin ? Avez-vous déjà mis à jour un package pour que le code de l'un de vos projets fonctionne, mais que le package mis à jour empêche le code d'un autre projet de fonctionner?

Nous avons construit Packrat pour résoudre ces problèmes. Utilisez Packrat pour rendre vos projets R plus:

  • Isolé: L'installation d'un nouveau package ou d'une mise à jour pour un projet ne cassera pas vos autres projets, et inversement. C’est parce que Packrat attribue à chaque projet sa propre bibliothèque de packages privés.
  • Portable: transportez facilement vos projets d'un ordinateur à un autre, même sur différentes plates-formes. Packrat facilite l'installation des packages sur lesquels votre projet repose.
  • Reproductible: Packrat enregistre les versions exactes du paquet dont vous dépendez et veille à ce que ces versions exactes soient celles qui sont installées où que vous soyez.

https://rstudio.github.io/Packrat/

4
mtelesha

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

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

Dans une ligne, ce qui précède peut être écrit comme suit:

_install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
_
4
Alex Essilfie

J'utilise la fonction suivante pour installer le paquet si require("<package>") se ferme avec une erreur de paquet non trouvé. Il interrogera les référentiels CRAN et Bioconductor à la recherche du paquet manquant.

Adapté du travail original 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 packages installés sur le système. Cela peut prendre beaucoup de temps et constitue une mise à niveau complète de R qui peut ne pas être garantie tout le temps!

4
Samir

J'ai implémenté la fonction pour installer et charger les packages R requis en mode silencieux. L'espoir pourrait 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
Pratik Patil

La version à venir de RStudio (1.2), déjà disponible en tant qu'aperçu, inclura une fonctionnalité permettant de détecter les packages manquants dans les appels library() et require(), et invite l'utilisateur à les installer:

Détecter les paquets R manquants

De nombreux scripts R s'ouvrent avec les appels à library() et require() pour charger les packages dont ils ont besoin pour s'exécuter. Si vous ouvrez un script R qui fait référence à des packages que vous n'avez pas installés, RStudio vous proposera désormais d'installer tous les packages nécessaires en un seul clic. Plus besoin de taper install.packages() à plusieurs reprises jusqu'à ce que les erreurs disparaissent!
https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/

Cela semble répondre particulièrement bien à la préoccupation initiale de OP:

Beaucoup d’entre eux sont des utilisateurs novices/intermédiaires et ne réalisent pas qu’ils doivent installer des paquets qu’ils n’ont pas encore.

2
Aurèle

En ce qui concerne votre objectif principal "d'installer des bibliothèques qu'ils n'ont pas déjà." Et indépendamment de l'utilisation de "instllaed.packages ()". La fonction suivante masque la fonction d'origine de require. Il essaie de charger et de vérifier le paquet nommé "x". S'il n'est pas installé, installez-le 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 de 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)
  } 
}

Ainsi, vous pouvez charger et installer le paquet de l'ancienne manière de R. require ("ggplot2") require ("Rcpp")

2
GeoObserver

En utilisant la famille lapply et l’approche par fonctions anonymes, vous pouvez:

  1. Essayez de joindre tous les paquets listés.
  2. Installation manquante uniquement (à l'aide de || évaluation paresseuse).
  3. Essayez d’attacher à nouveau ceux qui manquaient à l’étape 1 et qui ont été installés à l’étape 2.
  4. Affiche l'état de chargement final de chaque colis (TRUE/FALSE).

    req <- substitute(require(x, character.only = TRUE))
    lbs <- c("plyr", "psych", "tm")
    sapply(lbs, function(x) eval(req) || {install.packages(x); eval(req)})
    
    plyr psych    tm 
    TRUE  TRUE  TRUE 
    
2
Georgie Shimanovsky

Assez basique.

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

Je pensais apporter celle que j'utilise:

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

J'utilise ce qui suit pour vérifier 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
metasequoia

Voici mon code pour cela:

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
Edward Tyler
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 cités et est assez élégant (voir la réponse de GeoObserver)

1
s n
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
1
Shicheng Guo
 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
ruemorgue

Dans mon cas, je voulais un liner que je pourrais lancer depuis la ligne de commande (en fait via un Makefile). Voici un exemple d'installation de "VGAM" et "feather" s'ils ne sont pas déjà installés:

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

De l'intérieur de R ce serait juste:

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 le garde à une seule ligne
  • J'ai codé en dur le paramètre repos (pour éviter toute fenêtre contextuelle demandant le miroir à utiliser)
  • Je ne me donne pas la peine de définir une fonction à utiliser ailleurs

Notez également l'important character.only=TRUE (sans lui, le require essaierait de charger le paquet p).

0
user3780389