Estoy tratando de transferir mi comprensión de plyr a dplyr, pero no puedo entender cómo agrupar por múltiples columnas.
# make data with weird column names that can't be hard coded
data = data.frame(
  asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)
# get the columns we want to average within
columns = names(data)[-3]
# plyr - works
ddply(data, columns, summarize, value=mean(value))
# dplyr - raises error
data %.%
  group_by(columns) %.%
  summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds
¿Qué me falta para traducir el ejemplo de plyr en una sintaxis dplyr-esque?
Edición 2017 : Dplyr se ha actualizado, por lo que hay disponible una solución más simple. Ver la respuesta seleccionada actualmente.

group_by_ahora explicado envignette("nse").dots. Aquí está la solución adaptada de la respuesta de @hadley a continuación:df %>% group_by_(.dots=list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %>% summarise(n = n())Respuestas:
Desde que se publicó esta pregunta, dplyr agregó versiones de alcance de
group_by( documentación aquí ). Esto le permite usar las mismas funciones que usaríaselect, así:El resultado de su pregunta de ejemplo es el esperado (consulte la comparación con plyr arriba y el resultado abajo):
Tenga en cuenta que dado que
dplyr::summarizesolo elimina una capa de agrupación a la vez, todavía tiene algo de agrupación en el tibble resultante (que en ocasiones puede atrapar a las personas por sorpresa más adelante en la línea). Si desea estar absolutamente a salvo del comportamiento de agrupación inesperado, siempre puede agregar%>% ungroupa su canalización después de resumir.fuente
0.7.0que el sistema de presupuesto entre comillas esté disponible también con varias columnas?.dotsargumentos quegroup_by()como tal:data %>% group_by(.dots = columns) %>% summarize(value = mean(value)).one_of()hacer algo aquí? Creo que es redundante en este contexto, ya que la expresión está envuelta en una llamada avars().one_of()es redundante en este contextoselectsintaxis, vea la nuevaacrossfunción: dplyr.tidyverse.org/reference/across.html En su caso, se vería algo asísummarize(across(all_of(c(''value_A", "value_B")), mean))Solo para escribir el código completo, aquí hay una actualización de la respuesta de Hadley con la nueva sintaxis:
salida:
fuente
asihckhdoydk...dots <- lapply(names(df)[-3], function(x) as.symbol(x))para crear el.dotsargumento.dots=fue el paso crucial. Si alguiengroup_bysabe bien por qué es necesario en la llamada, ¿puede editar esta respuesta? En este momento es un poco inescrutable.vignette("nse")indica que hay tres formas de citar que son aceptables: fórmula, cita y carácter. A menos que esté preocupado por el entorno del que saldrá, probablemente pueda salirse con la suyagroup_by_(.dots=grp_cols)El soporte para esto en dplyr es actualmente bastante débil, eventualmente creo que la sintaxis será algo así como:
Pero eso probablemente no estará allí por un tiempo (porque necesito pensar en todas las consecuencias).
Mientras tanto, puede usar
regroup(), que toma una lista de símbolos:Si tiene un vector de caracteres de nombres de columna, puede convertirlos a la estructura correcta con
lapply()yas.symbol():fuente
as.symbollo resuelve ¡Gracias! En caso de que ayude con el desarrollo: este escenario es muy común para mí. Agregue un resultado numérico sobre cada combinación de las otras variables.regrouptambién está en desuso (al menos a partir de la versión 0.4.3).La especificación de cadenas de columnas
dplyrahora se admite a través de variantes de lasdplyrfunciones con nombres que terminan en un guión bajo. Por ejemplo, correspondiente a lagroup_byfunción hay unagroup_by_función que puede tomar argumentos de cadena. Esta viñeta describe la sintaxis de estas funciones en detalle.El siguiente fragmento resuelve limpiamente el problema que originalmente planteó @sharoz (tenga en cuenta la necesidad de escribir el
.dotsargumento):(Tenga en cuenta que dplyr ahora usa el
%>%operador y%.%está en desuso).fuente
Hasta que dplyr tenga soporte completo para los argumentos de cadena, quizás esta esencia es útil:
https://gist.github.com/skranz/9681509
Contiene un montón de funciones de contenedor como s_group_by, s_mutate, s_filter, etc. que usan argumentos de cadena. Puede mezclarlos con las funciones normales de dplyr. Por ejemplo
fuente
Funciona si le pasas los objetos (bueno, no lo eres, pero ...) en lugar de hacerlo como un vector de caracteres:
donde
dffue tudata.?group_bydice:lo que interpreto no significa las versiones de los personajes de los nombres, sino cómo se referiría a ellos en
foo$bar;barNo se cita aquí. O cómo le gustaría referirse a variables en una fórmula:foo ~ bar.@Arun también menciona que puedes hacer:
Pero no puede pasar algo que no se haya evaluado no es el nombre de una variable en el objeto de datos.
Supongo que esto se debe a los métodos internos que Hadley está utilizando para buscar las cosas que pasa a través del
...argumento.fuente
fuente
Un caso (pequeño) que falta en las respuestas aquí, que quería hacer explícito, es cuando las variables para agrupar se generan dinámicamente a mitad de camino en una tubería:
Básicamente, esto muestra cómo usar
grepjunto congroup_by_(.dots = ...)para lograr esto.fuente
Ejemplo general sobre el uso del
.dotsargumento como entrada de vector de caracteres para ladplyr::group_byfunción:O sin un nombre codificado para la variable de agrupación (como lo solicitó el OP):
Con el ejemplo del OP:
Vea también la viñeta dplyr sobre programación que explica pronombres, cuasiquotación, quosures y tidyeval.
fuente