Tengo el siguiente marco de datos
x <- read.table(text = "  id1 id2 val1 val2
1   a   x    1    9
2   a   x    2    4
3   a   y    3    5
4   a   y    4    9
5   b   x    1    7
6   b   y    4    4
7   b   x    3    9
8   b   y    2    8", header = TRUE)Quiero calcular la media de val1 y val2 agrupados por id1 e id2, y simultáneamente contar el número de filas para cada combinación id1-id2. Puedo realizar cada cálculo por separado:
# calculate mean
aggregate(. ~ id1 + id2, data = x, FUN = mean)
# count rows
aggregate(. ~ id1 + id2, data = x, FUN = length)Para hacer ambos cálculos en una llamada, intenté
do.call("rbind", aggregate(. ~ id1 + id2, data = x, FUN = function(x) data.frame(m = mean(x), n = length(x))))Sin embargo, obtengo una salida confusa junto con una advertencia:
#     m   n
# id1 1   2
# id2 1   1
#     1.5 2
#     2   2
#     3.5 2
#     3   2
#     6.5 2
#     8   2
#     7   2
#     6   2
# Warning message:
#   In rbind(id1 = c(1L, 2L, 1L, 2L), id2 = c(1L, 1L, 2L, 2L), val1 = list( :
#   number of columns of result is not a multiple of vector length (arg 1)Podría usar el paquete plyr, pero mi conjunto de datos es bastante grande y plyr es muy lento (casi inutilizable) cuando aumenta el tamaño del conjunto de datos.
¿Cómo puedo usar aggregateu otras funciones para realizar varios cálculos en una llamada?

aggregatemencionado en las respuestas, también haybyytapply.Respuestas:
Puede hacerlo todo en un solo paso y obtener el etiquetado adecuado:
Esto crea un marco de datos con dos columnas de identificación y dos columnas de matriz:
Como lo señala @ lord.garbage a continuación, esto se puede convertir en un marco de datos con columnas "simples" usando
do.call(data.frame, ...)Esta es la sintaxis para múltiples variables en el LHS:
fuente
d$val1[ , ""mn"]mirar la estructura constr.agg <- aggregate(cbind(val1, val2) ~ id1 + id2, data = x, FUN = function(x) c(mn = mean(x), n = length(x)))usandoagg_df <- do.call(data.frame, agg). Consulte también aquí .Dado esto en la pregunta:
Luego, en
data.table(1.9.4+) podrías intentar:Para comparar tiempos
aggregate(usado en la pregunta y las otras 3 respuestas) paradata.tablever este punto de referencia (los casosaggyagg.x).fuente
Puede agregar una
countcolumna, agregarlasumy luego reducirla para obtenermean:Tiene la ventaja de conservar los nombres de sus columnas y crear una sola
countcolumna.fuente
Usando el
dplyrpaquete, podría lograr esto usandosummarise_all. Con esta función de resumen puede aplicar otras funciones (en este casomeanyn()) a cada una de las columnas que no se agrupan:lo que da:
Si no desea aplicar la (s) función (es) a todas las columnas que no se agrupan, especifique las columnas a las que deben aplicarse o excluyendo las no deseadas con un signo menos usando la
summarise_at()función:fuente
¿Quizás quieras fusionarte ?
fuente
También puede utilizar
plyr::each()para introducir varias funciones:fuente
Otra
dplyropción esacrosscuál es parte de la versión de desarrollo actual.Resultado
fuente