Quelle est la différence entre require () et library ()?

565

Quelle est la difference entre require()et library()?

Marco
la source
7
Ajout d'un lien vers le blog de @ Yihui à moins qu'il ne souhaite publier une version de celui-ci comme réponse. yihui.name/en/2014/07/library-vs-require
MichaelChirico
4
Résumant le billet de blog de @ Yihui: "Mesdames et messieurs, je l'ai déjà dit: require () est la mauvaise façon de charger un package R; utilisez plutôt library ()"
De Novo
1
@DanHall ... car library()échoue immédiatement bruyamment, tôt et avec un message d'erreur pertinent (si le package n'est pas installé ou n'a pas pu être chargé), alors que require()ne déclenche pas d'erreur, retourne simplement silencieusement booléen FALSE qui est jeté, et provoque l'échec du code plus tard et de manière plus cryptée avec la Error: object “bar” not foundligne 175 (par exemple).
smci
1
@KonradRudolph: Terminé! Merci pour votre avis.
Marco

Réponses:

87

En plus des bons conseils déjà donnés, j'ajouterais ceci:

Il est probablement préférable d'éviter d'utiliser à require() moins que vous n'utilisiez réellement la valeur qu'elle renvoie, par exemple dans une boucle de vérification d'erreur telle que donnée par Thierry.

Dans la plupart des autres cas, il est préférable de l'utiliser library(), car cela donnera un message d'erreur au moment du chargement du package si le package n'est pas disponible. require()échouera sans erreur si le paquet n'est pas là. C'est le meilleur moment pour savoir si le paquet doit être installé (ou n'existe peut-être même pas parce qu'il s'est mal orthographié). Obtenir un retour d'erreur tôt et au moment opportun évitera des maux de tête possibles en recherchant pourquoi le code échoue plus tard lorsqu'il tente d'utiliser des routines de bibliothèque

dww
la source
356

Il n'y en a pas beaucoup dans le travail quotidien.

Cependant, selon la documentation des deux fonctions (accessible en mettant un ?avant le nom de la fonction et en appuyant sur Entrée), il requireest utilisé à l'intérieur des fonctions, car il génère un avertissement et continue si le package n'est pas trouvé, alors libraryqu'il générera une erreur.

richiemorrisroe
la source
1
#richiemorrisroe: Merci. Cela signifie-t-il que si je charge les packages dont j'ai besoin au tout début de mon code R, peu importe celui que je choisis?
Marco
6
tant que vous ne chargez pas de packages dans une fonction, cela ne fait vraiment aucune différence. Je charge tous mes packages à l'aide de require et je ne savais pas quelle était la différence jusqu'à ce que je lise l'aide après avoir vu votre question.
richiemorrisroe
45
L'autre raison que j'utilise requireest que cela m'empêche de faire référence aux packages comme libraries, une pratique qui pousse le R-cognoscenti le long du mur. Le libraryest l'emplacement du répertoire où les paquets sont assis.
IRTFM
22
Ils ont des différences très pertinentes. Ne pas utiliser require, sauf si vous vérifiez la valeur de retour (et dans ce cas, il existe généralement de meilleures alternatives, par exemple loadNamespace).
Konrad Rudolph
256

Un autre avantage de require()est qu'il renvoie une valeur logique par défaut. TRUEsi les packages sont chargés, FALSEsinon.

> test <- library("abc")
Error in library("abc") : there is no package called 'abc'
> test
Error: object 'test' not found
> test <- require("abc")
Loading required package: abc
Warning message:
In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
  there is no package called 'abc'
> test
[1] FALSE

Vous pouvez donc l'utiliser require()dans des constructions comme celle ci-dessous. Ce qui est surtout pratique si vous souhaitez distribuer votre code à notre installation R où les packages peuvent ne pas être installés.

if(require("lme4")){
    print("lme4 is loaded correctly")
} else {
    print("trying to install lme4")
    install.packages("lme4")
    if(require(lme4)){
        print("lme4 installed and loaded")
    } else {
        stop("could not install lme4")
    }
}
Thierry
la source
65

Vous pouvez utiliser require()si vous souhaitez installer des packages si et seulement si nécessaire, tels que:

if (!require(package, character.only=T, quietly=T)) {
    install.packages(package)
    library(package, character.only=T)
}

Pour plusieurs packages, vous pouvez utiliser

for (package in c('<package1>', '<package2>')) {
    if (!require(package, character.only=T, quietly=T)) {
        install.packages(package)
        library(package, character.only=T)
    }
}

Conseils de pro:

  • Lorsqu'il est utilisé dans le script, vous pouvez éviter un écran de dialogue en spécifiant le reposparamètre de install.packages(), tel que

    install.packages(package, repos="http://cran.us.r-project.org")
  • Vous pouvez envelopper require()et library()dans suppressPackageStartupMessages(), eh bien, les messages de paquet suppress, et également utiliser les paramètres require(..., quietly=T, warn.conflicts=F)si nécessaire pour maintenir le calme installations.

Daniel Sparing
la source
46

Utilisez toujours library. Jamais 1 utilisation require.

( 1 Presque jamais. Peut-être .)

En résumé, cela est dû au fait que, lors de l'utilisation require, votre code peut produire des résultats différents et erronés, sans signaler d'erreur . C'est rare mais pas hypothétique! Considérez ce code, qui donne des résultats différents selon que {dplyr} peut être chargé:

require(dplyr)

x = data.frame(y = seq(100))
y = 1
filter(x, y == 1)

Cela peut conduire à des résultats subtilement faux. Utiliser libraryau lieu de requirerenvoie une erreur ici, signalant clairement que quelque chose ne va pas. C'est bien .

Cela rend également le débogage de tous les autres échecs plus difficile: si vous requireun package au début de votre script et utilisez ses exportations à la ligne 500, vous obtiendrez un message d'erreur «objet« foo »introuvable» à la ligne 500, plutôt qu'un erreur "il n'y a pas de package appelé 'bla'".

Le seul cas d'utilisation acceptable requireest lorsque sa valeur de retour est immédiatement vérifiée, comme le montrent certaines des autres réponses. Il s'agit d'un modèle assez courant, mais même dans ces cas, il est préférable (et recommandé, voir ci-dessous) de séparer le contrôle d'existence et le chargement du package.

Plus techniquement, requireappelle en fait en libraryinterne (si le package n'était pas déjà attaché - requireeffectue donc une vérification redondante, car vérifie library également si le package a déjà été chargé). Voici une implémentation simplifiée de requirepour illustrer ce qu'il fait:

require = function (package) {
    already_attached = paste('package:', package) %in% search()
    if (already_attached) return(TRUE)
    maybe_error = try(library(package, character.only = TRUE)) 
    success = ! inherits(maybe_error, 'try-error')
    if (! success) cat("Failed")
    success
}

Les développeurs R expérimentés conviennent:

Yihui Xie , auteur de {knitr}, {bookdown} et de nombreux autres packages dit :

Mesdames et messieurs, je l'ai déjà dit: require () est la mauvaise façon de charger un package R; utilisez plutôt library ()

Hadley Wickham , auteur de packages R plus populaires que quiconque, dit

Utilisation library(x)dans les scripts d'analyse de données. […] Vous n'avez jamais besoin d'utiliser require()( requireNamespace()c'est presque toujours mieux)

Konrad Rudolph
la source
J'allais pointer exactement la même chose, sauf si vous appelez TOUTES les fonctions avec la syntaxe class::function, utilisez library()pour éviter précisément cela.
Ghost
19
?library

et vous allez voir:

library(package)et à la require(package)fois charger le package avec le nom packageet le mettre sur la liste de recherche. requireest conçu pour être utilisé à l'intérieur d'autres fonctions; il retourne FALSEet donne un avertissement (plutôt qu'une erreur comme c'est le library()cas par défaut) si le package n'existe pas. Les deux fonctions vérifient et mettent à jour la liste des packages actuellement chargés et ne rechargent pas un package déjà chargé. (Si vous souhaitez recharger un tel package, appelez detach(unload = TRUE)ou d' unloadNamespaceabord.) Si vous souhaitez charger un package sans le mettre dans la liste de recherche, utilisez requireNamespace.

dwstu
la source
9

Ma théorie initiale sur la différence était que librarycharge les packages qu'il soit déjà chargé ou non, c'est-à-dire qu'il peut recharger un package déjà chargé, tout en requirevérifiant simplement qu'il est chargé, ou le charge s'il ne l'est pas (donc l'utilisation dans les fonctions qui reposent sur un certain paquet). Cependant, la documentation réfute cela et déclare explicitement qu'aucune fonction ne rechargera un package déjà chargé.

dsb
la source
18
c'est intéressant, mais ce n'est pas vraiment une réponse à la question ...?
Ben Bolker
3

Voici la différence sur un paquet déjà chargé. Bien qu'il soit vrai que require et library ne chargent pas le package. La bibliothèque fait beaucoup d'autres choses avant de vérifier et de quitter.

Je recommanderais de supprimer "require" depuis le début d'une fonction exécutée 2mil fois de toute façon, mais si, pour une raison quelconque, je devais la garder. exiger est techniquement une vérification plus rapide.

microbenchmark(req = require(microbenchmark), lib = library(microbenchmark),times = 100000)
Unit: microseconds
 expr    min     lq      mean median     uq        max neval
  req  3.676  5.181  6.596968  5.655  6.177   9456.006 1e+05
  lib 17.192 19.887 27.302907 20.852 22.490 255665.881 1e+05
Forme
la source
Je dirais que c'est une bonne raison de corriger l'implémentation à la libraryplace (les deux fonctions, telles qu'elles sont actuellement livrées avec R, sont un énorme gâchis).
Konrad Rudolph
@KonradRudolph eh bien, si quelqu'un va réparer la bibliothèque, il peut peut-être aussi activer explicitement le chargement par version et faire de l'attachement une option d'argument
Forme
Oui, je suis absolument d'accord, mais cela changerait la sémantique, pas seulement la performance. Quoi qu'il en soit, le versioning ne fonctionnera jamais avec les packages dans R, malheureusement. Je travaille sur un remplacement pour cela (vraiment!). Quant à l'attachement, vous pouvez utiliser loadNamespace, qui charge un package et retourne son espace de noms, sans l'attacher.
Konrad Rudolph