185 votes

Vérifier les paquets installés avant de lancer install.packages()

J'ai un script R qui est partagé avec plusieurs utilisateurs sur différents ordinateurs. Une de ses lignes contient le install.packages("xtable") comando.

Le problème est que chaque fois que quelqu'un exécute le script, R passe beaucoup de temps à réinstaller apparemment le paquet (cela prend en fait un certain temps, puisque le cas réel a vecteur de plusieurs paquets).

Comment puis-je faire en sorte que l'on vérifie d'abord si les paquets sont installés et ensuite que l'on exécute seulement install.packages() pour ceux qui ne le sont pas ?

177voto

Shuguang Points 444

Essayez : require("xtable") o "xtable" %in% rownames(installed.packages())

74voto

Sean Murphy Points 128

Si vous voulez le faire aussi simplement que possible :

packages <- c("ggplot2", "dplyr", "Hmisc", "lme4", "arm", "lattice", "lavaan")

install.packages(setdiff(packages, rownames(installed.packages())))  

Remplacez les paquets listés sur la première ligne par ceux nécessaires à l'exécution de votre code, et voilà !

Note : Modifié pour enlever l'enveloppe conditionnelle grâce au commentaire d'Artem ci-dessous.

57voto

Sacha Epskamp Points 14956

C'est une fonction que j'ai souvent utilisée pour vérifier la présence d'un paquet, l'installer sinon et charger à nouveau :

pkgTest <- function(x)
  {
    if (!require(x,character.only = TRUE))
    {
      install.packages(x,dep=TRUE)
        if(!require(x,character.only = TRUE)) stop("Package not found")
    }
  }

Des travaux comme pkgTest("xtable") . Cela ne fonctionne que si le miroir est défini, mais vous pouvez l'indiquer dans le champ require appels.

12voto

silentbang Points 1162
# Function to check whether package is installed
  is.installed <- function(mypkg){
    is.element(mypkg, installed.packages()[,1])
  } 

  # check if package "hydroGOF" is installed
  if (!is.installed("hydroGOF")){
    install.packages("hydroGOF")
  }

4voto

rpierce Points 848

Ou un exemple massivement surchargé de drknexus/repsych sur github, glibrary . Il y a certainement des moyens plus efficaces et plus performants de faire cela, mais je l'ai programmé il y a longtemps et cela fonctionne.

  • Il fonctionne même si un repo n'a pas été sélectionné en prenant l'option de nuage par défaut si disponible. Si vous êtes sur une ancienne version de R, il reviendra en arrière et choisira un miroir basé sur le code du pays.
  • Il essaie de charger la bibliothèque (cette étape pourrait être rendue plus efficace en utilisant certaines des méthodes ci-dessus).
    • S'il échoue, il essaiera de l'installer.
    • Si l'installation échoue, vous serez informé des paquets dont l'installation a échoué.
  • C'est exact, les paquets, plusieurs paquets peuvent être chargés/installés en une seule fois avec leurs dépendances (du moins habituellement, il peut y avoir un bogue ici).

Par exemple : glibrary(xtable,sos,data.table) mais je ne pense pas qu'il flippera si tu appelles glibrary("xtable","sos","data.table") à la place. Poussoirs/tiges/fourches bienvenus.

Code de la fonction :

#' Try to load a library, if that fails, install it, then load it.
#'
#' glibrary short for (get)library.
#' The primary aim of this function is to make loading packages more transparent.  Given that we know we want to load a given package, actually fetching it is a formality.  glibrary skims past this formality to install the requested package.
#'
#' @export
#' @param ... comma seperated package names
#' @param lib.loc See \code{\link{require}}
#' @param quietly See \code{\link{require}}
#' @param warn.conflicts See \code{\link{require}}
#' @param pickmirror If TRUE, glibrary allows the user to select the mirror, otherwise it auto-selects on the basis of the country code
#' @param countrycode This option is ignored and the first mirror with the substring "Cloud", e.g. the RStudio cloud, is selected.  If no mirrors with that substring are identified, glibrary compares this value to results from getCRANmirrors() to select a mirror in the specified country.
#' @return logical; TRUE if glibrary was a success, an error if a package failed to load
#' @note keep.source was an arguement to require that was deprecated in R 2.15
#' @note This warning \code{Warning in install.packages: InternetOpenUrl failed: 'The operation timed out'} indicates that the randomly selected repository is not available.  Check your internet connection.  If your internet connection is fine, set pickmirror=TRUE and manually select an operational mirror.
#' @examples
#' #glibrary(lattice,MASS) #not run to prevent needless dependency
glibrary <- function(..., lib.loc = NULL, quietly = FALSE, warn.conflicts = TRUE, pickmirror = FALSE, countrycode = "us") {
  warningHandle <- function(w) {
    if (grepl("there is no package called",w$message,fixed=TRUE)) {
      return(FALSE) #not-loadable
    } else {
      return(TRUE) #loadable
    }
  }

  character.only <- TRUE  #this value is locked to TRUE so that the function passes the character value to require and not the variable name thislib
  librarynames <- unlist(lapply(as.list(substitute(.(...)))[-1],as.character))
  #if package already loaded, remove it from librarynames before processing further
  si.res <- sessionInfo()
  cur.loaded <- c(si.res$basePkgs,names(si.res$otherPkgs)) #removed names(si.res$loadedOnly) because those are loaded, but not attached, so glibrary does need to handle them.
  librarynames <- librarynames[librarynames %!in% cur.loaded]
  success <- vector("logical", length(librarynames))
  if (length(success)==0) {return(invisible(TRUE))} #everything already loaded, end.

  alreadyInstalled <- installed.packages()[,"Package"]
  needToInstall <- !librarynames %in% alreadyInstalled

  if (any(needToInstall)) {
    if (pickmirror) {chooseCRANmirror()}
    if (getOption("repos")[["CRAN"]] == "@CRAN@") {
      #Select the first "Cloud" if available
      m <- getCRANmirrors(all = FALSE, local.only = FALSE)
      URL <- m[grepl("Cloud",m$Name),"URL"][1] #get the first repos with "cloud" in the name
      if (is.na(URL)) { #if we did not find the cloud,
        #Fall back and use the previous method
        message("\nIn repsych:glibrary:  Now randomly selecting a CRAN mirror. You may reselect your CRAN mirror with chooseCRANmirror().\n")
        #if there is no repository set pick a random one by country code
        getCRANmirrors.res <- getCRANmirrors()
        foundone <- FALSE  #have we found a CRAN mirror yet?
        #is it a valid country code?
        if (!countrycode %in% getCRANmirrors.res$CountryCode) {
          stop("In repsych::glibrary:  Invalid countrycode argument")
        }
        ticker <- 0
        while (!foundone) {
          ticker <- ticker + 1
          URL <- getCRANmirrors.res$URL[sample(grep(countrycode, getCRANmirrors.res$CountryCode), 1)]
          host.list <- strsplit(URL, "/")
          host.clean <- unlist(lapply(host.list, FUN = function(x) {return(x[3])}))
          #make sure we can actually access the package list
          if (nrow(available.packages(contrib.url(URL)))!=0) {foundone <- TRUE}        
          if (ticker > 5) {stop("In repsych::glibrary:  Unable to access valid repository.  Is the internet connection working?")}
        } #end while
      } #end else
      repos <- getOption("repos")
      repos["CRAN"] <- gsub("/$", "", URL[1L])
      options(repos = repos)
    } #done setting CRAN mirror
    #installing packages
    installResults <- sapply(librarynames[needToInstall],install.packages)
    #checking for successful install
    needToInstall <- !librarynames %in% installed.packages()[,"Package"]
    if (any(needToInstall)) {
      stop(paste("In repsych::glibrary: Could not download and/or install: ",paste(librarynames[needToInstall],collapse=", "),"... glibrary stopped.",sep=""))
    } # done reporting any failure to install
  } #done if any needed to install

  #message("In repsych::glibrary:  Attempting to load requested packages...\n")
  #success <- tryCatch(
  success <- sapply(librarynames,require, lib.loc = lib.loc, quietly = FALSE, warn.conflicts = warn.conflicts, character.only = TRUE)
  #, warning=warningHandle) #end tryCatch
  if(length(success) != length(librarynames)) {stop("A package failed to return a success in glibrary.")}

  if (all(success)) {
    #message("In repsych::glibrary:  Success!")
    return(invisible(TRUE))
  } else {
    stop(paste("\nIn repsych::glibrary, unable to load: ", paste(librarynames[!success]), 
               collapse = " "))
  }
  stop("A problem occured in glibrary") #shouldn't get this far down, all returns should be made.
}
NULL

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X