web-dev-qa-db-fra.com

Recherchez les packages installés avant d'exécuter install.packages ()

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

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

Comment puis-je d'abord vérifier si les paquetages sont installés et ensuite n'exécuter que install.packages() pour ceux qui ne le sont pas?

122
Waldir Leoncio

essayez: require("xtable") ou "xtable" %in% rownames(installed.packages())

139
Shuguang

C’est une fonction que j’utilisais souvent pour rechercher un paquet, l’installer autrement et le 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")
    }
  }

Fonctionne comme pkgTest("xtable"). Cela ne fonctionne que si le miroir est défini, mais vous pouvez entrer cela dans les appels require.

48
Sacha Epskamp

Si vous voulez le faire aussi simplement que possible:

packages <- c("ggplot2", "dplyr", "Hmisc", "lme4", "arm", "lattice", "lavaan")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
  install.packages(setdiff(packages, rownames(installed.packages())))  
}

Remplacez les packages répertoriés sur la première ligne par ceux nécessaires à l'exécution de votre code, et le tour est joué!

44
Sean Murphy

Il y a aussi le paquet CRAN pacman qui a la fonction p_load pour installer un ou plusieurs paquets (mais seulement si nécessaire) et les charger ensuite.

14
Nick Kennedy

Je suggère une solution plus légère en utilisant system.file.

is_inst <- function(pkg) {
    nzchar(system.file(package = pkg))
}

is_inst2 <- function(pkg) {
    pkg %in% rownames(installed.packages())
}

library(microbenchmark)
microbenchmark(is_inst("aaa"), is_inst2("aaa"))
## Unit: microseconds
##            expr      min        lq       mean    median       uq       max neval
##  is_inst("aaa")   22.284   24.6335   42.84806   34.6815   47.566   252.568   100
## is_inst2("aaa") 1099.334 1220.5510 1778.57019 1401.5095 1829.973 17653.148   100
microbenchmark(is_inst("ggplot2"), is_inst2("ggplot2"))
## Unit: microseconds
##                expr      min       lq     mean   median       uq      max neval
##  is_inst("ggplot2")  336.845  386.660  459.243  431.710  483.474  867.637   100
## is_inst2("ggplot2") 1144.613 1276.847 1507.355 1410.054 1656.557 2747.508   100
9
Artem Klevtsov
# 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")
  }
9
Duc Tran
requiredPackages = c('plyr','ggplot2','ggtern')
for(p in requiredPackages){
  if(!require(p,character.only = TRUE)) install.packages(p)
  library(p,character.only = TRUE)
}
8
Nicholas Hamilton

J'ai trouvé un script packages quelque part que je mets toujours dans chaque script pour charger mes bibliothèques. Toutes les manipulations de votre bibliothèque (téléchargement, installation et chargement) seront effectuées, et uniquement si nécessaire.

# Install function for packages    
packages<-function(x){
  x<-as.character(match.call()[[2]])
  if (!require(x,character.only=TRUE)){
    install.packages(pkgs=x,repos="http://cran.r-project.org")
    require(x,character.only=TRUE)
  }
}
packages(ggplot2)
packages(reshape2)
packages(plyr)
# etc etc
6
CousinCocaine

La solution que j'ai utilisée est basée sur les contributions de Sacha Epskamp et Shuguang. Voici la fonction:

instalaPacotes <- function(pacote) {
  if (!pacote %in% installed.packages()) install.packages(pacote)
}

Cela fonctionne en silence, ne faisant écho à rien si le paquet "pacote" est déjà installé et l’installe sinon. N'oubliez pas d'écrire le nom du paquet entre guillemets!

4
Waldir Leoncio

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

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

  • Cela fonctionne même si un dépôt n'a pas été sélectionné en prenant l'option cloud par défaut si disponible. Si vous utilisez une version plus ancienne de R, il va revenir en arrière et choisir un miroir basé sur le code de pays.
  • Il essaie de charger la bibliothèque (cette étape pourrait être rendue plus efficace en utilisant certaines des méthodes ci-dessus)
    • Si cela échoue, il essaiera de l'installer
    • Si l'installation échoue, elle vous indiquera quels paquets n'ont pas été installés.
  • C’est vrai, des packages, plusieurs packages peuvent être chargés/installés en une seule passe avec leurs dépendances (au moins généralement, il peut y avoir un bogue ici).

par exemple: glibrary(xtable,sos,data.table) mais je ne pense pas que cela va paniquer si vous appelez glibrary("xtable","sos","data.table") à la place. Pousse/tire/fourche de bienvenue.

Code pour 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
4
russellpierce

Pourquoi ne pas essayer ça?

#will install the pROC library if you don't have it
if(!is.element('pROC', installed.packages()[,1]))
  {install.packages('pROC')
}else {print("pROC library already installed")}
2
Slak

Pourquoi ne pas simplement supprimer la ligne du script? Si l'utilisateur final n'a pas les connaissances nécessaires pour installer xtable au besoin, vous avez de plus gros problèmes :-(. Cela dit, consultez installed.packages()

Edit: dang, Ninja'd par une minute!

Edit: une suggestion générale: chargez le paquet sos et vous trouverez très facile d’obtenir des réponses à beaucoup de questions "existe-t-il une fonction permettant de traiter XXXXX".

1
Carl Witthoft

Cela devrait le faire. Vous pouvez faire de required.packages un vecteur si vous devez en vérifier plusieurs.

required.packages <- "data.table"
new.packages <- required.packages[!(required.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
0
Maiasaura

En lisant les réponses de chacun, j'ai pris quelques allusions ici et là et j'ai créé les miennes. En fait, très semblable à la plupart cependant.

## These codes are used for installing packages
# function for installing needed packages
installpkg <- function(x){
    if(x %in% rownames(installed.packages())==FALSE) {
        if(x %in% rownames(available.packages())==FALSE) {
            paste(x,"is not a valid package - please check again...")
        } else {
            install.packages(x)           
        }

    } else {
        paste(x,"package already installed...")
    }
}

# install necessary packages
required_packages  <- c("sqldf","car")
lapply(required_packages,installpkg)
0
statistinks

Regardé mon ancienne fonction, mis à jour en utilisant les conseils ci-dessus et voici ce que j'ai.

# VERSION 1.0
assign("installP", function(pckgs){
    ins <- function(pckg, mc){
        add <- paste(c(" ", rep("-", mc+1-nchar(pckg)), " "), collapse = "");
        if( !require(pckg,character.only=TRUE) ){
            reps <- c("http://lib.stat.cmu.edu/R/CRAN","http://cran.uk.R-project.org");
            for (r in reps) try(utils::install.packages(pckg, repos=r), silent=TRUE);
            if(!require(pckg,character.only = TRUE)){   cat("Package: ",pckg,add,"not found.\n",sep="");
            }else{                                      cat("Package: ",pckg,add,"installed.\n",sep="");}
        }else{                                          cat("Package: ",pckg,add,"is loaded.\n",sep=""); } }
    invisible(suppressMessages(suppressWarnings(lapply(pckgs,ins, mc=max(nchar(pckgs)))))); cat("\n"); 
}, envir=as.environment("dg_base"))

installP(c("base","a","TFX"))
Package: base ------------------- is loaded.
Package: a ---------------------- not found.
Package: TFX -------------------- installed.
0
Dom Grey