web-dev-qa-db-fra.com

La fonction dplyr :: select se heurte à MASS :: select

Si je charge le package MASS:

library(MASS)

puis chargez essayez de lancer dplyr::select, Je reçois une erreur:

library(dplyr)
mtcars %.%
select(mpg)

# Error in select(`__prev`, mpg) : unused argument (mpg)

Comment puis-je utiliser dplyr::select avec le package MASS chargé?

59
luciano

Comme dit Pascal, les travaux suivants

require(MASS)
require(dplyr)
mtcars %>%
   dplyr::select(mpg)
63
r.bot

Cela m’arrive plus souvent que je ne devrais l’avouer. dplyr se heurte à, entre autres, avec MASS::select, plyr::summarise et stats::filter, en particulier lors du chargement de paquets qui chargent une de ces bibliothèques via une bibliothèque (ils ne devraient pas, mais certains le font encore) ou lorsque vous chargez dplyr dans votre .Rprofile (non!). Et cela peut conduire à des problèmes assez obscurs, pas toujours un message d'erreur, en particulier des conflits avec plyr.

Je n'ai appris que récemment sur la fonction conflicts(). C'est utile, mais les "sur-rapports" sont en conflit lorsque deux packages ont des fonctions identiques, par exemple. tidyr :: %>% et dplyr :: %>%.

Alors j'ai écrit ne fonction pour me dire si je deviens fou ou s'il y a vraiment un conflit causant le bogue actuel. Il ne vérifie pas seulement les conflits, il vérifie également si un package souhaité est "au-dessus" et si les corps de la fonction sont réellement différents.

Cela s’applique par défaut à dplyr, mais vous pouvez spécifier un autre package à l’aide du paramètre want_package. Par exemple, je suis souvent dérouté par recode et alpha, qui sont réutilisés dans de nombreux packages.

L'utilisation est simplement: amigoingmad().

Par défaut, il "réparera" automatiquement les choses si dplyr n'est pas "au-dessus", en utilisant les commandes suivantes:

detach("package:dplyr", character.only = TRUE)
library("dplyr", character.only = TRUE)

Notez que la fonction signalera si une fonction spécifiée par l'utilisateur bloque dplyr, mais ne résout pas cela automatiquement pour des raisons de sécurité (il suffit de supprimer la fonction dans ce cas).

Pour l'instant, cette solution ne m'a posé aucun problème. Bien sûr, je ne préconiserais pas l’utilisation de cela dans le code de production, mais lorsque vous déboguez un fichier .Rmd - et que vous avez peut-être gâché l’ordre de chargement par accident, c’est un moyen rapide de le découvrir.

Si vous voulez cela dans un paquet:

devtools::install_github("rubenarslan/formr")
19
Ruben

Si vous chargez première la bibliothèque MASS et deuxième la dplyr une

library (MASS)
library (dplyr)

alors la première version de la fonction select dans votre session searchpaths () sera celle de la bibliothèque dplyr.

Par conséquent

select(mtcars, mpg)

travaillera comme

dplyr::select(mtcars, mpg)
8
dmontaner

Comme dans le commentaire de KFB ci-dessus, une solution simple que j'ai trouvée consiste à (1) charger vos packages, (2) ne vous inquiétez pas de l'ordre (ce qui peut être difficile avec des dépendances), (3) attribuez une priorité à votre package. d préfère "posséder" le namespace:

select <- dplyr::select
filter <- dplyr::filter

Par exemple, voyez comment le environment: namespace changements ci-dessous:

library(MASS)
select

  function (obj) 
  UseMethod("select")
  <bytecode: 0x7fbe822811b8>
  <environment: namespace:MASS>

select <- dplyr::select
select

  function (.data, ...) 
  {
      UseMethod("select")
  }
  <bytecode: 0x7fbe7c4a2f08>
  <environment: namespace:dplyr>
4
Omar Wasow

Une solution élégante consiste à utiliser le package conflicted qui:

  • génère des messages d'erreur informatifs en cas de conflits d'espaces de noms
  • offre une fonction explicite pour assigner une priorité d'espace de nom

Voir l'exemple de code ci-dessous, partiellement issu de https://github.com/r-lib/conflicted

# install.packages("devtools")
devtools::install_github("r-lib/conflicted")

library(conflicted)
library(dplyr)

# example of informative error message
filter(mtcars, cyl == 8)
#> Error: [conflicted] `filter` found in 2 packages.
#> Either pick the one you want with `::` 
#> * dplyr::filter
#> * stats::filter
#> Or declare a preference with `conflicted_prefer()`
#> * conflict_prefer("filter", "dplyr")
#> * conflict_prefer("filter", "stats")

# example of assigning priority with conflict_prefer function
conflict_prefer("filter", "dplyr")

filter(mtcars, cyl == 8) %>% head(2)
#    mpg cyl  disp  hp drat   wt  qsec vs am gear carb
# 1 18.7   8 360.0 175 3.15 3.44 17.02  0  0    3    2
# 2 14.3   8 360.0 245 3.21 3.57 15.84  0  0    3    4
1
Omar Wasow