Il me semble partager beaucoup de code avec des co-auteurs ces jours-ci. Beaucoup d’entre eux sont des utilisateurs novices/intermédiaires et ne réalisent pas qu’ils doivent installer des paquets qu’ils n’ont pas encore.
Existe-t-il un moyen élégant d’appeler installed.packages()
, comparez-le à ceux que je charge et installe s’il manque?
Oui. Si vous avez votre liste de paquets, comparez-la à la sortie de installed.packages()[,"Package"]
et installez les paquets manquants. Quelque chose comme ça:
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)
Autrement:
Si vous mettez votre code dans un paquet et en faites des dépendances, il sera automatiquement installé lors de l'installation de votre paquet.
Dason K. et moi avons le paquet pacman qui peut le faire très bien. La fonction p_load
dans le package effectue cette opération. La première ligne est juste pour s’assurer que pacman est installé.
if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
Vous pouvez simplement utiliser la valeur de retour de require
:
if(!require(somepackage)){
install.packages("somepackage")
library(somepackage)
}
J'utilise library
après l'installation, car une exception sera levée si l'installation a échoué ou si le package ne peut pas être chargé pour une autre raison. Vous rendez ceci plus robuste et réutilisable:
dynamic_require <- function(package){
if(eval(parse(text=paste("require(",package,")")))) return True
install.packages(package)
return eval(parse(text=paste("require(",package,")")))
}
L'inconvénient de cette méthode est que vous devez passer le nom du paquet entre guillemets, ce que vous ne faites pas pour le vrai require
.
Cette solution utilisera un vecteur de caractères contenant les noms de packages et tentera de les charger ou les installera si le chargement échoue. Cela dépend du comportement de retour de require
pour le faire parce que ...
require
renvoie (de manière invisible) une logique indiquant si le package requis est disponible
Par conséquent, nous pouvons simplement voir si nous avons pu charger le paquet requis et, dans le cas contraire, l’installer avec des dépendances. Donc, étant donné un vecteur de caractères de paquets que vous souhaitez charger ...
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" ) )
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')
"ggplot2" est le paquet. Il vérifie si le paquet est installé, sinon il l'installe. Il charge ensuite le package quelle que soit la branche prise.
Bien que la réponse de Shane soit vraiment bonne, pour l’un de mes projets, j’avais besoin de supprimer les messages de sortie, les avertissements et d’installer les paquets de façon automatique. J'ai finalement réussi à obtenir ce 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"] != "@CRAN@")
}
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)
}
Utilisation:
libraries <- c("ReadImages", "ggplot2")
for(library in libraries)
{
if(!UsePackage(library))
{
stop("Error!", library)
}
}
Beaucoup des réponses ci-dessus (et des doublons de cette question) reposent sur installed.packages
qui est de mauvaise forme. De la documentation:
Cela peut être lent lorsque des milliers de paquets sont installés, ne l'utilisez donc pas pour savoir si un paquet nommé est installé (utilisez system.file ou find.package), ni pour savoir si un paquet est utilisable (appel requis et vérifier la valeur de retour) ni pour trouver les détails d’un petit nombre de paquets (utilisez packageDescription). Il doit lire plusieurs fichiers par paquet installé, ce qui sera lent sous Windows et sur certains systèmes de fichiers montés sur le réseau.
Donc, une meilleure approche consiste à essayer de charger le paquet en utilisant require
et à installer si le chargement échoue (require
renverra FALSE
s'il n'est pas trouvé). Je préfère cette implémentation:
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)
}
}
qui peut être utilisé comme ceci:
using("RCurl","ggplot2","jsonlite","magrittr")
De cette façon, il charge tous les packages, puis revient en arrière et installe tous les packages manquants (qui, si vous le souhaitez, est un endroit pratique pour insérer une invite afin de demander si l'utilisateur souhaite installer des packages). Au lieu d'appeler install.packages
séparément pour chaque package, il transmet le vecteur entier des packages désinstallés une seule fois.
Voici la même fonction mais avec une fenêtre de dialogue qui demande si l'utilisateur veut installer les paquetages manquants
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)
}
}
}
# 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)
C’est l’objet de paquetage rbundler : fournir un moyen de contrôler les paquets installés pour un projet spécifique. Actuellement, le paquet fonctionne avec la fonctionnalité devtools pour installer les paquets dans le répertoire de votre projet. La fonctionnalité est similaire à celle de Ruby's bundler .
Si votre projet est un paquet (recommandé), il vous suffit de charger rbundler et de regrouper les paquets. La fonction bundle
examinera le fichier DESCRIPTION
de votre paquetage pour déterminer les paquets à regrouper.
library(rbundler)
bundle('.', repos="http://cran.us.r-project.org")
Maintenant, les packages seront installés dans le répertoire .Rbundle.
Si votre projet n'est pas un package, vous pouvez le simuler en créant un fichier DESCRIPTION
dans le répertoire racine de votre projet avec un champ Depends qui répertorie les packages que vous souhaitez installer (avec des informations de version facultatives):
Depends: ggplot2 (>= 0.9.2), arm, glmnet
Voici le dépôt github du projet si vous souhaitez contribuer: rbundler .
Sûr.
Vous devez comparer les "paquets installés" avec les "paquets souhaités". C'est très proche de ce que je fais avec CRANberries car j'ai besoin de comparer les 'paquets connus stockés' avec les 'paquets connus actuellement' pour déterminer les nouveaux paquets et/ou les paquets mis à jour.
Alors fais quelque chose comme
AP <- available.packages(contrib.url(repos[i,"url"])) # available t repos[i]
pour obtenir tous les packages connus, appelez simular pour les packages actuellement installés et comparez-le à un ensemble donné de packages cible.
La fonction simple suivante fonctionne comme un charme:
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)
}
(pas le mien, j'ai trouvé cela sur le Web il y a quelque temps et je l'utilisais depuis. je ne suis pas sûr de la source d'origine)
Utilisez Packrat
pour que les bibliothèques partagées soient exactement les mêmes et ne changent pas l'environnement des autres.
En termes d’élégance et de bonnes pratiques, je pense que vous vous y prenez fondamentalement de la mauvaise façon. le package Packrat
a été conçu pour ces problèmes. Il est développé par RStudio par Hadley Wickham. Au lieu de devoir installer des dépendances et éventuellement gâcher un environnement système, Packrat
utilise son propre répertoire et installe toutes les dépendances de vos programmes dans leur environnement et ne les touche pas.
Packrat est un système de gestion des dépendances pour R.
Les dépendances de paquets R peuvent être frustrantes. Avez-vous déjà eu besoin d'essais et d'erreurs pour déterminer quels packages R vous devez installer pour que le code de quelqu'un d'autre fonctionne, et vous restiez avec ces packages globalement installés pour toujours, car vous n'êtes pas sûr d'en avoir besoin ? Avez-vous déjà mis à jour un package pour que le code de l'un de vos projets fonctionne, mais que le package mis à jour empêche le code d'un autre projet de fonctionner?
Nous avons construit Packrat pour résoudre ces problèmes. Utilisez Packrat pour rendre vos projets R plus:
- Isolé: L'installation d'un nouveau package ou d'une mise à jour pour un projet ne cassera pas vos autres projets, et inversement. C’est parce que Packrat attribue à chaque projet sa propre bibliothèque de packages privés.
- Portable: transportez facilement vos projets d'un ordinateur à un autre, même sur différentes plates-formes. Packrat facilite l'installation des packages sur lesquels votre projet repose.
- Reproductible: Packrat enregistre les versions exactes du paquet dont vous dépendez et veille à ce que ces versions exactes soient celles qui sont installées où que vous soyez.
Vous pouvez simplement utiliser la fonction setdiff
pour obtenir les packages qui ne sont pas installés, puis les installer. Dans l'exemple ci-dessous, nous vérifions si les packages ggplot2
et Rcpp
sont installés avant de les installer.
_unavailable <- setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))
install.packages(unavailable)
_
Dans une ligne, ce qui précède peut être écrit comme suit:
_install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
_
J'utilise la fonction suivante pour installer le paquet si require("<package>")
se ferme avec une erreur de paquet non trouvé. Il interrogera les référentiels CRAN et Bioconductor à la recherche du paquet manquant.
Adapté du travail original de Joshua Wiley, 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)))
}
}
Exemple:
install.packages.auto(qvalue) # from bioconductor
install.packages.auto(rNMF) # from CRAN
PS: update.packages(ask = FALSE)
& biocLite(character(), ask=FALSE)
mettra à jour tous les packages installés sur le système. Cela peut prendre beaucoup de temps et constitue une mise à niveau complète de R qui peut ne pas être garantie tout le temps!
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);
La version à venir de RStudio (1.2), déjà disponible en tant qu'aperçu, inclura une fonctionnalité permettant de détecter les packages manquants dans les appels library()
et require()
, et invite l'utilisateur à les installer:
Détecter les paquets R manquants
De nombreux scripts R s'ouvrent avec les appels à
library()
etrequire()
pour charger les packages dont ils ont besoin pour s'exécuter. Si vous ouvrez un script R qui fait référence à des packages que vous n'avez pas installés, RStudio vous proposera désormais d'installer tous les packages nécessaires en un seul clic. Plus besoin de taperinstall.packages()
à plusieurs reprises jusqu'à ce que les erreurs disparaissent!
https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/
Cela semble répondre particulièrement bien à la préoccupation initiale de OP:
Beaucoup d’entre eux sont des utilisateurs novices/intermédiaires et ne réalisent pas qu’ils doivent installer des paquets qu’ils n’ont pas encore.
En ce qui concerne votre objectif principal "d'installer des bibliothèques qu'ils n'ont pas déjà." Et indépendamment de l'utilisation de "instllaed.packages ()". La fonction suivante masque la fonction d'origine de require. Il essaie de charger et de vérifier le paquet nommé "x". S'il n'est pas installé, installez-le directement, y compris les dépendances. et enfin le charger normalement. vous renommez le nom de la fonction 'require' en 'library' pour maintenir l'intégrité. La seule limitation est que les noms de paquets doivent être cités.
require <- function(x) {
if (!base::require(x, character.only = TRUE)) {
install.packages(x, dep = TRUE) ;
base::require(x, character.only = TRUE)
}
}
Ainsi, vous pouvez charger et installer le paquet de l'ancienne manière de R. require ("ggplot2") require ("Rcpp")
En utilisant la famille lapply et l’approche par fonctions anonymes, vous pouvez:
||
évaluation paresseuse).Affiche l'état de chargement final de chaque colis (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
Assez basique.
pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)
Je pensais apporter celle que j'utilise:
testin <- function(package){if (!package %in% installed.packages())
install.packages(package)}
testin("packagename")
J'utilise ce qui suit pour vérifier si le paquet est installé et si les dépendances sont mises à jour, puis charge le paquet.
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, ])
}
Voici mon code pour cela:
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)
library <- function(x){
x = toString(substitute(x))
if(!require(x,character.only=TRUE)){
install.packages(x)
base::library(x,character.only=TRUE)
}}
Cela fonctionne avec des noms de paquets non cités et est assez élégant (voir la réponse de GeoObserver)
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
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 }
Dans mon cas, je voulais un liner que je pourrais lancer depuis la ligne de commande (en fait via un Makefile). Voici un exemple d'installation de "VGAM" et "feather" s'ils ne sont pas déjà installés:
R -e 'for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")'
De l'intérieur de R ce serait juste:
for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")
Il n'y a rien ici au-delà des solutions précédentes sauf que:
repos
(pour éviter toute fenêtre contextuelle demandant le miroir à utiliser)Notez également l'important character.only=TRUE
(sans lui, le require
essaierait de charger le paquet p
).