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::summarize
solo 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%>% ungroup
a su canalización después de resumir.fuente
0.7.0
que el sistema de presupuesto entre comillas esté disponible también con varias columnas?.dots
argumentos 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 contextoselect
sintaxis, vea la nuevaacross
funció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.dots
argumento.dots=
fue el paso crucial. Si alguiengroup_by
sabe 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.symbol
lo 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.regroup
también está en desuso (al menos a partir de la versión 0.4.3).La especificación de cadenas de columnas
dplyr
ahora se admite a través de variantes de lasdplyr
funciones con nombres que terminan en un guión bajo. Por ejemplo, correspondiente a lagroup_by
funció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
.dots
argumento):(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
df
fue tudata
.?group_by
dice:lo que interpreto no significa las versiones de los personajes de los nombres, sino cómo se referiría a ellos en
foo$bar
;bar
No 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
grep
junto congroup_by_(.dots = ...)
para lograr esto.fuente
Ejemplo general sobre el uso del
.dots
argumento como entrada de vector de caracteres para ladplyr::group_by
funció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