Análisis de Datos I

Semana 4 · Hora mixta: Limpieza I de datos municipales

Dr(c). César Marcelo Ávila Fuentes

2026-04-08

Propósito de la sesión

Al finalizar este laboratorio, se espera que puedan:

  • cargar una base municipal en R
  • inspeccionar su estructura general
  • limpiar nombres de variables
  • revisar y corregir tipos de datos
  • transformar variables de remuneración a formato numérico
  • transformar fechas a formato fecha
  • detectar y tratar missing de manera justificada
  • guardar una base limpia para análisis posteriores

Base de trabajo

En esta sesión trabajaremos con una base municipal que contiene información como:

  • año y mes
  • estamento
  • nombre completo
  • cargo o función
  • formación
  • región
  • remuneraciones
  • fechas de inicio y término
  • observaciones

Idea central del laboratorio

La meta es dejar la base en condiciones mínimas para que luego sí podamos:

  • describirla
  • resumirla
  • graficarla
  • compararla

Ruta de trabajo

  1. Cargar la base
  2. Inspeccionar su estructura
  3. Limpiar nombres de variables
  4. Seleccionar y renombrar variables clave
  5. Revisar tipos de datos
  6. Limpiar remuneraciones
  7. Convertir fechas
  8. Revisar missing
  9. Detectar duplicados
  10. Guardar la base limpia
  11. Pensar cómo unir meses distintos

Paquetes de trabajo

library(dplyr)
library(tidyr)
library(stringr)
library(lubridate)
library(janitor)
library(skimr)
library(here)

Paso 1 · Cargar la base

Base <- readRDS("datos.rds")

Si el archivo está dentro de una carpeta del proyecto

Base <- readRDS(here("datos", "datos.rds"))

Paso 2 · Inspección inicial

dim(Base)
[1] 56 21
names(Base)
 [1] "Año"                                                                                    
 [2] "Mes"                                                                                    
 [3] "Estamento"                                                                              
 [4] "Nombre completo"                                                                        
 [5] "Cargo o función"                                                                        
 [6] "Grado EUS o jornada"                                                                    
 [7] "Calificación profesional o formación"                                                   
 [8] "Región"                                                                                 
 [9] "Asignaciones especiales del mes (inc. en rem. bruta)"                                   
[10] "Remuneración bruta del mes (incluye bonos e incentivos, asig. especiales, horas extras)"
[11] "Remuneración líquida del mes"                                                           
[12] "Rem. adicionales del mes (no inc. en rem. bruta)"                                       
[13] "Remuneración Bonos incentivos del mes (inc. en rem. bruta)"                             
[14] "Derecho a horas extraordinarias"                                                        
[15] "Montos y horas extraordinarias diurnas del mes(inc. en rem. bruta)"                     
[16] "Montos y horas extraordinarias nocturnas del mes(inc. en rem. bruta)"                   
[17] "Montos y horas extraordinarias festivas del mes (inc. en rem. bruta)"                   
[18] "Fecha de inicio dd/mm/aa"                                                               
[19] "Fecha de término dd/mm/aa"                                                              
[20] "Viáticos del mes (no inc. en rem. bruta)"                                               
[21] "Observaciones"                                                                          

Paso 2 · Inspección inicial

head(Base)
# A tibble: 6 × 21
    Año Mes     Estamento      `Nombre completo`               `Cargo o función`
  <int> <chr>   <chr>          <chr>                           <chr>            
1  2026 Febrero Auxiliar       ALARCON SOTO, CRISTIAN          OPERADOR PLANTA …
2  2026 Febrero Auxiliar       ARANEDA LAGOS, ALEJANDRO GONZA… ENCARGADO ESTADI…
3  2026 Febrero Técnico        ARAVENA DIAZ, MATIAS NICOLAS    ENCARGADO CEMENT…
4  2026 Febrero Auxiliar       AROSTICA MARTINEZ, EDGARDO ALA… AUXILIAR DIR. OB…
5  2026 Febrero Auxiliar       BELTRAN SAAVEDRA, RAMIRO LEONA… CONDUCTOR DIRECC…
6  2026 Febrero Administrativo CAQUILPAN REYES, MONICA DEL CA… ENCARGADA DEL RE…
# ℹ 16 more variables: `Grado EUS o jornada` <int>,
#   `Calificación profesional o formación` <chr>, Región <chr>,
#   `Asignaciones especiales del mes (inc. en rem. bruta)` <chr>,
#   `Remuneración bruta del mes (incluye bonos e incentivos, asig. especiales, horas extras)` <chr>,
#   `Remuneración líquida del mes` <lgl>,
#   `Rem. adicionales del mes (no inc. en rem. bruta)` <lgl>,
#   `Remuneración Bonos incentivos del mes (inc. en rem. bruta)` <chr>, …

Paso 2 · Inspección inicial

str(Base)
tibble [56 × 21] (S3: tbl_df/tbl/data.frame)
 $ Año                                                                                    : int [1:56] 2026 2026 2026 2026 2026 2026 2026 2026 2026 2026 ...
 $ Mes                                                                                    : chr [1:56] "Febrero" "Febrero" "Febrero" "Febrero" ...
 $ Estamento                                                                              : chr [1:56] "Auxiliar" "Auxiliar" "Técnico" "Auxiliar" ...
 $ Nombre completo                                                                        : chr [1:56] "ALARCON SOTO, CRISTIAN" "ARANEDA LAGOS, ALEJANDRO GONZALO" "ARAVENA DIAZ, MATIAS NICOLAS" "AROSTICA MARTINEZ, EDGARDO ALAMIRO" ...
 $ Cargo o función                                                                        : chr [1:56] "OPERADOR PLANTA TRATAMIENTO AGUAS SERVIDAS EN SAN PATRICIO , DIR. ASEO ORNATO" "ENCARGADO ESTADIO CHERQUENCO DIDECO" "ENCARGADO CEMENTERIOS DIRECCIÓN MEDIO AMBIENTE ASEO Y ORNATO" "AUXILIAR DIR. OBRAS" ...
 $ Grado EUS o jornada                                                                    : int [1:56] 20 20 17 18 20 15 17 20 17 17 ...
 $ Calificación profesional o formación                                                   : chr [1:56] "Enseñanza Media, Estudios técnicos en instalaciones sanitarias" "Enseñanza Media" "Estudios Técnicos" "Estudios Medios" ...
 $ Región                                                                                 : chr [1:56] "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" ...
 $ Asignaciones especiales del mes (inc. en rem. bruta)                                   : chr [1:56] "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(08)(09)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(08)(09)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(54)(33)(08)" ...
 $ Remuneración bruta del mes (incluye bonos e incentivos, asig. especiales, horas extras): chr [1:56] "$ 1.322.269" "$ 1.094.529" "$ 1.485.546" "$ 1.514.638" ...
 $ Remuneración líquida del mes                                                           : logi [1:56] NA NA NA NA NA NA ...
 $ Rem. adicionales del mes (no inc. en rem. bruta)                                       : logi [1:56] NA NA NA NA NA NA ...
 $ Remuneración Bonos incentivos del mes (inc. en rem. bruta)                             : chr [1:56] "$ 0" "$ 0" "$ 0" "$ 0" ...
 $ Derecho a horas extraordinarias                                                        : chr [1:56] "Sí" "Sí" "No" "Sí" ...
 $ Montos y horas extraordinarias diurnas del mes(inc. en rem. bruta)                     : chr [1:56] "No tiene" "$ 33.608 : 14,00 hrs" "No tiene" "$ 35.864 : 13,00 hrs" ...
 $ Montos y horas extraordinarias nocturnas del mes(inc. en rem. bruta)                   : chr [1:56] "$ 72.018 : 25,00 hrs" "$ 158.439 : 55,00 hrs" "No tiene" "$ 26.484 : 8,00 hrs" ...
 $ Montos y horas extraordinarias festivas del mes (inc. en rem. bruta)                   : chr [1:56] "No tiene" "No tiene" "No tiene" "No tiene" ...
 $ Fecha de inicio dd/mm/aa                                                               : chr [1:56] "20/06/2022" "22/06/2021" "01/01/2021" "22/05/2006" ...
 $ Fecha de término dd/mm/aa                                                              : chr [1:56] "31/12/2026" "31/12/2026" "31/12/2026" "31/12/2026" ...
 $ Viáticos del mes (no inc. en rem. bruta)                                               : chr [1:56] "No informa" "No informa" "No informa" "No informa" ...
 $ Observaciones                                                                          : chr [1:56] "decreto nombramiento n° 2680 24/06/2022 jornada 22 horas semanales; decreto 2789 06/07/2022 nombramiento contra"| __truncated__ "decreto nombramiento 2735 29/06/2021; Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desd"| __truncated__ "decreto 2747 29/06/2021;Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desde 01/07/2022 h"| __truncated__ "decreto 2747 29/06/2021; DECRETO 48 11/01/2022; decreto 5911 30/12/2022; Decreto 349 23/01/2024; decreto 6359 2"| __truncated__ ...
summary(Base)
      Año           Mes             Estamento         Nombre completo   
 Min.   :2026   Length:56          Length:56          Length:56         
 1st Qu.:2026   Class :character   Class :character   Class :character  
 Median :2026   Mode  :character   Mode  :character   Mode  :character  
 Mean   :2026                                                           
 3rd Qu.:2026                                                           
 Max.   :2026                                                           
 Cargo o función    Grado EUS o jornada Calificación profesional o formación
 Length:56          Min.   :10.00       Length:56                           
 Class :character   1st Qu.:15.00       Class :character                    
 Mode  :character   Median :17.00       Mode  :character                    
                    Mean   :16.68                                           
                    3rd Qu.:20.00                                           
                    Max.   :20.00                                           
    Región          Asignaciones especiales del mes (inc. en rem. bruta)
 Length:56          Length:56                                           
 Class :character   Class :character                                    
 Mode  :character   Mode  :character                                    
                                                                        
                                                                        
                                                                        
 Remuneración bruta del mes (incluye bonos e incentivos, asig. especiales, horas extras)
 Length:56                                                                              
 Class :character                                                                       
 Mode  :character                                                                       
                                                                                        
                                                                                        
                                                                                        
 Remuneración líquida del mes Rem. adicionales del mes (no inc. en rem. bruta)
 Mode:logical                 Mode:logical                                    
 NA's:56                      NA's:56                                         
                                                                              
                                                                              
                                                                              
                                                                              
 Remuneración Bonos incentivos del mes (inc. en rem. bruta)
 Length:56                                                 
 Class :character                                          
 Mode  :character                                          
                                                           
                                                           
                                                           
 Derecho a horas extraordinarias
 Length:56                      
 Class :character               
 Mode  :character               
                                
                                
                                
 Montos y horas extraordinarias diurnas del mes(inc. en rem. bruta)
 Length:56                                                         
 Class :character                                                  
 Mode  :character                                                  
                                                                   
                                                                   
                                                                   
 Montos y horas extraordinarias nocturnas del mes(inc. en rem. bruta)
 Length:56                                                           
 Class :character                                                    
 Mode  :character                                                    
                                                                     
                                                                     
                                                                     
 Montos y horas extraordinarias festivas del mes (inc. en rem. bruta)
 Length:56                                                           
 Class :character                                                    
 Mode  :character                                                    
                                                                     
                                                                     
                                                                     
 Fecha de inicio dd/mm/aa Fecha de término dd/mm/aa
 Length:56                Length:56                
 Class :character         Class :character         
 Mode  :character         Mode  :character         
                                                   
                                                   
                                                   
 Viáticos del mes (no inc. en rem. bruta) Observaciones     
 Length:56                                Length:56         
 Class :character                         Class :character  
 Mode  :character                         Mode  :character  
                                                            
                                                            
                                                            

Revisión rápida con skim()

skim(Base)
Data summary
Name Base
Number of rows 56
Number of columns 21
_______________________
Column type frequency:
character 17
logical 2
numeric 2
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
Mes 0 1 7 7 0 1 0
Estamento 0 1 7 14 0 4 0
Nombre completo 0 1 22 48 0 56 0
Cargo o función 0 1 12 98 0 50 0
Calificación profesional o formación 0 1 7 100 0 38 0
Región 0 1 22 22 0 1 0
Asignaciones especiales del mes (inc. en rem. bruta) 0 1 14 64 0 22 0
Remuneración bruta del mes (incluye bonos e incentivos, asig. especiales, horas extras) 0 1 9 11 0 54 0
Remuneración Bonos incentivos del mes (inc. en rem. bruta) 0 1 0 3 2 2 0
Derecho a horas extraordinarias 0 1 2 2 0 2 0
Montos y horas extraordinarias diurnas del mes(inc. en rem. bruta) 0 1 8 21 0 31 0
Montos y horas extraordinarias nocturnas del mes(inc. en rem. bruta) 0 1 8 21 0 23 0
Montos y horas extraordinarias festivas del mes (inc. en rem. bruta) 0 1 8 8 0 1 0
Fecha de inicio dd/mm/aa 0 1 10 10 0 34 0
Fecha de término dd/mm/aa 0 1 10 10 0 1 0
Viáticos del mes (no inc. en rem. bruta) 0 1 10 10 0 1 0
Observaciones 0 1 48 370 0 44 0

Variable type: logical

skim_variable n_missing complete_rate mean count
Remuneración líquida del mes 56 0 NaN :
Rem. adicionales del mes (no inc. en rem. bruta) 56 0 NaN :

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
Año 0 1 2026.00 0.00 2026 2026 2026 2026 2026 ▁▁▇▁▁
Grado EUS o jornada 0 1 16.68 2.99 10 15 17 20 20 ▃▁▂▇▇

Paso 3 · Limpiar nombres de variables

Base_limpia <- Base |>
  clean_names()

names(Base_limpia)
 [1] "ano"                                                                               
 [2] "mes"                                                                               
 [3] "estamento"                                                                         
 [4] "nombre_completo"                                                                   
 [5] "cargo_o_funcion"                                                                   
 [6] "grado_eus_o_jornada"                                                               
 [7] "calificacion_profesional_o_formacion"                                              
 [8] "region"                                                                            
 [9] "asignaciones_especiales_del_mes_inc_en_rem_bruta"                                  
[10] "remuneracion_bruta_del_mes_incluye_bonos_e_incentivos_asig_especiales_horas_extras"
[11] "remuneracion_liquida_del_mes"                                                      
[12] "rem_adicionales_del_mes_no_inc_en_rem_bruta"                                       
[13] "remuneracion_bonos_incentivos_del_mes_inc_en_rem_bruta"                            
[14] "derecho_a_horas_extraordinarias"                                                   
[15] "montos_y_horas_extraordinarias_diurnas_del_mes_inc_en_rem_bruta"                   
[16] "montos_y_horas_extraordinarias_nocturnas_del_mes_inc_en_rem_bruta"                 
[17] "montos_y_horas_extraordinarias_festivas_del_mes_inc_en_rem_bruta"                  
[18] "fecha_de_inicio_dd_mm_aa"                                                          
[19] "fecha_de_termino_dd_mm_aa"                                                         
[20] "viaticos_del_mes_no_inc_en_rem_bruta"                                              
[21] "observaciones"                                                                     

¿Por qué partimos por aquí?

Porque nombres más limpios permiten:

  • escribir código más corto
  • reducir errores
  • leer mejor la base
  • dejar un script más ordenado

Paso 4 · Renombrar variables largas

Base_limpia <- Base_limpia |>
  rename(
    anio = ano,
    cargo = cargo_o_funcion,
    formacion = calificacion_profesional_o_formacion,
    rem_bruta = remuneracion_bruta_del_mes_incluye_bonos_e_incentivos_asig_especiales_horas_extras,
    rem_liquida = remuneracion_liquida_del_mes,
    fecha_inicio = fecha_de_inicio_dd_mm_aa,
    fecha_termino = fecha_de_termino_dd_mm_aa
  )

¿Por qué renombrar?

Porque facilita:

  • leer el código
  • detectar errores
  • trabajar con menos texto
  • interpretar mejor la base

Paso 5 · Revisar tipos de variables

class(Base_limpia$rem_bruta)
[1] "character"
class(Base_limpia$rem_liquida)
[1] "logical"
class(Base_limpia$fecha_inicio)
[1] "character"
class(Base_limpia$fecha_termino)
[1] "character"
class(Base_limpia$estamento)
[1] "character"
str(Base_limpia)
tibble [56 × 21] (S3: tbl_df/tbl/data.frame)
 $ anio                                                             : int [1:56] 2026 2026 2026 2026 2026 2026 2026 2026 2026 2026 ...
 $ mes                                                              : chr [1:56] "Febrero" "Febrero" "Febrero" "Febrero" ...
 $ estamento                                                        : chr [1:56] "Auxiliar" "Auxiliar" "Técnico" "Auxiliar" ...
 $ nombre_completo                                                  : chr [1:56] "ALARCON SOTO, CRISTIAN" "ARANEDA LAGOS, ALEJANDRO GONZALO" "ARAVENA DIAZ, MATIAS NICOLAS" "AROSTICA MARTINEZ, EDGARDO ALAMIRO" ...
 $ cargo                                                            : chr [1:56] "OPERADOR PLANTA TRATAMIENTO AGUAS SERVIDAS EN SAN PATRICIO , DIR. ASEO ORNATO" "ENCARGADO ESTADIO CHERQUENCO DIDECO" "ENCARGADO CEMENTERIOS DIRECCIÓN MEDIO AMBIENTE ASEO Y ORNATO" "AUXILIAR DIR. OBRAS" ...
 $ grado_eus_o_jornada                                              : int [1:56] 20 20 17 18 20 15 17 20 17 17 ...
 $ formacion                                                        : chr [1:56] "Enseñanza Media, Estudios técnicos en instalaciones sanitarias" "Enseñanza Media" "Estudios Técnicos" "Estudios Medios" ...
 $ region                                                           : chr [1:56] "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" ...
 $ asignaciones_especiales_del_mes_inc_en_rem_bruta                 : chr [1:56] "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(08)(09)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(08)(09)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(54)(33)(08)" ...
 $ rem_bruta                                                        : chr [1:56] "$ 1.322.269" "$ 1.094.529" "$ 1.485.546" "$ 1.514.638" ...
 $ rem_liquida                                                      : logi [1:56] NA NA NA NA NA NA ...
 $ rem_adicionales_del_mes_no_inc_en_rem_bruta                      : logi [1:56] NA NA NA NA NA NA ...
 $ remuneracion_bonos_incentivos_del_mes_inc_en_rem_bruta           : chr [1:56] "$ 0" "$ 0" "$ 0" "$ 0" ...
 $ derecho_a_horas_extraordinarias                                  : chr [1:56] "Sí" "Sí" "No" "Sí" ...
 $ montos_y_horas_extraordinarias_diurnas_del_mes_inc_en_rem_bruta  : chr [1:56] "No tiene" "$ 33.608 : 14,00 hrs" "No tiene" "$ 35.864 : 13,00 hrs" ...
 $ montos_y_horas_extraordinarias_nocturnas_del_mes_inc_en_rem_bruta: chr [1:56] "$ 72.018 : 25,00 hrs" "$ 158.439 : 55,00 hrs" "No tiene" "$ 26.484 : 8,00 hrs" ...
 $ montos_y_horas_extraordinarias_festivas_del_mes_inc_en_rem_bruta : chr [1:56] "No tiene" "No tiene" "No tiene" "No tiene" ...
 $ fecha_inicio                                                     : chr [1:56] "20/06/2022" "22/06/2021" "01/01/2021" "22/05/2006" ...
 $ fecha_termino                                                    : chr [1:56] "31/12/2026" "31/12/2026" "31/12/2026" "31/12/2026" ...
 $ viaticos_del_mes_no_inc_en_rem_bruta                             : chr [1:56] "No informa" "No informa" "No informa" "No informa" ...
 $ observaciones                                                    : chr [1:56] "decreto nombramiento n° 2680 24/06/2022 jornada 22 horas semanales; decreto 2789 06/07/2022 nombramiento contra"| __truncated__ "decreto nombramiento 2735 29/06/2021; Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desd"| __truncated__ "decreto 2747 29/06/2021;Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desde 01/07/2022 h"| __truncated__ "decreto 2747 29/06/2021; DECRETO 48 11/01/2022; decreto 5911 30/12/2022; Decreto 349 23/01/2024; decreto 6359 2"| __truncated__ ...

Paso 5 · Revisar tipos de variables

str(Base_limpia)
tibble [56 × 21] (S3: tbl_df/tbl/data.frame)
 $ anio                                                             : int [1:56] 2026 2026 2026 2026 2026 2026 2026 2026 2026 2026 ...
 $ mes                                                              : chr [1:56] "Febrero" "Febrero" "Febrero" "Febrero" ...
 $ estamento                                                        : chr [1:56] "Auxiliar" "Auxiliar" "Técnico" "Auxiliar" ...
 $ nombre_completo                                                  : chr [1:56] "ALARCON SOTO, CRISTIAN" "ARANEDA LAGOS, ALEJANDRO GONZALO" "ARAVENA DIAZ, MATIAS NICOLAS" "AROSTICA MARTINEZ, EDGARDO ALAMIRO" ...
 $ cargo                                                            : chr [1:56] "OPERADOR PLANTA TRATAMIENTO AGUAS SERVIDAS EN SAN PATRICIO , DIR. ASEO ORNATO" "ENCARGADO ESTADIO CHERQUENCO DIDECO" "ENCARGADO CEMENTERIOS DIRECCIÓN MEDIO AMBIENTE ASEO Y ORNATO" "AUXILIAR DIR. OBRAS" ...
 $ grado_eus_o_jornada                                              : int [1:56] 20 20 17 18 20 15 17 20 17 17 ...
 $ formacion                                                        : chr [1:56] "Enseñanza Media, Estudios técnicos en instalaciones sanitarias" "Enseñanza Media" "Estudios Técnicos" "Estudios Medios" ...
 $ region                                                           : chr [1:56] "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" "Región de La Araucanía" ...
 $ asignaciones_especiales_del_mes_inc_en_rem_bruta                 : chr [1:56] "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(08)(09)(131)(132)(07)(66)(75)(76)(78)(37)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(08)(09)" "(03)(151)(149)(131)(132)(07)(66)(75)(76)(78)(37)(54)(33)(08)" ...
 $ rem_bruta                                                        : chr [1:56] "$ 1.322.269" "$ 1.094.529" "$ 1.485.546" "$ 1.514.638" ...
 $ rem_liquida                                                      : logi [1:56] NA NA NA NA NA NA ...
 $ rem_adicionales_del_mes_no_inc_en_rem_bruta                      : logi [1:56] NA NA NA NA NA NA ...
 $ remuneracion_bonos_incentivos_del_mes_inc_en_rem_bruta           : chr [1:56] "$ 0" "$ 0" "$ 0" "$ 0" ...
 $ derecho_a_horas_extraordinarias                                  : chr [1:56] "Sí" "Sí" "No" "Sí" ...
 $ montos_y_horas_extraordinarias_diurnas_del_mes_inc_en_rem_bruta  : chr [1:56] "No tiene" "$ 33.608 : 14,00 hrs" "No tiene" "$ 35.864 : 13,00 hrs" ...
 $ montos_y_horas_extraordinarias_nocturnas_del_mes_inc_en_rem_bruta: chr [1:56] "$ 72.018 : 25,00 hrs" "$ 158.439 : 55,00 hrs" "No tiene" "$ 26.484 : 8,00 hrs" ...
 $ montos_y_horas_extraordinarias_festivas_del_mes_inc_en_rem_bruta : chr [1:56] "No tiene" "No tiene" "No tiene" "No tiene" ...
 $ fecha_inicio                                                     : chr [1:56] "20/06/2022" "22/06/2021" "01/01/2021" "22/05/2006" ...
 $ fecha_termino                                                    : chr [1:56] "31/12/2026" "31/12/2026" "31/12/2026" "31/12/2026" ...
 $ viaticos_del_mes_no_inc_en_rem_bruta                             : chr [1:56] "No informa" "No informa" "No informa" "No informa" ...
 $ observaciones                                                    : chr [1:56] "decreto nombramiento n° 2680 24/06/2022 jornada 22 horas semanales; decreto 2789 06/07/2022 nombramiento contra"| __truncated__ "decreto nombramiento 2735 29/06/2021; Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desd"| __truncated__ "decreto 2747 29/06/2021;Decreto 50 11/01/2022; decreto 2789 06/07/2022 nombramiento contrata desde 01/07/2022 h"| __truncated__ "decreto 2747 29/06/2021; DECRETO 48 11/01/2022; decreto 5911 30/12/2022; Decreto 349 23/01/2024; decreto 6359 2"| __truncated__ ...

Tipos que nos interesan especialmente

  • estamento: texto o factor
  • rem_bruta: numérica
  • rem_liquida: numérica
  • fecha_inicio: fecha
  • fecha_termino: fecha

Paso 6 · Revisar valores de remuneración

head(Base_limpia$rem_bruta)
[1] "$ 1.322.269" "$ 1.094.529" "$ 1.485.546" "$ 1.514.638" "$ 1.278.435"
[6] "$ 1.735.627"

Problema frecuente

Las remuneraciones suelen venir como texto por:

  • puntos de miles
  • comas
  • espacios
  • símbolos
  • palabras como “Sin dato”

Si hay textos tipo “Sin dato”, primero convertir a NA

Base_limpia <- Base_limpia |>
  mutate(
    rem_bruta = na_if(rem_bruta, "Sin dato"),
    rem_liquida = na_if(rem_liquida, "Sin dato")
  )

Limpiar y convertir remuneraciones

Base_limpia <- Base_limpia |>
  mutate(
    rem_bruta = str_replace_all(rem_bruta, fixed("$"), ""),
    rem_bruta = str_replace_all(rem_bruta, "\\.", ""),
    rem_bruta = str_replace_all(rem_bruta, ",", "."),
    rem_bruta = str_trim(rem_bruta),
    rem_bruta = as.numeric(rem_bruta)
  )

Verificar resultado

class(Base_limpia$rem_bruta)
[1] "numeric"
summary(Base_limpia$rem_bruta)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 820090 1321172 1487142 1696017 1877888 3494400 

Paso 7 · Revisar fechas

head(Base_limpia$fecha_inicio)
[1] "20/06/2022" "22/06/2021" "01/01/2021" "22/05/2006" "14/12/2017"
[6] "15/03/2015"
head(Base_limpia$fecha_termino)
[1] "31/12/2026" "31/12/2026" "31/12/2026" "31/12/2026" "31/12/2026"
[6] "31/12/2026"
class(Base_limpia$fecha_inicio)
[1] "character"
class(Base_limpia$fecha_termino)
[1] "character"

Convertir fechas

Base_limpia <- Base_limpia |>
  mutate(
    fecha_inicio = dmy(fecha_inicio),
    fecha_termino = dmy(fecha_termino)
  )

Verificar fechas

class(Base_limpia$fecha_inicio)
[1] "Date"
class(Base_limpia$fecha_termino)
[1] "Date"

Paso 8 · Revisar missing

colSums(is.na(Base_limpia))
                                                             anio 
                                                                0 
                                                              mes 
                                                                0 
                                                        estamento 
                                                                0 
                                                  nombre_completo 
                                                                0 
                                                            cargo 
                                                                0 
                                              grado_eus_o_jornada 
                                                                0 
                                                        formacion 
                                                                0 
                                                           region 
                                                                0 
                 asignaciones_especiales_del_mes_inc_en_rem_bruta 
                                                                0 
                                                        rem_bruta 
                                                                0 
                                                      rem_liquida 
                                                               56 
                      rem_adicionales_del_mes_no_inc_en_rem_bruta 
                                                               56 
           remuneracion_bonos_incentivos_del_mes_inc_en_rem_bruta 
                                                                0 
                                  derecho_a_horas_extraordinarias 
                                                                0 
  montos_y_horas_extraordinarias_diurnas_del_mes_inc_en_rem_bruta 
                                                                0 
montos_y_horas_extraordinarias_nocturnas_del_mes_inc_en_rem_bruta 
                                                                0 
 montos_y_horas_extraordinarias_festivas_del_mes_inc_en_rem_bruta 
                                                                0 
                                                     fecha_inicio 
                                                                0 
                                                    fecha_termino 
                                                                0 
                             viaticos_del_mes_no_inc_en_rem_bruta 
                                                                0 
                                                    observaciones 
                                                                0 

Missing en variables clave

sum(is.na(Base_limpia$rem_bruta))
[1] 0
sum(is.na(Base_limpia$fecha_inicio))
[1] 0
sum(is.na(Base_limpia$fecha_termino))
[1] 0
sum(is.na(Base_limpia$estamento))
[1] 0

Paso 9 · Estandarizar categorías

unique(Base_limpia$estamento)
[1] "Auxiliar"       "Técnico"        "Administrativo" "Profesional"   

Generar una categoría simple

Base_limpia <- Base_limpia |>
  mutate(
    tramo_remuneracion = case_when(
      rem_bruta < 500000 ~ "Baja",
      rem_bruta >= 500000 & rem_bruta < 1000000 ~ "Media",
      rem_bruta >= 1000000 ~ "Alta",
      TRUE ~ NA_character_
    )
  )

table(Base_limpia$tramo_remuneración)
< table of extent 0 >

Otra variable útil

Base_limpia <- Base_limpia |>
  mutate(
    contrato_vigente = if_else(is.na(fecha_termino), 1, 0)
  )

Paso 10 · Eliminar variables si no se usarán todavía

Base_limpia <- Base_limpia |>
  select(-observaciones)

O conservar solo lo más importante

Base_limpia <- Base_limpia |>
  select(anio, mes, nombre_completo, estamento, cargo, rem_bruta, rem_liquida, fecha_inicio, fecha_termino, everything())

Paso 11 · Revisar duplicados

Base_limpia |>
  duplicated() |>
  sum()

Eliminar duplicados si corresponde

Base_limpia <- Base_limpia |>
  distinct()

Paso 12 · Guardar la base limpia

saveRDS(Base_limpia, "clean_muni.rds")

Actividad del laboratorio

Parte 1

Identifiquen al menos 4 problemas de calidad del dato.

Parte 2

Corrijan esos problemas con código.

Parte 3

Guarden una versión limpia de la base.

Parte 4

Escriban una bitácora con 5 decisiones de limpieza.

Formato sugerido de la bitácora

Para cada decisión:

  1. Problema detectado
  2. Cambio realizado
  3. Justificación

Ejemplo de bitácora

  • Se aplicó clean_names() para estandarizar los nombres de variables.
  • Se renombraron variables largas para facilitar el trabajo posterior.
  • Se transformó rem_bruta desde texto a numérico.
  • Se transformó fecha_inicio a formato fecha.
  • Se revisaron y contabilizaron los missing en variables clave.

Script base resumido

library(dplyr)
library(tidyr)
library(stringr)
library(lubridate)
library(janitor)
library(skimr)

Base <- readRDS("datos.rds")

Base <- Base |>
  clean_names()

Base_limpia <- Base |>
  select(
    ano,
    mes,
    estamento,
    nombre_completo,
    cargo_o_funcion,
    grado_eus_o_jornada,
    calificacion_profesional_o_formacion,
    region,
    remuneracion_bruta_del_mes_incluye_bonos_e_incentivos_asig_especiales_horas_extras,
    remuneracion_liquida_del_mes,
    fecha_de_inicio_dd_mm_aa,
    fecha_de_termino_dd_mm_aa,
    observaciones
  ) |>
  rename(
    anio = ano,
    cargo = cargo_o_funcion,
    formacion = calificacion_profesional_o_formacion,
    rem_bruta = remuneracion_bruta_del_mes_incluye_bonos_e_incentivos_asig_especiales_horas_extras,
    rem_liquida = remuneracion_liquida_del_mes,
    fecha_inicio = fecha_de_inicio_dd_mm_aa,
    fecha_termino = fecha_de_termino_dd_mm_aa
  ) |>
  mutate(
    estamento = str_trim(estamento),
    estamento = str_to_title(estamento),
    rem_bruta = na_if(rem_bruta, "Sin dato"),
    rem_liquida = na_if(rem_liquida, "Sin dato"),
    rem_bruta = str_replace_all(rem_bruta, "\\.", ""),
    rem_bruta = str_replace_all(rem_bruta, ",", "."),
    rem_bruta = str_trim(rem_bruta),
    rem_bruta = as.numeric(rem_bruta),
    rem_liquida = str_replace_all(rem_liquida, "\\.", ""),
    rem_liquida = str_replace_all(rem_liquida, ",", "."),
    rem_liquida = str_trim(rem_liquida),
    rem_liquida = as.numeric(rem_liquida),
    fecha_inicio = dmy(fecha_inicio),
    fecha_termino = dmy(fecha_termino),
    tramo_remuneracion = case_when(
      rem_bruta < 500000 ~ "Baja",
      rem_bruta >= 500000 & rem_bruta < 1000000 ~ "Media",
      rem_bruta >= 1000000 ~ "Alta",
      TRUE ~ NA_character_
    )
  ) |>
  distinct()

saveRDS(Base_limpia, "clean_muni.rds")

Cierre de la sesión

Hoy no buscamos cerrar un análisis, sino dejar la base en condiciones mínimas de trabajo.

La limpieza no es una tarea secundaria: es parte central del análisis de datos.

Tarea de la semana

Entregar:

  • clean_muni.rds
  • script de limpieza
  • bitácora con 5 decisiones de limpieza

Preguntas de salida

  • ¿Qué problema apareció con más frecuencia?
  • ¿Qué variable fue más difícil de limpiar?
  • ¿Qué decisión de limpieza fue más importante?
  • ¿Qué tendrían que modificar si trabajaran con otro mes?