Ejemplo de función agregada de R: summarise() y group_by()

⚡ Resumen inteligente

La función de agregación en R con dplyr combina varias filas en una sola estadística por grupo. Este tutorial combina group_by() con summarise() en los datos de bateo de Lahman para calcular medias, sumas, rangos, recuentos y valores posicionales en 104 324 observaciones.

  • 🧮 Verbo principal: summarise(df, name = function(column)) devuelve una fila, y group_by() primero la convierte en una fila por grupo.
  • 📊 Familias estadísticas: La media y la mediana describen el centro, la desviación estándar y el rango intercuartílico describen la dispersión, y el mínimo y el máximo describen el rango.
  • 🔢 Contando: n() cuenta las filas en el grupo actual y n_distinct() cuenta los valores únicos dentro del mismo.
  • 📍 Ayudantes posicionales: first(), last() y nth() extracuna observación específica de cada grupo.
  • 🔄 Trabajo en varias columnas: La función across() aplica una función a varias columnas sin repetir el código para cada una.
  • 🔓 Grouping del endoscopio: Siempre llame a ungroup() antes de un cálculo que deba ejecutarse nuevamente en toda la tabla.

Función agregada de R

Conjunto de datos utilizado en este tutorial

Resumir una variable proporciona una primera impresión de los datos, mientras que resumirlos por grupo ofrece mucha más información sobre cómo se distribuyen los valores. Este tutorial muestra cómo agregar un conjunto de datos por grupo con la biblioteca dplyr.

Este tutorial utiliza el conjunto de datos de bateo de Lahman. Después de importarlo y mantenerloping Con solo las nueve columnas que se enumeran a continuación, el marco de datos de trabajo contiene 104,324 observaciones y 9 variables:

  • playerID: código de identificación del jugador. Factor
  • IDaño: Año. Factor
  • ID de equipo: Equipo. factor
  • lgID: Liga. Factor: AA AL FL NL PL UA
  • AB: Al bate. Numérico
  • G: Juegos: número de juegos de un jugador. Numérico
  • R: Corre. Numérico
  • HR: Jonrones. Numérico
  • SH: Golpes de sacrificio. Numérico

Antes de realizar el resumen, deberá realizar los siguientes pasos para preparar los datos:

  • Paso 1: importar los datos
  • Paso 2: seleccione las variables relevantes
  • Paso 3: ordenar los datos
library(dplyr)

# Step 1
data <- read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/lahman-batting.csv") %>%

# Step 2
select(c(playerID, yearID, AB, teamID, lgID, G, R, HR, SH))  %>% 

# Step 3
arrange(playerID, teamID, yearID)

Una buena práctica al importar un conjunto de datos es utilizar la función glimpse() para tener una idea sobre la estructura del conjunto de datos.

# Structure of the data
glimpse(data)

Salida:

Observations: 104,324
Variables: 9
$ playerID <fctr> aardsda01, aardsda01, aardsda01, aardsda01, aardsda01, a...
$ yearID   <int> 2015, 2008, 2007, 2006, 2012, 2013, 2009, 2010, 2004, 196...
$ AB       <int> 1, 1, 0, 2, 0, 0, 0, 0, 0, 603, 600, 606, 547, 516, 495, ...
$ teamID   <fctr> ATL, BOS, CHA, CHN, NYA, NYN, SEA, SEA, SFN, ATL, ATL, A...
$ lgID     <fctr> NL, AL, AL, NL, AL, NL, AL, AL, NL, NL, NL, NL, NL, NL, ...
$ G        <int> 33, 47, 25, 45, 1, 43, 73, 53, 11, 158, 155, 160, 147, 15...
$ R        <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 113, 84, 100, 103, 95, 75...
$ HR       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 39, 29, 44, 38, 47, 34, 40...
$ SH       <int> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, ...

resumir()

La sintaxis de summarise() es básica y coherente con los demás verbos incluidos en la biblioteca dplyr.

summarise(df, variable_name=condition) 
arguments: 
- `df`: Dataset used to construct the summary statistics 
- `variable_name=condition`: Formula to create the new variable

Mira el código a continuación:

summarise(data, mean_run =mean(R))

Code Explicación

  • resumen (datos, media_ejecución = media (R)): crea una variable llamada media_ejecución que es el promedio de la columna ejecutada a partir de los datos del conjunto de datos.

Salida:

##   mean_run
## 1 19.20114

Puedes agregar tantas variables como quieras. Devuelves el promedio de juegos jugados y el promedio de hits de sacrificio.

summarise(data, mean_games = mean(G),
    mean_SH = mean(SH, na.rm = TRUE))

Code Explicación

  • mean_SH = mean(SH, na.rm = TRUE): resume una segunda variable. Estableciste na.rm = TRUE porque la columna SH contiene observaciones faltantes.

Salida:

##   mean_games  mean_SH
## 1   51.98361 2.340085

group_by() vs Sin group_by()

Utilizada sola, summarise() colapsa todo el marco de datos en una sola fila, como muestran los ejemplos anteriores. Su verdadero poder aparece una vez que se agrega group_by(): dplyr La biblioteca aplica entonces el mismo cálculo por separado a cada grupo y devuelve una fila por grupo.

Tenga en cuenta que group_by funciona perfectamente con todos los demás verbos (es decir, mutar(), filtrar(), organizar(),…).

Es conveniente utilizar el operador de tubería cuando se tiene más de un paso. Puedes calcular el jonrón promedio por liga de béisbol.

data %>%
	group_by(lgID) %>%
	summarise(mean_run = mean(HR))

Code Explicación

  • datos: conjunto de datos utilizado para construir las estadísticas de resumen
  • group_by(lgID): Divide los datos por los valores de lgID antes de resumirlos.
  • resumir (mean_run = mean (HR)): Calcula el jonrón promedio

Salida:

## 
# A tibble: 7 x 2
##     lgID  mean_run
##   <fctr>     <dbl>
## 1     AA 0.9166667
## 2     AL 3.1270988
## 3     FL 1.3131313
## 4     NL 2.8595953
## 5     PL 2.5789474
## 6     UA 0.6216216
## 7   <NA> 0.2867133	

La tubería también funciona con ggplot(), por lo que todo el proceso, desde los datos brutos hasta el gráfico final, se realiza en una sola instrucción. El código siguiente combina group_by(), summarise() y ggplot() para mostrar el promedio de jonrones por liga en un gráfico de barras.

Realizarás el siguiente paso:

  • Paso 1: seleccione el marco de datos
  • Paso 2: datos del grupo
  • Paso 3: resumir los datos
  • Paso 4: Trazar las estadísticas resumidas
library(ggplot2)
# Step 1
data %>% 
#Step 2
group_by(lgID) %>% 
#Step 3
summarise(mean_home_run = mean(HR)) %>% 
#Step 4
ggplot(aes(x = lgID, y = mean_home_run, fill = lgID)) +
    geom_bar(stat = "identity") +
    theme_classic() +
    labs(
        x = "baseball league",
        y = "Average home run",
        title = paste(
            "Example group_by() with summarise()"
        )
    )

Salida:

Ejemplo de Group_by con resumen

Funciones que puedes usar dentro de summarise()

El verbo resumir() es compatible con casi todas las funciones en R. Aquí hay una breve lista de funciones útiles que puedes usar junto con resumir():

Objetivo Función Mareas Ideales para Lecciones
Básico media() Promedio del vector x
mediana() Mediana del vector x
sum () Suma del vector x
variación Dakota del Sur() desviación estándar del vector x
RIQ() Intercuartil del vector x
Autonomía min () Mínimo del vector x
max () Máximo del vector x
cuantil() Cuantil del vector x
Posición primero() Usar con group_by() Primera observación del grupo
último() Úselo con group_by(). Última observación del grupo.
enésimo() Úselo con group_by(). enésima observación del grupo
Contar norte() Úselo con group_by(). Cuente el número de filas
n_distinto() Úselo con group_by(). Cuente el número de observaciones distintas.

Las secciones siguientes muestran un ejemplo para cada función de la tabla anterior. Si no está familiarizado con el pipe y los demás verbos, comience con el Tutorial para seleccionar, filtrar y organizar.

Función básica

En el ejemplo anterior, no almacenó la estadística resumida en un marco de datos.

Puedes generar un marco de datos a partir de un resumen en dos pasos:

  • Paso 1: almacene el marco de datos para su uso posterior
  • Paso 2: use el conjunto de datos para crear un diagrama de líneas

Paso 1) Calcula el número promedio de juegos jugados por año.

## Mean
ex1 <- data %>%
	group_by(yearID) %>%
	summarise(mean_game_year = mean(G))
head(ex1)

Code Explicación

  • La estadística resumida del conjunto de datos de bateo se almacena en el marco de datos ex1.

Salida:

## # A tibble: 6 x 2
##   yearID mean_game_year
##    <int>          <dbl>
## 1   1871       23.42308
## 2   1872       18.37931
## 3   1873       25.61538
## 4   1874       39.05263
## 5   1875       28.39535
## 6   1876       35.90625	

Paso 2) Muestra la estadística resumida con un gráfico de líneas y ve la tendencia.

# Plot the graph
ggplot(ex1, aes(x = yearID, y = mean_game_year)) +
    geom_line() +
    theme_classic() +
    labs(
        x = "Year",
        y = "Average games played",
        title = paste(
            "Average games played from 1871 to 2016"
        )
    )

Salida:

Ejemplo de función básica

Subconjunto

La función resumen() es compatible con el subconjunto.

## Subsetting + Median
data %>%
group_by(lgID) %>%
summarise(median_at_bat_league = median(AB), 
	#Compute the median without the zero 
	median_at_bat_league_no_zero = median(AB[AB > 0]))

Code Explicación

  • median_at_bat_league_no_zero = mediana(AB[AB > 0]): La variable AB contiene muchos 0. Puedes comparar la mediana de la al bate variable con y sin 0.

Salida:

## # A tibble: 7 x 3
##     lgID median_at_bat_league median_at_bat_league_no_zero
##   <fctr>                <dbl>                        <dbl>
## 1     AA                  130                          131
## 2     AL                   38                           85
## 3     FL                   88                           97
## 4     NL                   56                           67
## 5     PL                  238                          238
## 6     UA                   35                           35
## 7   <NA>                  101                          101	

Suma

Otra función útil para agregar la variable es sum().

Puedes comprobar qué ligas tienen más jonrones.

## Sum
data %>%
	group_by(lgID) %>%
	summarise(sum_homerun_league = sum(HR))

Salida:

## # A tibble: 7 x 2
##     lgID sum_homerun_league
##   <fctr>              <int>
## 1     AA                341
## 2     AL              29426
## 3     FL                130
## 4     NL              29817
## 5     PL                 98
## 6     UA                 46
## 7   <NA>                 41	

Desviación estándar

La dispersión de los datos se calcula con la desviación estándar o sd() en R.

# Spread
data %>%
	group_by(teamID) %>%
	summarise(sd_at_bat_league = sd(HR))

Salida:

## # A tibble: 148 x 2
##    teamID sd_at_bat_league
##    <fctr>            <dbl>
##  1    ALT               NA
##  2    ANA        8.7816395
##  3    ARI        6.0765503
##  4    ATL        8.5363863
##  5    BAL        7.7350173
##  6    BFN        1.3645163
##  7    BFP        0.4472136
##  8    BL1        0.6992059
##  9    BL2        1.7106757
## 10    BL3        1.0000000
## # ... with 138 more rows		

La diferencia en los jonrones varía mucho entre los equipos, y ALT devuelve NA porque ese equipo solo tiene una fila, por lo que no se puede calcular la desviación estándar.

Gramaje mínimo y máximo

Puedes acceder al mínimo y máximo de un vector con las funciones min() y max().

El siguiente código devuelve el número más bajo y más alto de juegos en una temporada jugados por un jugador.

# Min and max
data %>%
	group_by(playerID) %>%
	summarise(min_G = min(G),
    max_G = max(G))

Salida:

## # A tibble: 10,395 x 3
##     playerID min_G max_G
##       <fctr>       <int>
##  1 aardsda01    53    73
##  2 aaronha01   120   156
##  3  aasedo01    24    66
##  4  abadfe01    18    18
##  5 abadijo01    11    11
##  6 abbated01     3   153
##  7 abbeybe01    11    11
##  8 abbeych01    80   132
##  9 abbotgl01     5    23
## 10 abbotji01    13    29
## # ... with 10,385 more rows

Contar

Siempre vale la pena contar las observaciones por grupo. En R, n() devuelve el número de filas en el grupo actual.

Por ejemplo, el siguiente código calcula el número de años jugados por cada jugador.

# count observations
data %>%
	group_by(playerID) %>%
	summarise(number_year = n()) %>%
	arrange(desc(number_year))

Salida:

## # A tibble: 10,395 x 2
##     playerID number_year
##       <fctr>       <int>
##  1 pennohe01          11
##  2 joosted01          10
##  3 mcguide01          10
##  4  rosepe01          10
##  5 davisha01           9
##  6 johnssi01           9
##  7  kaatji01           9
##  8 keelewi01           9
##  9 marshmi01           9
## 10 quirkja01           9
## # ... with 10,385 more rows

Primero y último

Puede seleccionar la primera, última o enésima posición de un grupo.

Por ejemplo, puedes encontrar el primer y último año de cada jugador.

# first and last
data %>%
	group_by(playerID) %>%
	summarise(first_appearance = first(yearID),
		last_appearance = last(yearID))

Salida:

## # A tibble: 10,395 x 3
##     playerID first_appearance last_appearance
##       <fctr>            <int>           <int>
##  1 aardsda01             2009            2010
##  2 aaronha01             1973            1975
##  3  aasedo01             1986            1990
##  4  abadfe01             2016            2016
##  5 abadijo01             1875            1875
##  6 abbated01             1905            1897
##  7 abbeybe01             1894            1894
##  8 abbeych01             1895            1897
##  9 abbotgl01             1973            1979
## 10 abbotji01             1992            1996
## # ... with 10,385 more rows

enésima observación

La función nth() complementa a first() y last(). Devuelve la observación en el índice que se le pase dentro de cada grupo.

Por ejemplo, puedes filtrar solo el segundo año que jugó un equipo.

# nth
data %>%
	group_by(teamID) %>%
	summarise(second_game = nth(yearID, 2)) %>%
	arrange(second_game)

Salida:

## # A tibble: 148 x 2
##    teamID second_game
##    <fctr>       <int>
##  1    BS1        1871
##  2    CH1        1871
##  3    FW1        1871
##  4    NY2        1871
##  5    RC1        1871
##  6    BR1        1872
##  7    BR2        1872
##  8    CL1        1872
##  9    MID        1872
## 10    TRO        1872
## # ... with 138 more rows

Número distinto de observaciones

n() devuelve el número de filas en el grupo actual. La función relacionada n_distinct() cuenta los valores únicos.

En el siguiente ejemplo, sumas el total de jugadores que un equipo reclutó durante todos los períodos.

# distinct values
data %>%
	group_by(teamID) %>%
	summarise(number_player = n_distinct(playerID)) %>%
	arrange(desc(number_player))

Code Explicación

  • group_by(teamID): Agrupar por equipo
  • resumir(número_jugador = n_distinto(playerID): Cuenta los jugadores distintos por equipo.
  • organizar (desc (número_jugador)): Ordena los datos por el número de jugador

Salida:

## # A tibble: 148 x 2
##    teamID number_player
##    <fctr>         <int>
##  1    CHN           751
##  2    SLN           729
##  3    PHI           699
##  4    PIT           683
##  5    CIN           679
##  6    BOS           647
##  7    CLE           646
##  8    CHA           636
##  9    DET           623
## 10    NYA           612
## # ... with 138 more rows

Múltiples grupos

Se puede realizar una estadística resumida entre varios grupos.

# Multiple groups
data %>%
	group_by(yearID, teamID) %>%
	summarise(mean_games = mean(G)) %>%
	arrange(desc(teamID, yearID))

Code Explicación

  • group_by(yearID, teamID): Grupo por año y equipo
  • resumir(media_juegos = media(G)): Calcula el promedio del número de juegos jugados
  • organizar (desc (teamID, añoID)): Ordena los datos por equipo y año

Salida:

## # A tibble: 2,829 x 3
## # Groups:   yearID [146]
##    yearID teamID mean_games
##     <int> <fctr>      <dbl>
##  1   1884    WSU   20.41667
##  2   1891    WS9   46.33333
##  3   1886    WS8   22.00000
##  4   1887    WS8   51.00000
##  5   1888    WS8   27.00000
##  6   1889    WS8   52.42857
##  7   1884    WS7    8.00000
##  8   1875    WS6   14.80000
##  9   1873    WS5   16.62500
## 10   1872    WS4    4.20000
## # ... with 2,819 more rows

Filtrar

Antes de intentar realizar una operación, puede filtrar el conjunto de datos. El conjunto de datos comienza en 1871 y el análisis no necesita los años anteriores a 1980.

# Filter
data %>%
	filter(yearID > 1980) %>%
	group_by(yearID) %>%
	summarise(mean_game_year = mean(G))

Code Explicación

  • filter(yearID > 1980): filtra los datos para mostrar solo los años relevantes (es decir, después de 1980)
  • group_by(yearID): Grupo por año
  • resumir (mean_game_year = media (G)): resume los datos

Salida:

## # A tibble: 36 x 2
##    yearID mean_game_year
##     <int>          <dbl>
##  1   1981       40.64583
##  2   1982       56.97790
##  3   1983       60.25128
##  4   1984       62.97436
##  5   1985       57.82828
##  6   1986       58.55340
##  7   1987       48.74752
##  8   1988       52.57282
##  9   1989       58.16425
## 10   1990       52.91556
## # ... with 26 more rows

Desagrupar

Finalmente, debes eliminar el suelo.ping antes de cambiar el nivel en el que se ejecuta un cálculo. Sin ungroup(), el segundo summarise() seguiría operando por jugador.

# Ungroup the data
data %>%
	filter(HR > 0) %>%
	group_by(playerID) %>%
	summarise(average_HR_game = sum(HR) / sum(G)) %>%
	ungroup() %>%
	summarise(total_average_homerun = mean(average_HR_game))

Code Explicación

  • filtro (HR >0): excluye el jonrón cero
  • group_by(playerID): grupo por jugador
  • resumir (average_HR_game = suma (HR)/suma (G)): Calcula el jonrón promedio por jugador
  • ungroup(): elimina el grupoping
  • resumir (total_average_homerun = mean (average_HR_game)): resume los datos

Salida:

## # A tibble: 1 x 1
##   total_average_homerun
##                   <dbl>
## 1            0.06882226	

Cómo resumir varias columnas con across()

En cada ejemplo anterior se nombra una columna a la vez. Cuando se necesita la misma estadística para varias columnas, la función across() la aplica a todas ellas en una sola llamada.

# One function, several columns
data %>%
    group_by(lgID) %>%
    summarise(across(c(R, HR, G), mean, .names = "mean_{.col}"))

# Every numeric column at once
data %>%
    group_by(lgID) %>%
    summarise(across(where(is.numeric), mean, na.rm = TRUE))

# Several functions applied to several columns
data %>%
    group_by(teamID) %>%
    summarise(across(c(R, HR), list(avg = mean, total = sum)))

Tres argumentos controlan el comportamiento:

  • .cols: las columnas sobre las que actuar, escritas con las mismas funciones auxiliares que select(), incluyendo where(is.numeric).
  • .fns: una función, o una lista con nombre de funciones para aplicar a cada columna.
  • .nombres: el patrón de nomenclatura para la salida, donde {.col} es la columna y {.fn} el nombre de la función.

La función across() reemplazó a las funciones auxiliares summarise_all(), summarise_at() y summarise_if() anteriores en dplyr 1.0.0. Estas aún se ejecutan, pero han sido reemplazadas, por lo que el código nuevo debería usar across().

Errores comunes en la función summarise() y cómo solucionarlos.

La mayoría de las agregaciones fallidas se deben a cuatro problemas.

  • El resultado es NA. Las funciones mean() y sum() devuelven NA si falta algún valor. Añade na.rm = TRUE, como se muestra en el ejemplo mean_SH anterior.
  • El mensaje “summarise() tiene una salida agrupada”. Grouping por dos variables deja el resultado agrupado por la primera. Pasa .groups = “drop” para eliminar el grupo.pingo bien, llama a ungroup() después.
  • Un cálculo posterior arroja un nivel erróneo. Un marco de datos permanece agrupado hasta que se desagrupa, por lo que se ejecuta una segunda función summarise() por cada grupo. Esto es precisamente lo que demuestra el ejemplo de ungroup().
  • El resultado tiene más filas de las esperadas. summarise() devuelve una fila por grupo, por lo que un grupo no deseadoping La variable multiplica la salida. Compruebe la línea “Groups:” que aparece encima de cualquier tibble.
# Drop the grouping as part of the call
data %>%
    group_by(yearID, teamID) %>%
    summarise(mean_games = mean(G), .groups = "drop")

resumir() en R: Referencia de la función

Para obtener un resumen por grupo, primero divida los datos:

# group by X1, X2, X3
group_by(df, X1, X2, X3)

y quitar el sueloping cuando el cálculo cambia de nivel:

ungroup(df)

La siguiente tabla enumera todas las funciones utilizadas con summarise() en este tutorial:

Método Función Code
mean mean
summarise(df, mean_x1 = mean(x1))
media media
summarise(df, median_x1 = median(x1))
suma suma
summarise(df, sum_x1 = sum(x1))
desviación estándar sd
summarise(df, sd_x1 = sd(x1))
intercuartil RIC
summarise(df, interquartile_x1 = IQR(x1))
mínimo min
summarise(df, minimum_x1 = min(x1))
máximas max
summarise(df, maximum_x1 = max(x1))
cuantil cuantil
summarise(df, quantile_x1 = quantile(x1, probs = 0.75))
primera observación first
summarise(df, first_x1 = first(x1))
última observación pasado
summarise(df, last_x1 = last(x1))
enésima observación nth
summarise(df, nth_x1 = nth(x1, 2))
número de ocurrencia n
summarise(df, n_x1 = n())
número de ocurrencias distintas n_distinto
summarise(df, n_distinct_x1 = n_distinct(x1))

Preguntas Frecuentes

La función `summarise()` agrupa cada grupo en una sola fila de estadísticas. La función `mutate()` conserva todas las filas y añade una nueva columna. Utilice `mutate()` cuando la estadística del grupo deba aparecer junto a las observaciones originales.

Grouping Si se utilizan dos o más variables, el resultado se agrupa por todas excepto la última. dplyr advierte que los verbos posteriores se ejecutarían silenciosamente por grupo. Para evitarlo, utilice `.groups = “drop”`.

La función n() cuenta todas las filas del grupo actual, incluyendo las repetidas. La función n_distinct() cuenta los valores únicos de una columna. Para contar los jugadores por equipo se necesita n_distinct(), ya que un mismo jugador aparece en varias temporadas.

Los agregados a nivel de grupo, como los promedios, recuentos y valores de antigüedad de los clientes, se encuentran entre los predictores más sólidos en los modelos de IA tabulares. La función group_by() con summarise() es la forma estándar de construirlos de manera reproducible.

Sí. Los asistentes de IA pueden reescribir aggregate() y tapply() como pipelines group_by() y summarise(). Compara el número de filas en ambas versiones, ya que R base y dplyr manejan los grupos faltantes de manera diferente.

Resumir este post con: