web-dev-qa-db-fra.com

dplyr :: group_by_ avec entrée de chaîne de caractères de plusieurs noms de variables

J'écris une fonction où l'utilisateur est invité à définir une ou plusieurs variables de regroupement dans l'appel de fonction. Les données sont ensuite regroupées à l'aide de dplyr et cela fonctionne comme prévu s'il n'y a qu'une seule variable de regroupement, mais je n'ai pas compris comment le faire avec plusieurs variables de regroupement.

Exemple:

x <- c("cyl")
y <- c("cyl", "gear")
dots <- list(~cyl, ~gear)

library(dplyr)
library(lazyeval) 

mtcars %>% group_by_(x)             # groups by cyl
mtcars %>% group_by_(y)             # groups only by cyl (not gear)
mtcars %>% group_by_(.dots = dots)  # groups by cyl and gear, this is what I want.

J'ai essayé de transformer y en la même chose que dots en utilisant:

mtcars %>% group_by_(.dots = interp(~var, var = list(y)))
#Error: is.call(expr) || is.name(expr) || is.atomic(expr) is not TRUE

Comment utiliser une chaîne d'entrée définie par l'utilisateur de> 1 noms de variables (comme y dans l'exemple) pour regrouper les données à l'aide de dplyr?

(Cette question est en quelque sorte liée à celle-ci mais pas de réponse là-bas.)

24
talat

Pas besoin de interp ici, utilisez simplement as.formula pour convertir les chaînes en formules:

dots = sapply(y, . %>% {as.formula(paste0('~', .))})
mtcars %>% group_by_(.dots = dots)

La raison pour laquelle votre approche interp ne fonctionne pas est que l'expression vous renvoie ce qui suit:

~list(c("cyl", "gear"))

- pas ce que tu veux. Vous pouvez, bien sûr, sapplyinterp sur y, ce qui reviendrait à utiliser as.formula au dessus:

dots1 = sapply(y, . %>% {interp(~var, var = .)})

Mais, en fait, vous pouvez également passer directement y:

mtcars %>% group_by_(.dots = y)

La vignette dplyr sur l'évaluation non standard va plus en détail et explique la différence entre ces approches.

23
Konrad Rudolph

slice_rows() du package purrrlyr ( https://github.com/hadley/purrrlyr ) regroupe un data.frame en prenant un vecteur de colonne noms (chaînes) ou positions (entiers):

y <- c("cyl", "gear")
mtcars_grp <- mtcars %>% purrrlyr::slice_rows(y)

class(mtcars_grp)
#> [1] "grouped_df" "tbl_df"     "tbl"        "data.frame"

group_vars(mtcars_grp)
#> [1] "cyl"  "gear"

Particulièrement utile maintenant que group_by_() a été dépréciée.

1
wjchulme