Question Erreur lors de l'utilisation de dplyr dans une fonction


J'essaie de mettre en place une fonction qui crée un sous-ensemble de mon bloc de données d'origine, puis utilise SELECT et MUTATE de dplyr pour me donner le nombre d'entrées grandes / petites, basé sur la somme de la largeur et de la longueur des sépales / pétales. .

filter <- function (spp, LENGTH, WIDTH) {
  d <- subset (iris, subset=iris$Species == spp) # This part seems to work just fine
  large <- d %>%                       
    select (LENGTH, WIDTH) %>%   # This is where the problem arises.
    mutate (sum = LENGTH + WIDTH) 
  big_samples <- which(large$sum > 4)
 return (length(big_samples)) 
}

En gros, je veux que la fonction retourne le nombre de grandes fleurs. Cependant, lorsque j'exécute la fonction, j'obtiens l'erreur suivante -

filter("virginica", "Sepal.Length", "Sepal.Width")

 Error: All select() inputs must resolve to integer column positions.
The following do not:
*  LENGTH
*  WIDTH 

Qu'est-ce que je fais mal?


11
2017-12-09 19:01


origine


Réponses:


Vous rencontrez des problèmes NSE / SE, voir la vignette pour plus d'infos.

Brièvement, dplyr utilise une évaluation non standard (NSE) des noms, et le passage des noms de colonnes dans des fonctions le rompt, sans utiliser la version d'évaluation standard (SE).

Les versions SE du dplyr les fonctions se terminent par _. Tu peux voir ça select_ fonctionne bien avec vos arguments originaux.

Cependant, les choses deviennent plus compliquées lors de l'utilisation de fonctions. On peut utiliser lazyeval::interp pour convertir la plupart des arguments de fonction en noms de colonne, consultez la conversion du mutate à mutate_ Appelez votre fonction ci-dessous et plus généralement, l'aide: ?lazyeval::interp

Essayer:

filter <- function (spp, LENGTH, WIDTH) {
    d <- subset (iris, subset=iris$Species == spp) 
    large <- d %>%                       
        select_(LENGTH, WIDTH) %>%  
        mutate_(sum = lazyeval::interp(~X + Y, X = as.name(LENGTH), Y = as.name(WIDTH))) 
    big_samples <- which(large$sum > 4)
    return (length(big_samples)) 
}

17
2017-12-09 19:12



METTRE À JOUR: À partir de dplyr 0.7.0, vous pouvez utiliser eidy eval pour y parvenir.

Voir http://dplyr.tidyverse.org/articles/programming.html pour plus de détails.

filter_big <- function(spp, LENGTH, WIDTH) {
  LENGTH <- enquo(LENGTH)                    # Create quosure
  WIDTH  <- enquo(WIDTH)                     # Create quosure

  iris %>% 
    filter(Species == spp) %>% 
    select(!!LENGTH, !!WIDTH) %>%            # Use !! to unquote the quosure
    mutate(sum = (!!LENGTH) + (!!WIDTH)) %>% # Use !! to unquote the quosure
    filter(sum > 4) %>% 
    nrow()
}

filter_big("virginica", Sepal.Length, Sepal.Width)

> filter_big("virginica", Sepal.Length, Sepal.Width)
[1] 50

8
2018-06-23 21:01