Элегантный способ проверить недостающие пакеты и установить их?

Кажется, в наши дни я использую много кода с соавторами. Многие из них являются новичками/промежуточными пользователями R и не понимают, что им приходится устанавливать пакеты, которые у них еще нет.

Есть ли элегантный способ вызвать installed.packages(), сравнить его с теми, которые я загружаю и устанавливаю, если они отсутствуют?

Ответ 1

Да. Если у вас есть список пакетов, сравните его с выходом из installed.packages()[,"Package"] и установите недостающие пакеты. Что-то вроде этого:

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)

В противном случае:

Если вы поместите свой код в пакет и сделаете его зависимыми, тогда они будут автоматически установлены при установке вашего пакета.

Ответ 2

Dason K. и у меня есть пакет pacman, который может сделать это красиво. Функция p_load в пакете делает это. Первая строка предназначена только для обеспечения установки pacman.

if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)

Ответ 3

Вы можете просто использовать возвращаемое значение require:

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

Я использую library после установки, потому что это вызовет исключение, если установка не была успешной или пакет не может быть загружен по какой-либо другой причине. Вы делаете это более надежным и повторно используемым:

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

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

Недостатком этого метода является то, что вам нужно передать имя пакета в кавычках, чего вы не делаете для реального require.

Ответ 4

Это решение примет вектор символа имен пакетов и попытается их загрузить или установить, если загрузка не удалась. Он полагается на поведение возврата require, чтобы сделать это, потому что...

require возвращает (невидимо) логическое указание доступности пакета

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

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

Ответ 5

if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')

"ggplot2" - это пакет. Он проверяет, установлен ли пакет, если он не устанавливает его. Затем он загружает пакет независимо от того, какая ветка потребовалась.

Ответ 6

Хотя ответ Шейна действительно хорош, для одного из моих проектов мне нужно было удалить сообщения, предупреждения и установить пакеты автоматически. Мне наконец удалось получить этот 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"] != "@[email protected]")
}

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

Использование:

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

Ответ 7

Многие ответы выше (и на дубликаты этого вопроса) полагаются на installed.packages, который является плохим. Из документации:

Это может быть медленным, когда установлены тысячи пакетов, поэтому не используйте это, чтобы узнать, установлен ли именованный пакет (используйте файл system.file или find.package), а также выяснить, можно ли использовать пакет (требуется вызов и проверить возвращаемое значение), а также не найти детали небольшого количества пакетов (используйте packageDescription). Он должен прочитать несколько файлов на установленный пакет, который будет медленным в Windows и некоторых сетевых файловых системах.

Таким образом, лучший подход - попытаться загрузить пакет с помощью require и установить при неудачной загрузке (require вернет FALSE, если он не найден). Я предпочитаю эту реализацию:

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

который можно использовать следующим образом:

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

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

Здесь же функция, но с окном диалоговое окно, которое спрашивает, хочет ли пользователь установить недостающие пакеты

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

Ответ 8

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

Ответ 9

Это цель пакета rbundler: предоставить способ управления пакетами, установленными для конкретного проекта. В настоящий момент пакет работает с функциональностью devtools для установки пакетов в каталог проекта. Функциональность похожа на Ruby bundler.

Если ваш проект является пакетом (рекомендуется), вам нужно только загрузить rbundler и расслоить пакеты. Функция bundle будет смотреть на ваш пакет DESCRIPTION файл, чтобы определить, какие пакеты нужно связывать.

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

Теперь пакеты будут установлены в каталоге .Rbundle.

Если ваш проект не является пакетом, вы можете подделать его, создав файл DESCRIPTION в корневом каталоге проекта с полем Depends, в котором перечислены пакеты, которые вы хотите установить (с дополнительной информацией о версии):

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

Здесь репозиторий github для проекта, если вы заинтересованы в содействии: rbundler.

Ответ 10

Конечно.

Вам нужно сравнить "установленные пакеты" с "желаемыми пакетами". Это очень близко к тому, что я делаю с CRANberries, поскольку мне нужно сравнить "сохраненные известные пакеты" с "известными в настоящее время пакетами" для определения новых и/или обновленные пакеты.

Итак, сделайте что-нибудь вроде

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

чтобы получить все известные пакеты, имитировать вызов установленных пакетов и сравнить их с заданным набором целевых пакетов.

Ответ 11

Следующая простая функция работает как шарм:

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

(не мой, нашел это в Интернете некоторое время назад и использовал его с тех пор, не уверен в исходном источнике)

Ответ 12

Я использую следующую функцию для установки пакета, если require("<package>") завершает работу с ошибкой пакета. Он будет запрашивать как хранилища CRAN, так и Bioconductor для отсутствия пакета.

Адаптировано из оригинальной работы Джошуа Вили, 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)))
  }
}

Пример:

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

PS: update.packages(ask = FALSE) и biocLite(character(), ask=FALSE) будут обновлять все установленные пакеты в системе. Это может занять много времени и рассмотреть его как полное обновление R, которое не может быть гарантировано все время!

Ответ 13

Вы можете просто использовать функцию setdiff, чтобы получить пакеты, которые не установлены, а затем установить их. В приведенном ниже примере мы проверяем, установлены ли пакеты ggplot2 и Rcpp, прежде чем устанавливать их.

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

В одной строке вышесказанное может быть записано как:

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

Ответ 14

Используйте packrat, чтобы общие библиотеки были одинаковыми и не меняли другую среду.

С точки зрения элегантности и передовой практики, я думаю, что вы в корне идете по этому пути неправильно. пакет packrat был разработан для этих проблем. Он разработан RStudio Хэдли Уикхэмом. Вместо того, чтобы устанавливать зависимостей и, возможно, испортить кому-то систему окружения, packrat использует свой собственный каталог и устанавливает все зависимости для ваших программ в своих и не затрагивает кого-то среду.

Packrat - это система управления зависимостями для R.

Зависимости пакетов R могут быть разочаровывающими. Вам когда-нибудь приходилось использовать пробную версию и ошибки, чтобы выяснить, какие пакеты R вам нужно установить, чтобы заставить кого-то работать с кодом elses, а затем остался с этими пакетами, установленными на глобальном уровне навсегда, потому что теперь вы не уверены, нужны ли они вам? Вы когда-нибудь обновляли пакет, чтобы получить код в одном из ваших проектов, чтобы работать, только чтобы найти, что обновленный пакет заставляет код работать в другом проекте?

Мы создали пакет для решения этих проблем. Используйте packrat, чтобы увеличить ваши проекты R:

  • Изолированные. Установка нового или обновленного пакета для одного проекта не приведет к разрыву ваших других проектов и наоборот. Thats, потому что packrat дает каждому проекту свою собственную библиотеку частных пакетов.
  • Portable: легко переносите свои проекты с одного компьютера на другой, даже на разных платформах. Packrat упрощает установку пакетов, от которых зависит ваш проект.
  • Воспроизводимые: Packrat записывает точные версии пакетов, на которые вы полагаетесь, и гарантирует, что те точные версии будут теми, которые будут установлены везде, где бы вы ни находились.

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

Ответ 15

Я реализовал функцию для установки и загрузки требуемых 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);

Ответ 16

Относительно вашей основной цели "установить библиотеки, которые у них еще нет" и независимо от использования "instllaed.packages()". Следующая функция маскирует исходную функцию require. Он пытается загрузить и проверить именованный пакет "x", если он не установлен, установить его напрямую, включая зависимости; и, наконец, загрузите его нормальным образом. вы переименовываете имя функции из "require" в "library" для поддержания целостности. Единственное ограничение - имена пакетов должны быть указаны.

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

Таким образом, вы можете загружать и устанавливать пакет по старому способу R.   require ( "ggplot2" )   require ( "Rcpp" )

Ответ 17

Довольно простой.

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

Ответ 18

Думаю, что я внес бы то, что я использую:

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

Ответ 19

Используя семейный подход и анонимную функцию, вы можете:

  1. Попробуйте прикрепить все перечисленные пакеты.
  2. Установка только отсутствует (используя || ленивый анализ).
  3. Попытайтесь снова присоединить те, которые отсутствовали на шаге 1 и были установлены на шаге 2.
  4. Напечатайте статус окончательной загрузки каждого пакета (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 
    

Ответ 20

Предстоящая версия RStudio (1.2), уже доступная в качестве предварительного просмотра, будет включать функцию обнаружения отсутствующих пакетов в вызовах library() и require() и предложения пользователю установить их:

Обнаружить пропущенные пакеты R

Многие R-скрипты открываются вызовами library() и require() для загрузки пакетов, которые им необходимы для выполнения. Если вы откроете скрипт R, который ссылается на пакеты, которые вы не установили, RStudio предложит установить все необходимые пакеты одним щелчком мыши. Больше не install.packages() набирать install.packages() несколько раз, пока ошибки не исчезнут!
https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/

Похоже, это особенно хорошо отвечает первоначальной проблеме ОП:

Многие из них являются начинающими/промежуточными пользователями R и не понимают, что им нужно устанавливать пакеты, которых у них еще нет.

Ответ 21

Я использую следующее, которое будет проверять, установлен ли пакет и обновлены зависимости, а затем загружает пакет.

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

Ответ 22

Вот мой код для него:

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)

Ответ 23

 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 }

Ответ 24

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

Это работает с именами без кавычек и довольно элегантно (см. ответ GeoObserver)

Ответ 25

source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")

Ответ 26

В моем случае я хотел один лайнер, который я мог запустить из командной строки (на самом деле через Makefile). Вот пример установки "VGAM" и "Перо", если они еще не установлены:

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

Изнутри R это будет просто:

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

Здесь нет ничего кроме предыдущих решений, кроме того, что:

  • Я держу это в одной строке
  • Я жестко repos параметр repos (чтобы избежать всплывающих окон, спрашивающих об использовании зеркала)
  • Я не пытаюсь определить функцию, которая будет использоваться в другом месте

Также обратите внимание на важный character.only=TRUE (без него require попытается загрузить пакет p).

Ответ 27

  packages_installed <- function(pkg_list){
        pkgs <- unlist(pkg_list)
        req <- unlist(lapply(pkgs, require, character.only = TRUE))
        not_installed <- pkgs[req == FALSE]
        lapply(not_installed, install.packages, 
               repos = "http://cran.r-project.org")# add lib.loc if needed
        lapply(pkgs, library, character.only = TRUE)
}

Ответ 28

попробуйте следующее:

if (!require(MyDesiredLibrary)) {
   install.packages("MyDesiredLibrary")
}