tablas studio filtros datos columna agrupar agregar r dplyr aggregate

studio - filtros en r



¿Resumiendo múltiples columnas con dplyr? (5)

El paquete dplyr contiene summarise_all para este objetivo:

df %>% group_by(grp) %>% summarise_all(funs(mean)) #> Source: local data frame [3 x 5] #> #> grp a b c d #> (int) (dbl) (dbl) (dbl) (dbl) #> 1 1 3.000000 2.666667 2.666667 3.333333 #> 2 2 2.666667 2.666667 2.500000 2.833333 #> 3 3 4.000000 1.000000 4.000000 3.000000

Si desea resumir solo ciertas columnas, use las funciones summarise_at o summarise_if .

Alternativamente, el paquete purrrlyr proporciona la misma funcionalidad:

df %>% slice_rows("grp") %>% dmap(mean) #> Source: local data frame [3 x 5] #> #> grp a b c d #> (int) (dbl) (dbl) (dbl) (dbl) #> 1 1 3.000000 2.666667 2.666667 3.333333 #> 2 2 2.666667 2.666667 2.500000 2.833333 #> 3 3 4.000000 1.000000 4.000000 3.000000

Además, no te olvides de data.table :

setDT(df)[, lapply(.SD, mean), by = grp] #> grp a b c d #> 1: 3 3.714286 3.714286 2.428571 2.428571 #> 2: 1 1.000000 4.000000 5.000000 2.000000 #> 3: 2 4.000000 4.500000 3.000000 3.000000

Tratemos de comparar el rendimiento.

library(dplyr) library(purrrlyr) library(data.table) library(benchr) n <- 10000 df <- data.frame( a = sample(1:5, n, replace = TRUE), b = sample(1:5, n, replace = TRUE), c = sample(1:5, n, replace = TRUE), d = sample(1:5, n, replace = TRUE), grp = sample(1:3, n, replace = TRUE) ) dt <- setDT(df) benchmark( dplyr = df %>% group_by(grp) %>% summarise_all(funs(mean)), purrrlyr = df %>% slice_rows("grp") %>% dmap(mean), data.table = dt[, lapply(.SD, mean), by = grp] ) #> Benchmark summary: #> Time units : microseconds #> expr n.eval min lw.qu median mean up.qu max total relative #> dplyr 100 3490 3550 3710 3890 3780 15100 389000 6.98 #> purrrlyr 100 2540 2590 2680 2920 2860 12000 292000 5.04 #> data.table 100 459 500 531 563 571 1380 56300 1.00

Estoy luchando un poco con la sintaxis dplyr. Tengo un marco de datos con diferentes variables y una variable de agrupación. Ahora quiero calcular la media de cada columna dentro de cada grupo, usando dplyr en R.

df <- data.frame( a = sample(1:5, n, replace = TRUE), b = sample(1:5, n, replace = TRUE), c = sample(1:5, n, replace = TRUE), d = sample(1:5, n, replace = TRUE), grp = sample(1:3, n, replace = TRUE) ) df %>% group_by(grp) %>% summarise(mean(a))

Esto me da el promedio para la columna "a" para cada grupo indicado por "grp".

Mi pregunta es: ¿es posible obtener los medios para cada columna dentro de cada grupo a la vez? ¿O tengo que repetir df %>% group_by(grp) %>% summarise(mean(a)) para cada columna?

Lo que me gustaría tener es algo así como

df %>% group_by(grp) %>% summarise(mean(a:d)) # "mean(a:d)" does not work


Para completar: con dplyr v0.2 ddply con colwise también hará esto:

> ddply(df, .(grp), colwise(mean)) grp a b c d 1 1 4.333333 4.00 1.000000 2.000000 2 2 2.000000 2.75 2.750000 2.750000 3 3 3.000000 4.00 4.333333 3.666667

pero es más lento, al menos en este caso:

> microbenchmark(ddply(df, .(grp), colwise(mean)), df %>% group_by(grp) %>% summarise_each(funs(mean))) Unit: milliseconds expr min lq mean ddply(df, .(grp), colwise(mean)) 3.278002 3.331744 3.533835 df %>% group_by(grp) %>% summarise_each(funs(mean)) 1.001789 1.031528 1.109337 median uq max neval 3.353633 3.378089 7.592209 100 1.121954 1.133428 2.292216 100


Podemos resumir usando summarize_at , summarize_all y summarize_if en dplyr 0.7.4 . Podemos establecer las múltiples columnas y funciones usando vars y funs argument como el código a continuación. El lado izquierdo de la fórmula funs se asigna al sufijo de vars resumidos. En dplyr 0.7.4 , summarise_each (y mutate_each ) ya está en desuso, por lo que no podemos usar estas funciones.

options(scipen = 100, dplyr.width = Inf, dplyr.print_max = Inf) library(dplyr) packageVersion("dplyr") # [1] ‘0.7.4’ set.seed(123) df <- data_frame( a = sample(1:5, 10, replace=T), b = sample(1:5, 10, replace=T), c = sample(1:5, 10, replace=T), d = sample(1:5, 10, replace=T), grp = as.character(sample(1:3, 10, replace=T)) # For convenience, specify character type ) df %>% group_by(grp) %>% summarise_each(.vars = letters[1:4], .funs = c(mean="mean")) # `summarise_each()` is deprecated. # Use `summarise_all()`, `summarise_at()` or `summarise_if()` instead. # To map `funs` over a selection of variables, use `summarise_at()` # Error: Strings must match column names. Unknown columns: mean

Deberías cambiar al siguiente código. Los siguientes códigos tienen el mismo resultado.

# summarise_at df %>% group_by(grp) %>% summarise_at(.vars = letters[1:4], .funs = c(mean="mean")) df %>% group_by(grp) %>% summarise_at(.vars = names(.)[1:4], .funs = c(mean="mean")) df %>% group_by(grp) %>% summarise_at(.vars = vars(a,b,c,d), .funs = c(mean="mean")) # summarise_all df %>% group_by(grp) %>% summarise_all(.funs = c(mean="mean")) # summarise_if df %>% group_by(grp) %>% summarise_if(.predicate = function(x) is.numeric(x), .funs = funs(mean="mean")) # A tibble: 3 x 5 # grp a_mean b_mean c_mean d_mean # <chr> <dbl> <dbl> <dbl> <dbl> # 1 1 2.80 3.00 3.6 3.00 # 2 2 4.25 2.75 4.0 3.75 # 3 3 3.00 5.00 1.0 2.00

También puedes tener múltiples funciones.

df %>% group_by(grp) %>% summarise_at(.vars = letters[1:2], .funs = c(Mean="mean", Sd="sd")) # A tibble: 3 x 5 # grp a_Mean b_Mean a_Sd b_Sd # <chr> <dbl> <dbl> <dbl> <dbl> # 1 1 2.80 3.00 1.4832397 1.870829 # 2 2 4.25 2.75 0.9574271 1.258306 # 3 3 3.00 5.00 NA NA


Simplemente puede pasar más argumentos para summarise :

df %>% group_by(grp) %>% summarise(mean(a), mean(b), mean(c), mean(d))

Fuente: marco de datos local [3 x 5]

grp mean(a) mean(b) mean(c) mean(d) 1 1 2.500000 3.500000 2.000000 3.0 2 2 3.800000 3.200000 3.200000 2.8 3 3 3.666667 3.333333 2.333333 3.0


Todos los ejemplos son geniales, pero creo que agregaría uno más para mostrar cómo trabajar en un formato "ordenado" simplifica las cosas. En este momento, el marco de datos está en formato "ancho", lo que significa que las variables "a" a "d" están representadas en columnas. Para llegar a un formato "ordenado" (o largo), puede usar gather() del paquete tidyr que cambia las variables de las columnas "a" a "d" en filas. Luego usa las group_by() y summarize() para obtener la media de cada grupo. Si desea presentar los datos en un formato amplio, simplemente agregue una llamada adicional a la función spread() .


library(tidyverse) # Create reproducible df set.seed(101) df <- tibble(a = sample(1:5, 10, replace=T), b = sample(1:5, 10, replace=T), c = sample(1:5, 10, replace=T), d = sample(1:5, 10, replace=T), grp = sample(1:3, 10, replace=T)) # Convert to tidy format using gather df %>% gather(key = variable, value = value, a:d) %>% group_by(grp, variable) %>% summarize(mean = mean(value)) %>% spread(variable, mean) #> Source: local data frame [3 x 5] #> Groups: grp [3] #> #> grp a b c d #> * <int> <dbl> <dbl> <dbl> <dbl> #> 1 1 3.000000 3.5 3.250000 3.250000 #> 2 2 1.666667 4.0 4.666667 2.666667 #> 3 3 3.333333 3.0 2.333333 2.333333