6.5 dplyr::group_by()

Un funcionalidad muy importante es el uso de datos agrupados. Dichos grupos serán subconjuntos de datos que compartan una característica en común. Esto tiene muchas ventajas ya que se pueden obtener funciones resumen con una mayor fluidez y aplicaciones de funciones por bloques en lugar de observaciones individuales. La función para otorgar esta propiedad es dplyr::group_by() en donde sus parámetros indican que variables servirán para crear los grupos de acuerdo a los diferentes valores de esas variables.

Por ejemplo, véase que es natural pensar que en los datos de la población ya vistos se tomen resúmenes por la variable Rango_edad.

Population_FEntity %>% group_by(Rango_edad)
# A tibble: 448 x 4
# Groups:   Rango_edad [14]
   `Entidad Federativa` `Población Total` Rango_edad Población
   <chr>                            <dbl> <chr>          <dbl>
 1 Aguascalientes                 1066233 0 a 4        109853 
 2 Baja California                2856361 0 a 4        268842 
 3 Baja California Sur             512030 0 a 4         46070 
 4 Campeche                        755703 0 a 4         63034.
 5 Coahuila                       2501413 0 a 4        244624.
 6 Colima                          568642 0 a 4         45985 
 7 Chiapas                        4293414 0 a 4        491525 
 8 Chihuahua                      3241513 0 a 4        253834.
 9 Distrito Federal               8737172 0 a 4        682914.
10 Durango                        1509025 0 a 4        150485 
# … with 438 more rows

A simple vista no se ve algún cambio, pero internamente ya se tiene más estructura a dicha base de datos, ahora existe un atributo llamado “groups”.

str(Population_FEntity %>% group_by(Rango_edad))
tibble [448 × 4] (S3: grouped_df/tbl_df/tbl/data.frame)
 $ Entidad Federativa: chr [1:448] "Aguascalientes" "Baja California" "Baja California Sur" "Campeche" ...
 $ Población Total   : num [1:448] 1066233 2856361 512030 755703 2501413 ...
 $ Rango_edad        : chr [1:448] "0 a 4" "0 a 4" "0 a 4" "0 a 4" ...
 $ Población         : num [1:448] 109853 268842 46070 63034 244624 ...
 - attr(*, "groups")= tibble [14 × 2] (S3: tbl_df/tbl/data.frame)
  ..$ Rango_edad: chr [1:14] "0 a 4" "10 a 14" "15 a 19" "20 a 24" ...
  ..$ .rows     : list<int> [1:14] 
  .. ..$ : int [1:32] 1 2 3 4 5 6 7 8 9 10 ...
  .. ..$ : int [1:32] 65 66 67 68 69 70 71 72 73 74 ...
  .. ..$ : int [1:32] 97 98 99 100 101 102 103 104 105 106 ...
  .. ..$ : int [1:32] 129 130 131 132 133 134 135 136 137 138 ...
  .. ..$ : int [1:32] 161 162 163 164 165 166 167 168 169 170 ...
  .. ..$ : int [1:32] 193 194 195 196 197 198 199 200 201 202 ...
  .. ..$ : int [1:32] 225 226 227 228 229 230 231 232 233 234 ...
  .. ..$ : int [1:32] 257 258 259 260 261 262 263 264 265 266 ...
  .. ..$ : int [1:32] 289 290 291 292 293 294 295 296 297 298 ...
  .. ..$ : int [1:32] 33 34 35 36 37 38 39 40 41 42 ...
  .. ..$ : int [1:32] 321 322 323 324 325 326 327 328 329 330 ...
  .. ..$ : int [1:32] 353 354 355 356 357 358 359 360 361 362 ...
  .. ..$ : int [1:32] 385 386 387 388 389 390 391 392 393 394 ...
  .. ..$ : int [1:32] 417 418 419 420 421 422 423 424 425 426 ...
  .. ..@ ptype: int(0) 
  ..- attr(*, ".drop")= logi TRUE

Entonces, al aplicar funciones con mutate, estas se harán por grupos.

Population_FEntity %>% 
  group_by(Rango_edad) %>% 
  mutate("Población Mínima" = min(Población), "Población Máxima" = max(Población))
# A tibble: 448 x 6
# Groups:   Rango_edad [14]
   `Entidad Federa… `Población Tota… Rango_edad Población `Población Míni…
   <chr>                       <dbl> <chr>          <dbl>            <dbl>
 1 Aguascalientes            1066233 0 a 4        109853             45985
 2 Baja California           2856361 0 a 4        268842             45985
 3 Baja California…           512030 0 a 4         46070             45985
 4 Campeche                   755703 0 a 4         63034.            45985
 5 Coahuila                  2501413 0 a 4        244624.            45985
 6 Colima                     568642 0 a 4         45985             45985
 7 Chiapas                   4293414 0 a 4        491525             45985
 8 Chihuahua                 3241513 0 a 4        253834.            45985
 9 Distrito Federal          8737172 0 a 4        682914.            45985
10 Durango                   1509025 0 a 4        150485             45985
# … with 438 more rows, and 1 more variable: `Población Máxima` <dbl>

Igual se puede agrupar por distintas variables

Population_FEntity %>% 
  mutate(division = rep(c(rep(1,16),rep(2,16)), 14)) %>% 
  group_by(Rango_edad, division) %>% 
  mutate(index = row_number()) %>% 
  select(`Entidad Federativa`, Rango_edad, division, index)
# A tibble: 448 x 4
# Groups:   Rango_edad, division [28]
   `Entidad Federativa` Rango_edad division index
   <chr>                <chr>         <dbl> <int>
 1 Aguascalientes       0 a 4             1     1
 2 Baja California      0 a 4             1     2
 3 Baja California Sur  0 a 4             1     3
 4 Campeche             0 a 4             1     4
 5 Coahuila             0 a 4             1     5
 6 Colima               0 a 4             1     6
 7 Chiapas              0 a 4             1     7
 8 Chihuahua            0 a 4             1     8
 9 Distrito Federal     0 a 4             1     9
10 Durango              0 a 4             1    10
# … with 438 more rows

Algo interesante que se puede hacer con datos agrupados es el uso de funciones para resumir información, tales como dplyr::first(), dplyr::min(), dplyr::n(), dplyr::n_distinct() y dplyr::mean(); estas funciones también se pueden usar sin datos agrupados. Véase los siguientes ejemplos

Population_FEntity %>% 
  group_by(Rango_edad) %>% 
  summarise(min(Población))
# A tibble: 14 x 2
   Rango_edad `min(Población)`
   <chr>                 <dbl>
 1 0 a 4                45985 
 2 10 a 14              51549 
 3 15 a 19              55391 
 4 20 a 24              44808 
 5 25 a 29              37723 
 6 30 a 34              35922.
 7 35 a 39              41890 
 8 40 a 44              37496.
 9 45 a 49              30294 
10 5 a 9                43193.
11 50 a 54              22129.
12 55 a 59              23534 
13 60 y más             34364 
14 NE                       0 
Population_FEntity %>% 
  group_by(Rango_edad) %>% 
  summarise(last(Población))
# A tibble: 14 x 2
   Rango_edad `last(Población)`
   <chr>                  <dbl>
 1 0 a 4                127635.
 2 10 a 14              165710 
 3 15 a 19              143317 
 4 20 a 24              108938 
 5 25 a 29               94536.
 6 30 a 34               97108 
 7 35 a 39               92482.
 8 40 a 44               85895 
 9 45 a 49               72674 
10 5 a 9                152801 
11 50 a 54               49238 
12 55 a 59               53257 
13 60 y más             123730 
14 NE                     1067.
Population_FEntity %>% 
  group_by(Rango_edad) %>% 
  summarise("Población promedio" = mean(Población))
# A tibble: 14 x 2
   Rango_edad `Población promedio`
   <chr>                     <dbl>
 1 0 a 4                   301178.
 2 10 a 14                 361577.
 3 15 a 19                 326600.
 4 20 a 24                 269529.
 5 25 a 29                 237230.
 6 30 a 34                 244256 
 7 35 a 39                 225481.
 8 40 a 44                 197310.
 9 45 a 49                 169798.
10 5 a 9                   336668.
11 50 a 54                 130510.
12 55 a 59                 127968.
13 60 y más                302126.
14 NE                        4088.

Otras funciones que ofrece dplyr para resumir información son dplyr::summarise_each() y dplyr::count(). La primera aplica la función resumen a cada una de las columnas y la segunda cuenta el número de valores únicos con o sin un peso establecido.

Population_FEntity %>% count()
# A tibble: 1 x 1
      n
  <int>
1   448

Para eliminar esta propiedad a los datos se utiliza la función dplyr::ungroup() y así la manipulación de datos continuará sin eliminar los resultados ya obtenidos.