2010-11-03 2 views
203

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

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

+1

@krlmlr Как насчет принятого ответа устарел и требует пересмотра? Он работает для меня (для нескольких быстрых тестов) в разделе 'R version 3.0.2 (2013-09-25) x86_64-w64-mingw32/x64 (64-разрядный)'. –

+1

@BrianDiggs: Появилось по крайней мере три пакета, которые адресуют эту проблему, только один из них приведен ниже. Есть еще больше - вот в чем вопрос. – krlmlr

+2

@krlmlr Кажется, что есть ироническая проблема с курицей и яйцом об использовании пакета для обеспечения (других) необходимых пакетов. Но, конечно, стоит того, чтобы кто-то, кто знает о них, написал ответ. –

ответ

193

Да. Если у вас есть список пакетов, сравните его с выводом 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) 

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

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

+6

Я думаю, что правильный синтаксис: ' if (length (new.packages)> 0) {install.packages (new.packages) } ' – 2015-08-14 10:16:07

+3

@psql, Shine прав, поскольку«> 0 »является« неявным »в условии if. запустите это для проверки: 'new.packages <- c (1,2)' 'length (new.packages)' 'if (length (new.packages)) {print (" hello! ") } else {print ("oh no!")} ' –

+5

В документе doc.packages указано:« Это может быть медленным, когда тысячи пакетов установлены, поэтому не используйте это, чтобы узнать, установлен ли именованный пакет (используйте system.file или find.package) ... » –

5

Несомненно.

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

Так что-то вроде

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

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

15

Хотя ответ Шейна действительно хорош, для одного из моих проектов мне нужно было удалить сообщения, предупреждения и установить пакеты automagically. Я, наконец, удалось получить этот сценарий:

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

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

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

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

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

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

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

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

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

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

10

Это решение примет вектор символа имен пакетов и попытается загрузить их или установить, если загрузка не удалась. Он опирается на поведение возвратного 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")) 
+0

Не хотите ли вы снова вызвать 'require' после установки? – krlmlr

+0

@krlmlr Нет, потому что для того, чтобы оператор 'if' был оценен, он должен сначала оценить' require', побочный эффект которого загружает пакет, если он доступен! –

+1

SimonO101: Я думаю, что krlmlr означает в выражении if после вызова 'install.packages', так как это фактически не загрузит этот пакет. Но (to @krlmlr) я подозреваю, что намерение состоит в том, что этот фрагмент кода будет вызываться только один раз; вы не будете писать это каждый раз, когда вам понадобится пакет. Вместо этого вы запускаете его один раз раньше времени, а затем вызываете 'require', как обычно, по мере необходимости. – Aaron

37

Вы можете просто использовать возвращаемое значение 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.

+1

Вы можете значительно упростить свою жизнь, используя 'character.only = TRUE' в' require', но тогда, я думаю, нет ничего, чтобы отличить ваш ответ от моего. –

+0

Что такое «[Этот ответ]»? – Mars

+0

@Mars Я думаю, что это была ссылка на ответ, который больше не существует (или, возможно, ссылку, которая никогда не существовала, потому что я забыл ее заполнить). – Livius

136

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

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

Это выглядит как удобный пакет. Каждый должен рассказать своим друзьям об этом! – Dason

+1

Каков статус пакета? Я не могу видеть на C-RAN. – MERose

+1

@ Дасон и я довольно заняты написанием диссертации. Мы решили выпустить 14 февраля в CRAN. –

2

Что касается вашей главной цели «чтобы установить библиотеки они уже не имеют.» И независимо от того, с помощью «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. требуют ("ggplot2") требуют ("Rcpp")

+0

Если вам больше не нравится ваш ответ, не подвергайте его вандализму - просто удалите его. –

+0

Ну, я пробовал, но я не мог. Я думаю, что мое расширение NoScript для FScript отключает его или у меня нет прав и кредитов, чтобы удалить мой собственный ответ. LoL Однако, я думаю, что Ливий довольно близок к моему ответу, подумал, не маскируя. Спасибо, Майкл Петротта. для уведомления. – GeoObserver

+0

Вы должны увидеть ссылку «удалить» над этими комментариями. Если вы этого не сделаете, и вы все еще хотите удалить, используйте ссылку 'flag', выберите« other »и объясните модератору, что вы хотите, чтобы ответ был удален. –

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

попробовать это:

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

По существу дубликат ответа Ливия у вершины. – Gregor

3

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

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

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

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

1

Вот мой код для этого:

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

Я использую следующую функцию т o установить пакет, если 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, которое не может быть гарантировано все время!

+0

Это может быть улучшено путем проверки того, действительно ли пакеты доступны на кране или bc. Также он должен использовать библиотеку в конце, чтобы выбросить ошибку, если установка завершилась неудачно или пакет не существует. См. Мою улучшенную версию под названием 'loadpack()' на https://raw.githubusercontent.com/holgerbrandl/datautils/master/R/core_commons.R –

1
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 } 
2

Достаточно простой.

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

Мысль я бы внести свой вклад в один я использую:

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

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

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

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

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

Я использую тот же подход. Мы также можем использовать 'installed.packages() [, 'Package']' вместо 'rownames (installed.packages())'. – Scudelletti

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

Это работает с некотируемыми именами пакетов и довольно элегантный (см ответа GeoObserver в)

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

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

2

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

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

Packrat представляет собой систему управления зависимость для R.

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

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

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

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

6

Многие из перечисленных выше (и на дубликатах этого вопроса) ответы полагаться на 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) 
     } 
    } 
} 
1
source("https://bioconductor.org/biocLite.R") 
if (!require("ggsci")) biocLite("ggsci") 
0

В моем случае, я хотел один вкладыш, который я мог бы запустить из командной строки (фактически через 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") 

Там нет ничего, за предыдущие решения, за исключением что:

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^