Semana 05 — Pipeline de Ingesta desde Múltiples Fuentes

Introducción al Lenguaje de Programación y Estadística R — ITLA

Author

Angelo Pérez

Published

June 5, 2026

# Paquetes necesarios — instala los que falten con:
# install.packages(c("tidyverse", "readxl", "writexl", "DBI", "RSQLite"))
library(tidyverse)
library(readxl)
library(writexl)
library(DBI)
library(RSQLite)

Nota técnica: Este documento genera los archivos empleados.csv y empleados.xlsx automáticamente antes de leerlos, por lo que no es necesario tenerlos descargados previamente.


1 Preparación — Crear los archivos de práctica

# ── Archivo 1: empleados.csv ─────────────────────────────────────────────────
empleados_base <- tibble(
  id_empleado     = sprintf("%03d", 1:20),
  nombre          = c("Ana Torres", "Pedro Méndez", "María López",
                      "Luis García", "Carmen Díaz", "Carlos Mendoza",
                      "Elena Rostova", "Jorge Ortiz", "Lucía Blanco",
                      "Andrés Castro", "Sofia Martínez", "Ricardo Gómez",
                      "Daniela Vega", "Manuel Soler", "Beatriz Luna",
                      "Roberto Peña", "Irene Castillo", "Fernando Plaza",
                      "Gabriela Núñez", "Héctor Vargas"),
  departamento    = c("Tecnología", "Auditoría", "Tecnología", "RRHH",
                      "Auditoría", "Tecnología", "Riesgo", "Finanzas",
                      "RRHH", "Riesgo", "Tecnología", "Auditoría",
                      "Finanzas", "Tecnología", "Riesgo", "Auditoría",
                      "RRHH", "Finanzas", "Tecnología", "Riesgo"),
  salario_mensual = c(58000, 45000, 63000, 41000, 52000, 70000, 65000,
                      48000, 39000, 59000, 61000, 47000, 53000, 55000,
                      67000, 51000, 42000, 46000, 72000, 58000),
  fecha_ingreso   = as.Date(c(
    "2019-03-15", "2021-07-01", "2018-11-20", "2022-01-10",
    "2020-05-30", "2017-04-12", "2021-09-18", "2023-02-05",
    "2022-11-11", "2020-08-24", "2019-06-30", "2022-04-15",
    "2021-01-20", "2020-10-05", "2018-05-14", "2023-07-19",
    "2021-12-01", "2022-08-10", "2016-11-03", "2020-02-28"
  ))
)

write_csv(empleados_base, "empleados.csv")
cat("empleados.csv creado correctamente\n")
empleados.csv creado correctamente
# ── Archivo 2: empleados.xlsx con sheets 2022 y 2023 ─────────────────────────
sheet_2022 <- tibble(
  id_empleado     = sprintf("%03d", 21:30),
  nombre          = c("Patricia Rojas", "Miguel Ángel Soto", "Valentina Cruz",
                      "Javier Morales", "Natalia Fuentes", "Diego Herrera",
                      "Camila Reyes", "Sebastián Pino", "Fernanda Ríos",
                      "Alejandro Vera"),
  departamento    = c("Tecnología", "Auditoría", "RRHH", "Finanzas", "Riesgo",
                      "Tecnología", "Auditoría", "RRHH", "Finanzas", "Riesgo"),
  salario_mensual = c(60000, 43000, 40000, 49000, 64000,
                      68000, 44000, 37000, 51000, 62000)
)

sheet_2023 <- tibble(
  id_empleado     = sprintf("%03d", 31:40),
  nombre          = c("Isabella Romero", "Mateo Salinas", "Valeria Espinoza",
                      "Emilio Contreras", "Andrea Paredes", "Nicolás Bravo",
                      "Catalina Muñoz", "Tomás Aguilar", "Renata Cordero",
                      "Maximiliano Peña"),
  departamento    = c("Tecnología", "Auditoría", "RRHH", "Finanzas", "Riesgo",
                      "Tecnología", "Auditoría", "RRHH", "Finanzas", "Riesgo"),
  salario_mensual = c(74000, 46000, 42000, 54000, 69000,
                      76000, 48000, 41000, 55000, 71000)
)

write_xlsx(
  list("2022" = sheet_2022, "2023" = sheet_2023),
  path = "empleados.xlsx"
)
cat("empleados.xlsx creado correctamente (sheets: 2022, 2023)\n")
empleados.xlsx creado correctamente (sheets: 2022, 2023)

2 Parte 1 — Lectura del CSV

2.1 Leer empleados.csv con tipos explícitos

id_empleado se fuerza a character para preservar los ceros a la izquierda (001 no se convierte en 1). fecha_ingreso se lee directamente como Date.

empleados_csv <- read_csv(
  "empleados.csv",
  col_types = cols(
    id_empleado     = col_character(),
    nombre          = col_character(),
    departamento    = col_character(),
    salario_mensual = col_double(),
    fecha_ingreso   = col_date(format = "%Y-%m-%d")
  )
)

2.2 Verificación con glimpse()

glimpse(empleados_csv)
Rows: 20
Columns: 5
$ id_empleado     <chr> "001", "002", "003", "004", "005", "006", "007", "008"…
$ nombre          <chr> "Ana Torres", "Pedro Méndez", "María López", "Luis Gar…
$ departamento    <chr> "Tecnología", "Auditoría", "Tecnología", "RRHH", "Audi…
$ salario_mensual <dbl> 58000, 45000, 63000, 41000, 52000, 70000, 65000, 48000…
$ fecha_ingreso   <date> 2019-03-15, 2021-07-01, 2018-11-20, 2022-01-10, 2020-…

2.3 Vista previa

empleados_csv

2.4 Estadísticas rápidas

cat("=== Resumen del CSV ===\n")
=== Resumen del CSV ===
cat("Total empleados:        ", nrow(empleados_csv), "\n")
Total empleados:         20 
cat("Departamentos únicos:   ", n_distinct(empleados_csv$departamento), "\n")
Departamentos únicos:    5 
cat("Salario mínimo:   RD$", format(min(empleados_csv$salario_mensual),
                                     big.mark = ","), "\n")
Salario mínimo:   RD$ 39,000 
cat("Salario máximo:   RD$", format(max(empleados_csv$salario_mensual),
                                     big.mark = ","), "\n")
Salario máximo:   RD$ 72,000 
cat("Salario promedio: RD$", format(round(mean(empleados_csv$salario_mensual)),
                                     big.mark = ","), "\n")
Salario promedio: RD$ 54,600 
cat("Ingreso más antiguo: ", as.character(min(empleados_csv$fecha_ingreso)), "\n")
Ingreso más antiguo:  2016-11-03 
cat("Ingreso más reciente:", as.character(max(empleados_csv$fecha_ingreso)), "\n")
Ingreso más reciente: 2023-07-19 

3 Parte 2 — Lectura del Excel (dos sheets)

3.1 Leer sheet "2022" y sheet "2023"

sheet_2022_leido <- read_excel(
  "empleados.xlsx",
  sheet     = "2022",
  col_types = c("text", "text", "text", "numeric")
)

sheet_2023_leido <- read_excel(
  "empleados.xlsx",
  sheet     = "2023",
  col_types = c("text", "text", "text", "numeric")
)

cat("Filas en sheet 2022:", nrow(sheet_2022_leido), "\n")
Filas en sheet 2022: 10 
cat("Filas en sheet 2023:", nrow(sheet_2023_leido), "\n")
Filas en sheet 2023: 10 

3.2 Combinar con columna anio

empleados_excel <- bind_rows(
  sheet_2022_leido |> mutate(anio = 2022L),
  sheet_2023_leido |> mutate(anio = 2023L)
)

glimpse(empleados_excel)
Rows: 20
Columns: 5
$ id_empleado     <chr> "021", "022", "023", "024", "025", "026", "027", "028"…
$ nombre          <chr> "Patricia Rojas", "Miguel Ángel Soto", "Valentina Cruz…
$ departamento    <chr> "Tecnología", "Auditoría", "RRHH", "Finanzas", "Riesgo…
$ salario_mensual <dbl> 60000, 43000, 40000, 49000, 64000, 68000, 44000, 37000…
$ anio            <int> 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, …

3.3 Vista previa combinada

empleados_excel

3.4 Promedio de salario por departamento

cat("=== Salario promedio por departamento (Excel) ===\n")
=== Salario promedio por departamento (Excel) ===
empleados_excel |>
  group_by(departamento) |>
  summarise(
    n_empleados      = n(),
    salario_promedio = round(mean(salario_mensual), 0),
    salario_minimo   = min(salario_mensual),
    salario_maximo   = max(salario_mensual),
    .groups          = "drop"
  ) |>
  arrange(desc(salario_promedio)) |>
  print()
# A tibble: 5 × 5
  departamento n_empleados salario_promedio salario_minimo salario_maximo
  <chr>              <int>            <dbl>          <dbl>          <dbl>
1 Tecnología             4            69500          60000          76000
2 Riesgo                 4            66500          62000          71000
3 Finanzas               4            52250          49000          55000
4 Auditoría              4            45250          43000          48000
5 RRHH                   4            40000          37000          42000

3.5 Promedio por departamento y año

cat("=== Salario promedio por departamento y año ===\n")
=== Salario promedio por departamento y año ===
empleados_excel |>
  group_by(anio, departamento) |>
  summarise(
    salario_promedio = round(mean(salario_mensual), 0),
    .groups = "drop"
  ) |>
  arrange(anio, desc(salario_promedio)) |>
  print()
# A tibble: 10 × 3
    anio departamento salario_promedio
   <int> <chr>                   <dbl>
 1  2022 Tecnología              64000
 2  2022 Riesgo                  63000
 3  2022 Finanzas                50000
 4  2022 Auditoría               43500
 5  2022 RRHH                    38500
 6  2023 Tecnología              75000
 7  2023 Riesgo                  70000
 8  2023 Finanzas                54500
 9  2023 Auditoría               47000
10  2023 RRHH                    41500

4 Parte 3 — Base de Datos SQLite

4.1 Crear conexión y escribir tabla

empleados_sql_data <- bind_rows(
  empleados_csv |>
    mutate(anio = 2022L,
           monto_total_año = salario_mensual * 12) |>
    select(id_empleado, anio, monto_total_año),
  empleados_csv |>
    mutate(anio = 2023L,
           monto_total_año = round(salario_mensual * 12 * 1.05)) |>
    select(id_empleado, anio, monto_total_año)
)

con <- dbConnect(RSQLite::SQLite(), dbname = "nomina_dgii.sqlite")

dbWriteTable(con, name = "empleados", value = empleados_sql_data,
             overwrite = TRUE)

cat("Tabla 'empleados' creada en SQLite\n")
Tabla 'empleados' creada en SQLite
cat("Tablas disponibles:", dbListTables(con), "\n")
Tablas disponibles: empleados 
cat("Columnas:          ", dbListFields(con, "empleados"), "\n")
Columnas:           id_empleado anio monto_total_año 

4.2 Consulta — todos los registros

cat("=== Todos los registros ===\n")
=== Todos los registros ===
dbGetQuery(con,
  "SELECT * FROM empleados ORDER BY id_empleado, anio") |>
  as_tibble() |>
  print()
# A tibble: 40 × 3
   id_empleado  anio monto_total_año
   <chr>       <int>           <dbl>
 1 001          2022          696000
 2 001          2023          730800
 3 002          2022          540000
 4 002          2023          567000
 5 003          2022          756000
 6 003          2023          793800
 7 004          2022          492000
 8 004          2023          516600
 9 005          2022          624000
10 005          2023          655200
# ℹ 30 more rows

4.3 Consulta con WHERE anio = 2023

cat("=== Registros del año 2023 ===\n")
=== Registros del año 2023 ===
dbGetQuery(con,
  "SELECT id_empleado,
          anio,
          monto_total_año,
          ROUND(monto_total_año / 12.0, 0) AS salario_mensual_est
   FROM   empleados
   WHERE  anio = 2023
   ORDER  BY monto_total_año DESC") |>
  as_tibble() |>
  print()
# A tibble: 20 × 4
   id_empleado  anio monto_total_año salario_mensual_est
   <chr>       <int>           <dbl>               <dbl>
 1 019          2023          907200               75600
 2 006          2023          882000               73500
 3 015          2023          844200               70350
 4 007          2023          819000               68250
 5 003          2023          793800               66150
 6 011          2023          768600               64050
 7 010          2023          743400               61950
 8 001          2023          730800               60900
 9 020          2023          730800               60900
10 014          2023          693000               57750
11 013          2023          667800               55650
12 005          2023          655200               54600
13 016          2023          642600               53550
14 008          2023          604800               50400
15 012          2023          592200               49350
16 018          2023          579600               48300
17 002          2023          567000               47250
18 017          2023          529200               44100
19 004          2023          516600               43050
20 009          2023          491400               40950

4.4 Agregación por año

cat("=== Nómina total por año ===\n")
=== Nómina total por año ===
dbGetQuery(con,
  "SELECT anio,
          COUNT(id_empleado)             AS n_empleados,
          SUM(monto_total_año)           AS nomina_total,
          ROUND(AVG(monto_total_año), 0) AS promedio_anual
   FROM   empleados
   GROUP  BY anio
   ORDER  BY anio") |>
  as_tibble() |>
  print()
# A tibble: 2 × 4
   anio n_empleados nomina_total promedio_anual
  <int>       <int>        <dbl>          <dbl>
1  2022          20     13104000         655200
2  2023          20     13759200         687960
dbDisconnect(con)
cat("Conexión SQLite cerrada\n")
Conexión SQLite cerrada

5 Consolidado Final

5.1 Unir las tres fuentes y enriquecer

consolidado <- empleados_csv |>
  mutate(
    antiguedad_años = floor(
      as.numeric(Sys.Date() - fecha_ingreso) / 365.25
    ) |> as.integer(),
    salario_anual  = salario_mensual * 12,
    banda_salarial = case_when(
      salario_mensual <  45000 ~ "Banda A  (<45k)",
      salario_mensual <  60000 ~ "Banda B (45k–60k)",
      salario_mensual <  70000 ~ "Banda C (60k–70k)",
      TRUE                     ~ "Banda D  (70k+)"
    )
  ) |>
  arrange(departamento, desc(salario_mensual))

cat("=== Dataset Consolidado ===\n")
=== Dataset Consolidado ===
glimpse(consolidado)
Rows: 20
Columns: 8
$ id_empleado     <chr> "005", "016", "012", "002", "013", "008", "018", "017"…
$ nombre          <chr> "Carmen Díaz", "Roberto Peña", "Ricardo Gómez", "Pedro…
$ departamento    <chr> "Auditoría", "Auditoría", "Auditoría", "Auditoría", "F…
$ salario_mensual <dbl> 52000, 51000, 47000, 45000, 53000, 48000, 46000, 42000…
$ fecha_ingreso   <date> 2020-05-30, 2023-07-19, 2022-04-15, 2021-07-01, 2021-…
$ antiguedad_años <int> 6, 2, 4, 4, 5, 3, 3, 4, 4, 3, 8, 4, 5, 6, 9, 9, 7, 6, …
$ salario_anual   <dbl> 624000, 612000, 564000, 540000, 636000, 576000, 552000…
$ banda_salarial  <chr> "Banda B (45k–60k)", "Banda B (45k–60k)", "Banda B (45…

5.2 Vista final del consolidado

consolidado

5.3 Resumen por departamento

consolidado |>
  group_by(departamento) |>
  summarise(
    n_empleados      = n(),
    salario_promedio = round(mean(salario_mensual), 0),
    nomina_mensual   = sum(salario_mensual),
    nomina_anual     = sum(salario_anual),
    antiguedad_prom  = round(mean(antiguedad_años), 1),
    .groups          = "drop"
  ) |>
  arrange(desc(nomina_mensual)) |>
  print()
# A tibble: 5 × 6
  departamento n_empleados salario_promedio nomina_mensual nomina_anual
  <chr>              <int>            <dbl>          <dbl>        <dbl>
1 Tecnología             6            63167         379000      4548000
2 Riesgo                 4            62250         249000      2988000
3 Auditoría              4            48750         195000      2340000
4 Finanzas               3            49000         147000      1764000
5 RRHH                   3            40667         122000      1464000
# ℹ 1 more variable: antiguedad_prom <dbl>

5.4 Distribución por banda salarial

consolidado |>
  count(banda_salarial) |>
  mutate(pct = round(n / sum(n) * 100, 1)) |>
  print()
# A tibble: 4 × 3
  banda_salarial        n   pct
  <chr>             <int> <dbl>
1 Banda A  (<45k)       3    15
2 Banda B (45k–60k)    11    55
3 Banda C (60k–70k)     4    20
4 Banda D  (70k+)       2    10

Sesión de R:
R version: 4.6.0 
tidyverse: 2.0.0 
readxl:    1.4.5 
writexl:   1.5.4 
DBI:       1.3.0 
RSQLite:   3.53.1 
Fecha:     2026-06-05 
install.packages("writexl")

Práctica Semana 05 — Introducción al Lenguaje de Programación y Estadística R — ITLA T2 2026