Проверьте установленные пакеты перед запуском install.packages()

У меня есть R script, который используется несколькими пользователями на разных компьютерах. Одна из его строк содержит команду install.packages("xtable").

Проблема заключается в том, что каждый раз, когда кто-то запускает script, R тратит много времени, по-видимому, на переустановку пакета (на самом деле это занимает некоторое время, так как в реальном случае есть вектор нескольких пакетов).

Как я могу сначала проверить, установлены ли пакеты, а затем запустить только install.packages() для тех, которые не являются?

Ответ 1

попробуйте: require("xtable") или "xtable" %in% rownames(installed.packages())

Ответ 2

Это функция, которую я часто использовал для проверки пакета, установки в противном случае и загрузки снова:

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

Работает как pkgTest("xtable"). Он работает только в том случае, если установлено зеркало, но вы можете ввести его в вызовы require.

Ответ 3

Если вы хотите сделать это как можно проще:

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

Замените пакеты, перечисленные в первой строке, теми, которые необходимы для запуска вашего кода, и voilà!

Ответ 4

Также есть пакет CRAN pacman, который имеет функцию p_load для установки одного или нескольких пакетов (но только при необходимости), а затем их загрузки.

Ответ 5

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

Ответ 6

Я предлагаю более легкое решение, используя 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

Ответ 7

Я нашел packages script где-то, что я всегда помещал в каждый script для загрузки моих библиотек. Он будет выполнять всю обработку вашей библиотеки (загрузка, установка и загрузка) и только при необходимости.

# 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

Ответ 8

requiredPackages = c('plyr','ggplot2','ggtern')
for(p in requiredPackages){
  if(!require(p,character.only = TRUE)) install.packages(p)
  library(p,character.only = TRUE)
}

Ответ 9

Решение, которое я использовал, было получено из ввода Sacha Epskamp и Shuguang. Здесь функция:

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

Он работает тихо, ничего не повторяя, если пакет "pacote" уже установлен и установлен в противном случае. Не забудьте написать имя пакета между кавычками!

Ответ 10

Или массово замаскированный пример из drknexus/repsych в github, glibrary. Есть почти наверняка более эффективные и лучшие способы сделать это, но я запрограммировал его на долгое время назад, и он в основном работает.

  • Он работает, даже если репо не было выбрано, если использовать параметр облака по умолчанию, если он доступен. Если вы используете более старую версию R, она откатится и отобразит зеркало на основе кода страны.
  • Он пытается загрузить библиотеку (этот шаг можно сделать более эффективным, используя некоторые из вышеперечисленных методов)
    • Если он не работает, он попытается установить его
    • Если сбой установки, он уведомит вас, какие пакеты не смогли установить
  • Правильно, пакеты, несколько пакетов могут быть загружены/установлены за один проход вместе с их зависимостями (по крайней мере, обычно здесь может быть ошибка).

например: glibrary(xtable,sos,data.table), но я не думаю, что это будет волноваться, если вы вместо этого назовете glibrary("xtable","sos","data.table"). Поднимает/тянет/вилки приветствуем.

Код для функции:

#' 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"]] == "@[email protected]") {
      #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

Ответ 11

Я реализовал функцию для установки и загрузки требуемых R-пакетов. Надежда может помочь. Вот код:

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

Ответ 12

Как насчет этого?

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

Ответ 13

Почему бы просто не удалить строку из script? Если у конечного пользователя нет настроек для установки xtable по мере необходимости, у вас возникают большие проблемы:-(. Тем не менее, проверьте installed.packages()

Изменить: dang, Ninja'd ONE minute!

Изменить: общее предложение: загрузить пакет sos, и вам будет очень легко получить ответы на многие вопросы "есть функция, которая делает XXXXX".

Ответ 14

Это должно сделать это. Вы можете сделать required.packages вектор, если вам нужно проверить более одного.

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

Ответ 15

Считывая все ответы, я кое-что понял и создал и создал. На самом деле очень похоже на большинство, хотя.

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

Ответ 16

Посмотрел на мою старую функцию, обновил ее, используя подсказки выше, и это то, что я получил.

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