03: Tidyverse

Virtual

Autor/a

Victor Adrian

Fecha de publicación

2026-03-27

Código
knitr::opts_chunk$set(echo = TRUE, error = TRUE, eval = TRUE, include = TRUE)

Intro

La clase es una introducción a los paquetes que integran tidyverse, con foco en la lectura de archivos con readr y readxl, y algunos verbos/funciones de dplyr. Para evitar redundancia, me limitaré a aportar a la definición de tidyverse —además de qué ofrece—, más una breve mención al operador pipe.

La información y ejemplos prácticos con funciones de tidyverse se encuentran en las diapositivas de la clase 03.

Como siempre, al final hay ejercicios de la práctica resueltos.

¿Qué es el tidyverse?

Se trata de un paquete/conjunto de paquetes que trabajan en armonía al compartir representaciones de datos comunes (estructuras, síntaxis y filosofía). Su propósito es el de simplificar la instalación y carga de estos paquetes en un solo paso.

Entre los paquetes se encuentran aquellos que forman parte del core, los más usados cotidianamente, y otros con usos específicos. Ver más.

Core tidyverse

Paquete Función
dplyr manipular datos
tidyr ordenar datos
tibble mejorar lo ofrecido por un data frame
readr leer datos “rectángulares”
ggplot2 visualizar datos
purrr escalar funciones
stringr manipular texto
lubridate manipular fechas y hora
forcats manipular factores

Reglas “tidy”

  1. Cada variable ocupa una columna.
  2. Cada observación ocupa una fila.
  3. Cada valor ocupa una variable.

Es necesario que los datos sigan este formato para poder utilizar los verbos del paquete dplyr; además de ser el formato recomendado para manipular datasets, independientemente del lenguaje o herramienta.

El operador pipe

Un operador pipe (tubo) es un pasador de inputs. Toma como input de una función el output de una anterior, evitando el anidado (nesting) de funciones y la creación y almacenamiento en memoria de variables/objetos intermedios para lograr iguales resultados.

La versión preferida actualmente es la nativa de R, |>, que reemplaza al %>% de los paquetes tidyverse y magrittr. Su principal ventaja radica en facilitar la escritura y lectura de código, y no requerir la instalación de librerías (paquetes) al ser nativo.

Cabe aclarar que no es una característica exclusiva de R, la mayoría de lenguajes tienen un operador pipe.

Práctica

Consignas

  • Todos los ejercicios utilizan el dataset Datos_por_departamento_y_actividad.csv ubicado en la carpeta datos/ del repositorio.
  • Resolver cada ejercicio en un único bloque encadenado con el pipe |>.
  • Guardar cada resultado como un CSV dentro de output/clase03/ usando write_csv().
  • Se pueden usar solamente las funciones vistas en clase: read_csv(), select(), filter(), mutate(), arrange(), summarise(), group_by() y el pipe |>.

Vistazo al dataset

Código
# No tengo instalado tidyverse para evitar cargar paquetes que no uso y ocupan espacio, por eso la carga individual
library(tibble)
library(dplyr)
library(readr)
Código
df = read_csv(r"(..\..\datos\Datos_por_departamento_y_actividad.csv)", show_col_types = FALSE)
glimpse(df)
cat("\nValores únicos por columna:\n")
for (col in names(df)) {
    cat(col, " -> ", n_distinct(df[[col]]), "\n", sep = "")
}
Rows: 195,370
Columns: 11
$ anio                  <dbl> 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, …
$ in_departamentos      <dbl> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, …
$ departamento          <chr> "Comuna 1", "Comuna 1", "Comuna 1", "Comuna 1", …
$ provincia_id          <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ provincia             <chr> "CABA", "CABA", "CABA", "CABA", "CABA", "CABA", …
$ clae6                 <dbl> 11111, 11112, 11119, 11121, 11129, 11130, 11211,…
$ clae2                 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ letra                 <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"…
$ Empleo                <dbl> 33, 407, 1193, 85, 78, 2, 743, 18, 170, 29, 15, …
$ Establecimientos      <dbl> 9, 73, 343, 29, 24, 2, 244, 6, 25, 5, 8, 3, 1, 4…
$ empresas_exportadoras <dbl> 4, 2, 8, 0, 0, 0, 9, 1, 4, 0, 2, 0, 0, 1, 0, 0, …

Valores únicos por columna:
anio -> 2
in_departamentos -> 527
departamento -> 445
provincia_id -> 24
provincia -> 24
clae6 -> 945
clae2 -> 87
letra -> 21
Empleo -> 2255
Establecimientos -> 531
empresas_exportadoras -> 91

Ej. 1

Código
filtro_prov = "Buenos Aires"
filtro_anio = 2022

output_ej_1 = df |> # definirlo como objeto es una decisión propia para poder manejarlo mejor
    filter(provincia == filtro_prov, anio == filtro_anio) |>
    group_by(departamento) |>
    summarize(
        empl_industrial = sum(Empleo[letra == "C"]),
        empl_total = sum(Empleo),
        share_empl_industrial = round(empl_industrial / empl_total, 2)
    ) |>
    filter(empl_industrial > 500) |> # primero filtro, para ordenar solo lo que voy a usar
    arrange(desc(share_empl_industrial))

output_ej_1
write_csv(output_ej_1, r"(..\..\output\clase03\ejercicio_1.csv)")
# si no se define un objeto para el output, se puede pasar `write_csv()` con el operador `|>`
# A tibble: 76 × 4
   departamento       empl_industrial empl_total share_empl_industrial
   <chr>                        <dbl>      <dbl>                 <dbl>
 1 General Las Heras             1353       2274                  0.59
 2 Ramallo                       6749      11849                  0.57
 3 Magdalena                      967       1926                  0.5 
 4 Capitán Sarmiento             1340       2726                  0.49
 5 Colón                         1849       3898                  0.47
 6 General San Martín           37348      80264                  0.47
 7 Tres de Febrero              26103      56379                  0.46
 8 Cañuelas                      4292      10047                  0.43
 9 Zárate                       12191      28304                  0.43
10 Navarro                        699       1762                  0.4 
# ℹ 66 more rows

Ej. 2

Código
options(width = 300) # para no truncar el ancho de este output

output_ej_2 = df |>
    filter(anio == filtro_anio) |>
    group_by(provincia) |>
    summarise(
        empl_total = sum(Empleo),
        establ_total = sum(Establecimientos),
        empl_por_establ = round(empl_total / establ_total, 2)
    ) |>
    mutate(
        categoria = ifelse(empl_por_establ > median(empl_por_establ),
        paste("encima de Mdn Nac.", round(median(empl_por_establ), 2)),
        paste("debajo de Mdn Nac.", round(median(empl_por_establ), 2))
        )
    ) |>
    arrange(desc(empl_por_establ))

print.data.frame(output_ej_2)
write_csv(output_ej_2, r"(..\..\output\clase03\ejercicio_2.csv)")
             provincia empl_total establ_total empl_por_establ               categoria
1              Tucuman     178863        19802            9.03 encima de Mdn Nac. 6.81
2           Santa Cruz      60009         6999            8.57 encima de Mdn Nac. 6.81
3     Tierra Del Fuego      38003         4550            8.35 encima de Mdn Nac. 6.81
4              Neuquen     126837        16781            7.56 encima de Mdn Nac. 6.81
5                 CABA    1596397       212077            7.53 encima de Mdn Nac. 6.81
6             La Rioja      32613         4391            7.43 encima de Mdn Nac. 6.81
7             San Juan      86824        11929            7.28 encima de Mdn Nac. 6.81
8                Jujuy      62476         8659            7.22 encima de Mdn Nac. 6.81
9               Chubut     100217        14008            7.15 encima de Mdn Nac. 6.81
10        Buenos Aires    2108119       302925            6.96 encima de Mdn Nac. 6.81
11               Salta     119944        17261            6.95 encima de Mdn Nac. 6.81
12            Misiones     111105        16215            6.85 encima de Mdn Nac. 6.81
13           Catamarca      34191         5047            6.77 debajo de Mdn Nac. 6.81
14            San Luis      57169         8612            6.64 debajo de Mdn Nac. 6.81
15            Santa Fe     543358        84118            6.46 debajo de Mdn Nac. 6.81
16           Rio Negro     115372        17976            6.42 debajo de Mdn Nac. 6.81
17             Mendoza     252202        39580            6.37 debajo de Mdn Nac. 6.81
18               Chaco      87672        13877            6.32 debajo de Mdn Nac. 6.81
19             Cordoba     537565        86771            6.20 debajo de Mdn Nac. 6.81
20             Formosa      26982         4501            5.99 debajo de Mdn Nac. 6.81
21 Santiago Del Estero      55944         9479            5.90 debajo de Mdn Nac. 6.81
22          Corrientes      81033        13984            5.79 debajo de Mdn Nac. 6.81
23          Entre Rios     141767        26278            5.39 debajo de Mdn Nac. 6.81
24            La Pampa      40787         9898            4.12 debajo de Mdn Nac. 6.81

Ej. 3

Código
filtro_anio_2 = 2021

output_ej_3 = df |>
    filter(anio == filtro_anio_2) |>
    group_by(letra) |>
    summarise(
        emp_expo_total = sum(empresas_exportadoras),
        establ_total = sum(Establecimientos),
        share_emp_expo = round(emp_expo_total / establ_total, 2) # no me gusta multiplicar por cien los porcentajes
    ) |>
    filter(establ_total > 1000) |>
    arrange(desc(share_emp_expo))

output_ej_3
write_csv(output_ej_3, r"(..\..\output\clase03\ejercicio_3.csv)")
# A tibble: 19 × 4
   letra emp_expo_total establ_total share_emp_expo
   <chr>          <dbl>        <dbl>          <dbl>
 1 B               1219         3921           0.31
 2 C              21234       102706           0.21
 3 J               2093        21718           0.1 
 4 D                168         3180           0.05
 5 G              10632       260346           0.04
 6 A               2603        80490           0.03
 7 F                777        41546           0.02
 8 I                855        47507           0.02
 9 E                 31         2712           0.01
10 H                820        56960           0.01
11 M                394        44280           0.01
12 N                375        48904           0.01
13 Q                289        36685           0.01
14 R                 67        12267           0.01
15 K                 79        25478           0   
16 L                 41        27679           0   
17 O                  0         2046           0   
18 P                 18        18823           0   
19 S                107        83822           0