1 # Fase 1: Preparación y diagnóstico de datos (Data Understanding)

2 Carga, impieza y exportación final

# INSTALACIÓN Y CARGA DE PAQUETES
options(repos = c(CRAN = "https://cloud.r-project.org"))

# MANTENER LAS FILAS Y EVITAR ERRORES FUTUROS
Sys.setlocale("LC_CTYPE", "Spanish_Spain.1252")
[1] "Spanish_Spain.1252"
# Instalar (solo la primera vez)
install.packages('tidyverse') # dplyr 1.1.4, readr 2.1.5, forcats 1.0.0, stringr 1.5.2, ggplot2 4.0.0, tibble 3.3.0, lubridate 1.9.4, tidyr 1.3.1, purrr 1.1.0 
package 'tidyverse' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('mice')
package 'mice' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('VIM')
package 'VIM' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('tidyr')
package 'tidyr' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('writexl')
package 'writexl' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('MASS')
package 'MASS' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('openxlsx')
package 'openxlsx' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages

3 CARGAR LIBRERIAS

# Cargar librerías
library(tidyverse)
library(mice)
library(VIM)
library(tidyr)
library(readr)
library(writexl)
library(MASS, exclude = "select") # evita conflicto con dplyr::select
library(openxlsx)

4 CARGA DE DATOS Y VARIABLES PARA COMPLETAR DB IMPUTADAS

saber_11_22_1 <- read_csv("saber_11_2022_1.csv")

glimpse(saber_11_22_1)
Rows: 532,789
Columns: 53
$ COLE_BILINGUE                 <chr> "No", "No", "No", "No", "No", "No", "No"~
$ FAMI_TIENEAUTOMOVIL           <chr> "No", "No", "No", "No", "No", "Si", "No"~
$ FAMI_TIENECOMPUTADOR          <chr> "No", "No", "No", "No", "No", "Si", "No"~
$ FAMI_TIENEINTERNET            <chr> "No", "Si", "No", "Si", "No", "Si", "No"~
$ FAMI_TIENELAVADORA            <chr> "Si", "No", "Si", "Si", "Si", "Si", "No"~
$ COLE_SEDE_PRINCIPAL           <chr> "Si", "Si", "Si", "Si", "Si", "Si", "Si"~
$ ESTU_GENERO                   <chr> "F", "M", "F", "F", "F", "M", "F", "F", ~
$ COLE_NATURALEZA               <chr> "Oficial", "Oficial", "Oficial", "Oficia~
$ COLE_AREA_UBICACION           <chr> "Urbano", "Urbano", "Urbano", "Urbano", ~
$ COLE_CARACTER                 <chr> "Tecnico/Academico", "Tecnico/Academico"~
$ COLE_CALENDARIO               <chr> "A", "A", "A", "A", "A", "A", "A", "A", ~
$ COLE_JORNADA                  <chr> "Unica", "Unica", "Unica", "Unica", "Mañ~
$ COLE_GENERO                   <chr> "Mixto", "Mixto", "Mixto", "Mixto", "Mix~
$ COLE_DEPTO_UBICACION          <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ ESTU_DEPTO_RESIDE             <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ FAMI_EDUCACIONMADRE           <chr> "Primaria Incompleta", "Secundaria (bach~
$ FAMI_EDUCACIONPADRE           <chr> "Primaria Incompleta", "Primaria Incompl~
$ FAMI_CUARTOSHOGAR             <chr> "4", "1", "2", "2", "2", "3", "2", "2", ~
$ FAMI_PERSONASHOGAR            <chr> "5 a 6", "3 a 4", "7 a 8", "3 a 4", "5 a~
$ DESEMP_INGLES                 <chr> "A2", "A-", "A-", "A1", "A-", "A1", "A-"~
$ PUNT_INGLES                   <dbl> 60, 43, 45, 56, 37, 56, 38, 45, 64, 59, ~
$ PERIODO                       <dbl> 20224, 20224, 20224, 20224, 20224, 20224~
$ COLE_COD_DANE_ESTABLECIMIENTO <dbl> 183247000272, 176001001702, 105001001121~
$ COLE_COD_DANE_SEDE            <dbl> 183247000272, 176001001702, 105001001121~
$ COLE_COD_DEPTO_UBICACION      <chr> "18", "76", "05", "08", "13", "11", "44"~
$ COLE_COD_MCPIO_UBICACION      <chr> "18247", "76001", "05001", "08296", "136~
$ COLE_CODIGO_ICFES             <dbl> 671586, 731349, 719096, 708081, 4663, 71~
$ COLE_MCPIO_UBICACION          <chr> "El Doncello", "Cali", "Medellin", "Gala~
$ COLE_NOMBRE_ESTABLECIMIENTO   <chr> "I.E. Jorge Abel Molina", "Institucion E~
$ COLE_NOMBRE_SEDE              <chr> "Jorge Abel Molina", "Institucion Educat~
$ ESTU_TIPODOCUMENTO            <chr> "TI", "TI", "TI", "CR", "CC", "TI", "TI"~
$ ESTU_CONSECUTIVO              <chr> "sb11202240536228", "sb11202240218341", ~
$ ESTU_COD_DEPTO_PRESENTACION   <chr> "18", "76", "05", "08", "13", "11", "44"~
$ ESTU_COD_MCPIO_PRESENTACION   <chr> "18247", "76001", "05001", "08078", "136~
$ ESTU_COD_RESIDE_DEPTO         <chr> "18", "76", "05", "08", "13", "11", "44"~
$ ESTU_COD_RESIDE_MCPIO         <chr> "18247", "76001", "05001", "08296", "136~
$ ESTU_DEPTO_PRESENTACION       <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ ESTU_MCPIO_PRESENTACION       <chr> "El Doncello", "Cali", "Medellin", "Bara~
$ ESTU_MCPIO_RESIDE             <chr> "El Doncello", "Cali", "Medellin", "Gala~
$ ESTU_ESTADOINVESTIGACION      <chr> "publicar", "publicar", "publicar", "pub~
$ ESTU_ESTUDIANTE               <chr> "estudiante", "estudiante", "estudiante"~
$ ESTU_FECHANACIMIENTO          <date> 2004-12-30, 2004-12-30, 2004-12-30, 200~
$ ESTU_NACIONALIDAD             <chr> "Colombia", "Colombia", "Colombia", "Col~
$ ESTU_PAIS_RESIDE              <chr> "Colombia", "Colombia", "Colombia", "Col~
$ ESTU_PRIVADO_LIBERTAD         <chr> "No", "No", "No", "No", "No", "No", "No"~
$ EDAD                          <dbl> 18, 18, 18, 19, 19, 17, 17, 18, 17, 17, ~
$ FAMI_ESTRATOVIVIENDA          <dbl> 2, 2, 1, 2, 2, 3, 1, 1, 4, 1, 2, 1, 2, 3~
$ PUNT_MATEMATICAS              <dbl> 44, 41, 30, 52, 30, 65, 34, 26, 57, 49, ~
$ PUNT_SOCIALES_CIUDADANAS      <dbl> 50, 29, 42, 43, 32, 58, 34, 40, 40, 36, ~
$ PUNT_C_NATURALES              <dbl> 41, 42, 36, 48, 35, 60, 35, 43, 56, 36, ~
$ PUNT_LECTURA_CRITICA          <dbl> 50, 44, 53, 51, 32, 61, 43, 48, 63, 49, ~
$ PUNT_GLOBAL                   <dbl> 237, 197, 203, 245, 163, 303, 183, 198, ~
$ FECHA_EXAMEN_REF              <date> 2022-12-31, 2022-12-31, 2022-12-31, 202~

5 1_Auditoría del dataset saber_11_2022_1:

Revisar duplicados, valores nulos, incoherencias (fechas, edades, etc.).

1.1_Verificación de duplicados

# Total de filas duplicadas
duplicados <- saber_11_22_1 %>%
  duplicated() %>%
  sum()

cat("Filas duplicadas:", duplicados, "\n")
Filas duplicadas: 0 
# Extraer los registros duplicados (si los hay)
duplicados_df <- saber_11_22_1 %>%
  filter(duplicated(.) | duplicated(., fromLast = TRUE))

1.2_Valores nulos o vacíos

# Conteo de nulos por variable
na_counts <- colSums(is.na(saber_11_22_1))
na_porcentaje <- round((na_counts / nrow(saber_11_22_1)) * 100, 2)

# Crear tabla resumen ordenada
na_resumen <- tibble(
  Variable = names(na_counts),
  Nulos = na_counts,
  Porcentaje = na_porcentaje
) %>% arrange(desc(Porcentaje))

print(na_resumen)
# A tibble: 53 x 3
   Variable             Nulos Porcentaje
   <chr>                <dbl>      <dbl>
 1 COLE_BILINGUE            0          0
 2 FAMI_TIENEAUTOMOVIL      0          0
 3 FAMI_TIENECOMPUTADOR     0          0
 4 FAMI_TIENEINTERNET       0          0
 5 FAMI_TIENELAVADORA       0          0
 6 COLE_SEDE_PRINCIPAL      0          0
 7 ESTU_GENERO              0          0
 8 COLE_NATURALEZA          0          0
 9 COLE_AREA_UBICACION      0          0
10 COLE_CARACTER            0          0
# i 43 more rows

1.3_Detección de incoherencias (fechas y edades)

# Verificar rango de fechas de nacimiento
summary(saber_11_22_1$ESTU_FECHANACIMIENTO)
        Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
"1900-12-30" "2004-12-30" "2005-12-30" "2005-05-28" "2005-12-30" "2055-12-31" 
# Calcular edad a partir de la fecha del examen
saber_11_22_1 <- saber_11_22_1 %>%
  mutate(EDAD_CALCULADA = as.numeric(difftime(FECHA_EXAMEN_REF, ESTU_FECHANACIMIENTO, units = "days")) / 365.25)

# Comparar edad calculada vs registrada
saber_11_22_1 <- saber_11_22_1 %>%
  mutate(DIF_EDAD = abs(EDAD - round(EDAD_CALCULADA, 0)))

# Registros inconsistentes (diferencia > 1 año)
inconsistentes_edad <- saber_11_22_1 %>%
  filter(DIF_EDAD > 1)

cat("Registros con incoherencias de edad:", nrow(inconsistentes_edad), "\n")
Registros con incoherencias de edad: 0 

1.4_Validación de códigos y geografía

# Comparar nombres y códigos de departamentos
verif_depto <- saber_11_22_1 %>%
  select(COLE_DEPTO_UBICACION, COLE_COD_DEPTO_UBICACION) %>%
  distinct() %>%
  arrange(COLE_DEPTO_UBICACION)

print(verif_depto, n = 33)
# A tibble: 33 x 2
   COLE_DEPTO_UBICACION     COLE_COD_DEPTO_UBICACION
   <chr>                    <chr>                   
 1 Amazonas                 91                      
 2 Antioquia                05                      
 3 Arauca                   81                      
 4 Atlantico                08                      
 5 Bogota D.C.              11                      
 6 Bolivar                  13                      
 7 Boyaca                   15                      
 8 Caldas                   17                      
 9 Caqueta                  18                      
10 Casanare                 85                      
11 Cauca                    19                      
12 Cesar                    20                      
13 Choco                    27                      
14 Cordoba                  23                      
15 Cundinamarca             25                      
16 Guainia                  94                      
17 Guaviare                 95                      
18 Huila                    41                      
19 La Guajira               44                      
20 Magdalena                47                      
21 Meta                     50                      
22 Narino                   52                      
23 Norte de Santander       54                      
24 Putumayo                 86                      
25 Quindio                  63                      
26 Risaralda                66                      
27 San Andres y Providencia 88                      
28 Santander                68                      
29 Sucre                    70                      
30 Tolima                   73                      
31 Valle                    76                      
32 Vaupes                   97                      
33 Vichada                  99                      

1.5_Reporte de resultados generales

# Resumen general
resumen_auditoria <- tibble(
  Total_filas = nrow(saber_11_22_1),
  Total_columnas = ncol(saber_11_22_1),
  Filas_duplicadas = duplicados,
  Variables_con_nulos = sum(na_counts > 0),
  Registros_incoherentes_edad = nrow(inconsistentes_edad)
)

print(resumen_auditoria)
# A tibble: 1 x 5
  Total_filas Total_columnas Filas_duplicadas Variables_con_nulos
        <int>          <int>            <int>               <int>
1      532789             55                0                   0
# i 1 more variable: Registros_incoherentes_edad <int>

1.6_Verificación de municipios

# Verificar municipios únicos y sus códigos
verif_mcpio <- saber_11_22_1 %>%
  select(COLE_MCPIO_UBICACION, COLE_COD_MCPIO_UBICACION) %>%
  distinct() %>%
  arrange(COLE_MCPIO_UBICACION)

# Mostrar número total de municipios únicos
cat("Número total de municipios únicos:", nrow(verif_mcpio), "\n")
Número total de municipios únicos: 1114 
# Revisar valores nulos
sum(is.na(verif_mcpio$COLE_MCPIO_UBICACION))
[1] 0
sum(is.na(verif_mcpio$COLE_COD_MCPIO_UBICACION))
[1] 0
# Mostrar primeros registros para inspección
head(verif_mcpio)
# A tibble: 6 x 2
  COLE_MCPIO_UBICACION COLE_COD_MCPIO_UBICACION
  <chr>                <chr>                   
1 Abejorral            05002                   
2 Abrego               54003                   
3 Abriaqui             05004                   
4 Acacias              50006                   
5 Acandi               27006                   
6 Acevedo              41006                   

1.7_Detección de posibles inconsistencias (opcional, comparación por longitud del código)

# Verificar que los códigos tengan 5 dígitos (formato DANE)
inconsistencias_mcpio <- verif_mcpio %>%
  filter(nchar(COLE_COD_MCPIO_UBICACION) != 5)

cat("Municipios con códigos incorrectos:", nrow(inconsistencias_mcpio), "\n")
Municipios con códigos incorrectos: 0 

1.8_Verificación de establecimientos y sedes

# Validar códigos DANE de establecimientos
verif_est <- saber_11_22_1 %>%
  select(COLE_NOMBRE_ESTABLECIMIENTO, COLE_COD_DANE_ESTABLECIMIENTO) %>%
  distinct() %>%
  arrange(COLE_NOMBRE_ESTABLECIMIENTO)

# Validar códigos DANE de sedes
verif_sede <- saber_11_22_1 %>%
  select(COLE_NOMBRE_SEDE, COLE_COD_DANE_SEDE) %>%
  distinct() %>%
  arrange(COLE_NOMBRE_SEDE)

# Contar posibles nulos
cat("Nulos en COLE_COD_DANE_ESTABLECIMIENTO:", sum(is.na(verif_est$COLE_COD_DANE_ESTABLECIMIENTO)), "\n")
Nulos en COLE_COD_DANE_ESTABLECIMIENTO: 0 
cat("Nulos en COLE_COD_DANE_SEDE:", sum(is.na(verif_sede$COLE_COD_DANE_SEDE)), "\n")
Nulos en COLE_COD_DANE_SEDE: 0 

1.9_Resumen general de validación geográfica e institucional

resumen_validacion <- tibble(
  Total_municipios = nrow(verif_mcpio),
  Codigos_incorrectos_municipios = nrow(inconsistencias_mcpio),
  Nulos_municipios_nombre = sum(is.na(verif_mcpio$COLE_MCPIO_UBICACION)),
  Nulos_municipios_codigo = sum(is.na(verif_mcpio$COLE_COD_MCPIO_UBICACION)),
  Nulos_cod_establecimiento = sum(is.na(verif_est$COLE_COD_DANE_ESTABLECIMIENTO)),
  Nulos_cod_sede = sum(is.na(verif_sede$COLE_COD_DANE_SEDE))
)

print(resumen_validacion)
# A tibble: 1 x 6
  Total_municipios Codigos_incorrectos_municipios Nulos_municipios_nombre
             <int>                          <int>                   <int>
1             1114                              0                       0
# i 3 more variables: Nulos_municipios_codigo <int>,
#   Nulos_cod_establecimiento <int>, Nulos_cod_sede <int>

2_Verificación institucional avanzada

2.1_Comprobar la relación entre establecimientos y sedes

# Verificar si cada sede pertenece a un solo establecimiento
relacion_est_sede <- saber_11_22_1 %>%
  select(COLE_COD_DANE_ESTABLECIMIENTO, COLE_COD_DANE_SEDE) %>%
  distinct() %>%
  group_by(COLE_COD_DANE_SEDE) %>%
  summarise(
    n_establecimientos = n_distinct(COLE_COD_DANE_ESTABLECIMIENTO)
  ) %>%
  ungroup() %>%
  arrange(desc(n_establecimientos))

# Mostrar posibles sedes con más de un establecimiento (inconsistencia)
inconsistencias_sede <- relacion_est_sede %>%
  filter(n_establecimientos > 1)

cat("Sedes asignadas a más de un establecimiento:", nrow(inconsistencias_sede), "\n")
Sedes asignadas a más de un establecimiento: 0 

2.2_Validar la cantidad de sedes por establecimiento

# Contar cuántas sedes tiene cada establecimiento
sedes_por_est <- saber_11_22_1 %>%
  select(COLE_COD_DANE_ESTABLECIMIENTO, COLE_COD_DANE_SEDE) %>%
  distinct() %>%
  group_by(COLE_COD_DANE_ESTABLECIMIENTO) %>%
  summarise(
    n_sedes = n_distinct(COLE_COD_DANE_SEDE)
  ) %>%
  ungroup() %>%
  arrange(desc(n_sedes))

# Estadísticas descriptivas
summary(sedes_por_est$n_sedes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.098   1.000  13.000 

2.3_Comprobación de correspondencia nombre–código

# Validar correspondencia entre nombre y código DANE del establecimiento
inconsistencias_est <- saber_11_22_1 %>%
  select(COLE_NOMBRE_ESTABLECIMIENTO, COLE_COD_DANE_ESTABLECIMIENTO) %>%
  distinct() %>%
  group_by(COLE_COD_DANE_ESTABLECIMIENTO) %>%
  summarise(nombres_distintos = n_distinct(COLE_NOMBRE_ESTABLECIMIENTO)) %>%
  filter(nombres_distintos > 1)

cat("Establecimientos con más de un nombre asociado:", nrow(inconsistencias_est), "\n")
Establecimientos con más de un nombre asociado: 0 
# Validar correspondencia entre nombre y código DANE de la sede
inconsistencias_sede_nombre <- saber_11_22_1 %>%
  select(COLE_NOMBRE_SEDE, COLE_COD_DANE_SEDE) %>%
  distinct() %>%
  group_by(COLE_COD_DANE_SEDE) %>%
  summarise(nombres_distintos = n_distinct(COLE_NOMBRE_SEDE)) %>%
  filter(nombres_distintos > 1)

cat("Sedes con más de un nombre asociado:", nrow(inconsistencias_sede_nombre), "\n")
Sedes con más de un nombre asociado: 0 

2.4_Resumen institucional general

resumen_institucional <- tibble(
  Sedes_con_varios_establecimientos = nrow(inconsistencias_sede),
  Establecimientos_con_varios_nombres = nrow(inconsistencias_est),
  Sedes_con_varios_nombres = nrow(inconsistencias_sede_nombre),
  Total_establecimientos = n_distinct(saber_11_22_1$COLE_COD_DANE_ESTABLECIMIENTO),
  Total_sedes = n_distinct(saber_11_22_1$COLE_COD_DANE_SEDE)
)

print(resumen_institucional)
# A tibble: 1 x 5
  Sedes_con_varios_establecimien~1 Establecimientos_con~2 Sedes_con_varios_nom~3
                             <int>                  <int>                  <int>
1                                0                      0                      0
# i abbreviated names: 1: Sedes_con_varios_establecimientos,
#   2: Establecimientos_con_varios_nombres, 3: Sedes_con_varios_nombres
# i 2 more variables: Total_establecimientos <int>, Total_sedes <int>

CONCLUSIONES

Cada establecimiento (código de 12 dígitos) agrupa una o varias sedes (también con código DANE único).

No hay ninguna sede duplicada ni asociada a más de un establecimiento.

No existen divergencias de nombres, lo que indica consistencia nominal y administrativa total.

El resumen estadístico summary(sedes_por_est$n_sedes) muestra:

Mediana = 1 → la mayoría de los colegios tienen una sola sede.

Máximo = 13 → hay instituciones grandes (como colegios distritales o rurales integrados) que agrupan varias sedes, lo cual es esperado y correcto.

Validación Resultado
Departamentos 33 correctos
Municipios 1,114 válidos
Establecimientos y sedes Sin inconsistencias
Nombres–Códigos DANE Coinciden 1:1

3. Diagnóstico general y consolidación de auditoría

3.1_Cargar librerías

install.packages('psych')
package 'psych' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
install.packages('fs')
package 'fs' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
library(visdat)
library(naniar)
library(psych)
library(fs)

**3.2_ _Análisis de valores faltantes (missingness)**

Calcular número y porcentaje de nulos por variable

missing_summary <- saber_11_22_1 %>%
  summarise(across(everything(), ~sum(is.na(.)))) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Nulos") %>%
  mutate(Porcentaje = round((Nulos / nrow(saber_11_22_1)) * 100, 2)) %>%
  arrange(desc(Porcentaje))

missing_summary
# A tibble: 55 x 3
   Variable             Nulos Porcentaje
   <chr>                <int>      <dbl>
 1 COLE_BILINGUE            0          0
 2 FAMI_TIENEAUTOMOVIL      0          0
 3 FAMI_TIENECOMPUTADOR     0          0
 4 FAMI_TIENEINTERNET       0          0
 5 FAMI_TIENELAVADORA       0          0
 6 COLE_SEDE_PRINCIPAL      0          0
 7 ESTU_GENERO              0          0
 8 COLE_NATURALEZA          0          0
 9 COLE_AREA_UBICACION      0          0
10 COLE_CARACTER            0          0
# i 45 more rows

3.3_Estadísticas descriptivas

# Variables numéricas
desc_num <- saber_11_22_1 %>%
  select(where(is.numeric)) %>%
  psych::describe() %>%
  as_tibble(rownames = "Variable")

# Variables categóricas
desc_cat <- saber_11_22_1 %>%
  select(where(is.character)) %>%
  summarise(across(everything(), ~n_distinct(.))) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Categorias")

3.4_Resumen general del diagnóstico

resumen_diagnostico <- tibble(
  Total_filas = nrow(saber_11_22_1),
  Total_columnas = ncol(saber_11_22_1),
  Variables_con_nulos = sum(missing_summary$Nulos > 0),
  Promedio_porcentaje_nulos = mean(missing_summary$Porcentaje),
  Variables_numericas = ncol(select(saber_11_22_1, where(is.numeric))),
  Variables_categoricas = ncol(select(saber_11_22_1, where(is.character)))
)

print(resumen_diagnostico)
# A tibble: 1 x 6
  Total_filas Total_columnas Variables_con_nulos Promedio_porcentaje_nulos
        <int>          <int>               <int>                     <dbl>
1      532789             55                   0                         0
# i 2 more variables: Variables_numericas <int>, Variables_categoricas <int>

CONCLUSIONES

Interpretación técnica

Integridad total: el dataset no requiere imputación adicional.

Coherencia estructural: los conteos coinciden con la estructura oficial de los datos Saber 11 (2022).

Tipos de variables correctamente identificados: 14 numéricas + 39 categóricas = 53 variables activas, más 2 de tipo fecha (ESTU_FECHANACIMIENTO, FECHA_EXAMEN_REF) que R suele clasificar aparte.

Sin pérdida de información: durante los pasos de limpieza, validación y auditoría no se eliminaron filas ni columnas.

3.5 Crear carpeta final de salida

dir_create("auditoria_datos/diagnostico_general")

3.6_Consolidar todo en un solo archivo Excel maestro

Este documento incluirá todos los resultados previos:

Validaciones geográficas

Validaciones institucionales

Missingness

Estadísticas descriptivas

Resumen global del diagnóstico

# Crear libro Excel maestro
wb_master <- createWorkbook()

# Hojas previas de auditoría (si ya existen)
addWorksheet(wb_master, "Resumen_Geografica")
writeData(wb_master, "Resumen_Geografica", resumen_validacion)

addWorksheet(wb_master, "Resumen_Institucional")
writeData(wb_master, "Resumen_Institucional", resumen_institucional)

# Nuevas hojas de diagnóstico
addWorksheet(wb_master, "Resumen_Diagnostico")
addWorksheet(wb_master, "Missingness")
addWorksheet(wb_master, "Descriptivas_Numericas")
addWorksheet(wb_master, "Descriptivas_Categoricas")

# Escribir los nuevos resultados
writeData(wb_master, "Resumen_Diagnostico", resumen_diagnostico)
writeData(wb_master, "Missingness", missing_summary)
writeData(wb_master, "Descriptivas_Numericas", desc_num)
writeData(wb_master, "Descriptivas_Categoricas", desc_cat)

# Guardar el libro maestro
saveWorkbook(wb_master, "auditoria_datos/diagnostico_general/diagnostico_saber11_2022.xlsx", overwrite = TRUE)

cat("Archivo Excel maestro guardado en auditoria_datos/diagnostico_general/diagnostico_saber11_2022.xlsx\n")
Archivo Excel maestro guardado en auditoria_datos/diagnostico_general/diagnostico_saber11_2022.xlsx

3.7_Visualizaciones opcionales

Visualizar solo una muestra representativa de tus datos (por ejemplo, 5.000 registros):

library(visdat)

# Crear una muestra representativa
saber_11_22_1_sample <- saber_11_22_1 %>% 
  dplyr::slice_sample(n = 5000)  # o usa prop = 0.01 para 1% de la base

# Visualizar valores faltantes
vis_miss(saber_11_22_1_sample) +
  theme_minimal() +
  labs(title = "Mapa de valores faltantes - Muestra (Saber 11, 2022)",
       subtitle = "Visualización sobre una muestra de 5,000 registros")

Fase 2 — Creación de sub-bases por tipo

Dataset: saber_11_22_1

# --- 1. Definición de variables por tipo ---

num_vars <- c(
  "PUNT_INGLES", "PUNT_MATEMATICAS", "PUNT_SOCIALES_CIUDADANAS",
  "PUNT_C_NATURALES", "PUNT_LECTURA_CRITICA", "PUNT_GLOBAL",
  "EDAD", "EDAD_CALCULADA", "DIF_EDAD", "FAMI_ESTRATOVIVIENDA",
  "COLE_COD_DANE_ESTABLECIMIENTO", "COLE_COD_DANE_SEDE",
  "COLE_CODIGO_ICFES", "PERIODO"
)

ord_vars <- c(
  "FAMI_EDUCACIONMADRE", "FAMI_EDUCACIONPADRE",
  "FAMI_PERSONASHOGAR", "FAMI_CUARTOSHOGAR", "DESEMP_INGLES"
)

bin_vars <- c(
  "COLE_BILINGUE", "FAMI_TIENEAUTOMOVIL", "FAMI_TIENECOMPUTADOR",
  "FAMI_TIENEINTERNET", "FAMI_TIENELAVADORA",
  "COLE_SEDE_PRINCIPAL", "ESTU_PRIVADO_LIBERTAD"
)

geo_vars <- c(
  "COLE_DEPTO_UBICACION", "COLE_MCPIO_UBICACION",
  "COLE_COD_DEPTO_UBICACION", "COLE_COD_MCPIO_UBICACION",
  "ESTU_DEPTO_PRESENTACION", "ESTU_MCPIO_PRESENTACION",
  "ESTU_DEPTO_RESIDE", "ESTU_MCPIO_RESIDE",
  "ESTU_COD_DEPTO_PRESENTACION", "ESTU_COD_MCPIO_PRESENTACION",
  "ESTU_COD_RESIDE_DEPTO", "ESTU_COD_RESIDE_MCPIO",
  "FECHA_EXAMEN_REF", "ESTU_CONSECUTIVO"
)

# Las nominales son todas las demás
nom_vars <- setdiff(names(saber_11_22_1),
                    c(num_vars, ord_vars, bin_vars, geo_vars))

# --- 2. Crear las sub-bases según tipo ---
saber_11_22_1_num  <- saber_11_22_1 %>% select(all_of(num_vars))
saber_11_22_1_ord  <- saber_11_22_1 %>% select(all_of(ord_vars))
saber_11_22_1_bin  <- saber_11_22_1 %>% select(all_of(bin_vars))
saber_11_22_1_nom  <- saber_11_22_1 %>% select(all_of(nom_vars))
saber_11_22_1_geog <- saber_11_22_1 %>% select(all_of(geo_vars))

# --- 3. Exportar cada sub-base a CSV ---
write.csv(saber_11_22_1_num,  "saber_11_22_1_num.csv",  row.names = FALSE)
write.csv(saber_11_22_1_ord,  "saber_11_22_1_ord.csv",  row.names = FALSE)
write.csv(saber_11_22_1_bin,  "saber_11_22_1_bin.csv",  row.names = FALSE)
write.csv(saber_11_22_1_nom,  "saber_11_22_1_nom.csv",  row.names = FALSE)
write.csv(saber_11_22_1_geog, "saber_11_22_1_geog.csv", row.names = FALSE)

# --- 4. Confirmar creación de archivos ---
list.files(pattern = "saber_11_22_1_")
 [1] "cod_saber_11_22_1_bin.csv"  "cod_saber_11_22_1_geog.csv"
 [3] "cod_saber_11_22_1_nom.csv"  "cod_saber_11_22_1_num.csv" 
 [5] "cod_saber_11_22_1_ord.csv"  "saber_11_22_1_bin.csv"     
 [7] "saber_11_22_1_geog.csv"     "saber_11_22_1_nom.csv"     
 [9] "saber_11_22_1_num.csv"      "saber_11_22_1_ord.csv"     

6 CREACIÓN DE DICCIONARIO DE CODIFICACIÓN COMPLETO

# 1. Cargar los dataframes por tipo

cod_saber_11_22_1_bin  <- read_csv("saber_11_22_1_bin.csv",  show_col_types = FALSE)
cod_saber_11_22_1_geog <- read_csv("saber_11_22_1_geog.csv", show_col_types = FALSE)
cod_saber_11_22_1_nom  <- read_csv("saber_11_22_1_nom.csv",  show_col_types = FALSE)
cod_saber_11_22_1_num  <- read_csv("saber_11_22_1_num.csv",  show_col_types = FALSE)
cod_saber_11_22_1_ord  <- read_csv("saber_11_22_1_ord.csv",  show_col_types = FALSE)

# 2. Crear diccionario BINARIO

dicc_bin <- data.frame()
for (v in names(cod_saber_11_22_1_bin)) {
  niveles <- sort(unique(cod_saber_11_22_1_bin[[v]]))
  codigos <- seq_along(niveles)
  temp <- data.frame(
    Variable = v,
    Codigo = codigos,
    Categoria = as.character(niveles),
    Clase_R = class(cod_saber_11_22_1_bin[[v]])[1],
    Tipo = "Binaria",
    stringsAsFactors = FALSE
  )
  dicc_bin <- bind_rows(dicc_bin, temp)
}

# 3. Crear diccionario GEOGRÁFICO

dicc_geog <- data.frame()
for (v in names(cod_saber_11_22_1_geog)) {
  niveles <- sort(unique(cod_saber_11_22_1_geog[[v]]))
  codigos <- seq_along(niveles)
  temp <- data.frame(
    Variable = v,
    Codigo = codigos,
    Categoria = as.character(niveles),
    Clase_R = class(cod_saber_11_22_1_geog[[v]])[1],
    Tipo = "Geográfica",
    stringsAsFactors = FALSE
  )
  dicc_geog <- bind_rows(dicc_geog, temp)
}

# 4. Crear diccionario NOMINAL

dicc_nom <- data.frame()
for (v in names(cod_saber_11_22_1_nom)) {
  niveles <- sort(unique(cod_saber_11_22_1_nom[[v]]))
  codigos <- seq_along(niveles)
  temp <- data.frame(
    Variable = v,
    Codigo = codigos,
    Categoria = as.character(niveles),
    Clase_R = class(cod_saber_11_22_1_nom[[v]])[1],
    Tipo = "Nominal",
    stringsAsFactors = FALSE
  )
  dicc_nom <- bind_rows(dicc_nom, temp)
}

# 5. Crear diccionario NUMÉRICO

dicc_num <- data.frame()
for (v in names(cod_saber_11_22_1_num)) {
  niveles <- sort(unique(cod_saber_11_22_1_num[[v]]))
  codigos <- seq_along(niveles)
  temp <- data.frame(
    Variable = v,
    Codigo = codigos,
    Categoria = as.character(niveles),
    Clase_R = class(cod_saber_11_22_1_num[[v]])[1],
    Tipo = "Numérica",
    stringsAsFactors = FALSE
  )
  dicc_num <- bind_rows(dicc_num, temp)
}


# 6. Crear diccionario ORDINAL

dicc_ord <- data.frame()
for (v in names(cod_saber_11_22_1_ord)) {
  niveles <- sort(unique(cod_saber_11_22_1_ord[[v]]))
  codigos <- seq_along(niveles)
  temp <- data.frame(
    Variable = v,
    Codigo = codigos,
    Categoria = as.character(niveles),
    Clase_R = class(cod_saber_11_22_1_ord[[v]])[1],
    Tipo = "Ordinal",
    stringsAsFactors = FALSE
  )
  dicc_ord <- bind_rows(dicc_ord, temp)
}


# 7. Exportar a un solo archivo Excel con múltiples hojas

write_xlsx(
  list(
    "Binarias"    = dicc_bin,
    "Ordinales"   = dicc_ord,
    "Nominales"   = dicc_nom,
    "Numericas"   = dicc_num,
    "Geograficas" = dicc_geog
  ),
  path = "diccionario_codificacion_saber_11_22_1.xlsx"
)

print("Diccionario completo exportado con 5 hojas en Excel:")
[1] "Diccionario completo exportado con 5 hojas en Excel:"
print("diccionario_codificacion_saber_11_22_1.xlsx")
[1] "diccionario_codificacion_saber_11_22_1.xlsx"
# Exportar cada base individualmente en formato CSV

write_csv(cod_saber_11_22_1_bin,  "cod_saber_11_22_1_bin.csv")
write_csv(cod_saber_11_22_1_ord,  "cod_saber_11_22_1_ord.csv")
write_csv(cod_saber_11_22_1_nom,  "cod_saber_11_22_1_nom.csv")
write_csv(cod_saber_11_22_1_num,  "cod_saber_11_22_1_num.csv")
write_csv(cod_saber_11_22_1_geog, "cod_saber_11_22_1_geog.csv")

7 CODIFICACIÓN COMPLETA: BINARIAS Y ORDINALES (SABER 11, 2022)

install.packages('janitor')
package 'janitor' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\john\AppData\Local\Temp\RtmpySlWoZ\downloaded_packages
library(janitor)

library(dplyr)
library(readr)
library(stringr)
library(stringi)
library(janitor)

# Cargar subconjuntos
bin  <- read_csv("cod_saber_11_22_1_bin.csv",  show_col_types = FALSE)
ord  <- read_csv("cod_saber_11_22_1_ord.csv",  show_col_types = FALSE)
nom  <- read_csv("cod_saber_11_22_1_nom.csv",  show_col_types = FALSE)
num  <- read_csv("cod_saber_11_22_1_num.csv",  show_col_types = FALSE)
geog <- read_csv("cod_saber_11_22_1_geog.csv", show_col_types = FALSE)

# Limpieza de nombres
bin  <- clean_names(bin)
ord  <- clean_names(ord)
nom  <- clean_names(nom)
num  <- clean_names(num)
geog <- clean_names(geog)

# Verificación de dimensiones
cat("Dimensiones:\n")
Dimensiones:
cat("Geográficas:", dim(geog), "\n")
Geográficas: 532789 14 
cat("Binarias:   ", dim(bin),  "\n")
Binarias:    532789 7 
cat("Ordinales:  ", dim(ord),  "\n")
Ordinales:   532789 5 
cat("Nominales:  ", dim(nom),  "\n")
Nominales:   532789 15 
cat("Numéricas:  ", dim(num),  "\n")
Numéricas:   532789 14 
if (length(unique(c(nrow(geog), nrow(bin), nrow(ord), nrow(nom), nrow(num)))) == 1) {
  cat("\n Todas las bases tienen el mismo número de filas.\n")
} else {
  warning("\n Atención: hay diferencias en el número de filas entre subconjuntos.\n")
}

 Todas las bases tienen el mismo número de filas.
# CODIFICACIÓN BINARIA (0/1)
to_bin <- function(x) {
  x0 <- as.character(x)
  x0 <- stri_trans_general(x0, "Latin-ASCII") %>% str_trim() %>% str_to_lower()
  case_when(
    x0 %in% c("si", "s", "1", "true", "t") ~ 1L,
    x0 %in% c("no", "n", "0", "false", "f") ~ 0L,
    TRUE ~ NA_integer_
  )
}

bin_cod <- bin %>% mutate(across(everything(), to_bin))
write_csv(bin_cod, "cod_saber_11_22_1_bin.csv")
cat("\n Variables binarias codificadas correctamente (0/1)\n")

 Variables binarias codificadas correctamente (0/1)
glimpse(bin_cod) #Variables codificadas
Rows: 532,789
Columns: 7
$ cole_bilingue         <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, ~
$ fami_tieneautomovil   <int> 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, ~
$ fami_tienecomputador  <int> 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, ~
$ fami_tieneinternet    <int> 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, ~
$ fami_tienelavadora    <int> 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, ~
$ cole_sede_principal   <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ~
$ estu_privado_libertad <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
# Exportar base ordinal codificada
write_csv(bin_cod, "cod_saber_11_22_1_bin.csv")

# CODIFICACIÓN ORDINARIA (EDUCACIÓN, PERSONAS, CUARTOS, INGLÉS)

# Limpieza de texto
clean_txt <- function(x) {
  x0 <- stringi::stri_trans_general(as.character(x), "Latin-ASCII")
  x0 <- stringr::str_trim(stringr::str_to_lower(x0))
  x0
}

# Mapa detallado educación madre/padre
map_edu_mampap <- c(
  # 0
  "ninguno" = 0, "no aplica" = 0, "no sabe" = 0, "ninguna" = 0,
  "sin informacion" = 0, "sin educacion" = 0,
  # 1-2
  "primaria incompleta" = 1, "primaria completa" = 2,
  # 3-4
  "secundaria (bachillerato) incompleta" = 3, "secundaria (bachillerato) completa" = 4,
  "secundaria incompleta" = 3, "secundaria completa" = 4,
  "bachillerato incompleto" = 3, "bachillerato completo" = 4,
  # 5-6
  "tecnica/tecnologica incompleta" = 5, "tecnica/tecnologica completa" = 6,
  "tecnico/tecnologico incompleto" = 5, "tecnico/tecnologico completo" = 6,
  "tecnica o tecnologica incompleta" = 5, "tecnica o tecnologica completa" = 6,
  "tecnica incompleta" = 5, "tecnica completa" = 6,
  # 7-8
  "educacion profesional incompleta" = 7, "educacion profesional completa" = 8,
  "profesional incompleta" = 7, "profesional completa" = 8,
  # 9
  "postgrado" = 9, "especializacion" = 9, "maestria" = 9, "doctorado" = 9
)

# Personas en el hogar
map_personas <- c(
  "1" = 1, "2" = 1, "1 a 2" = 1,
  "3" = 2, "4" = 2, "3 a 4" = 2,
  "5" = 3, "6" = 3, "5 a 6" = 3,
  "7" = 4, "8" = 4, "9" = 4, "7 a 8" = 4,
  "7 o mas" = 4, "8 o mas" = 4, "9 o mas" = 4,
  "7 o más" = 4, "8 o más" = 4, "9 o más" = 4,
  "7 o mas personas" = 4, "7 o más personas" = 4
)

# --- Desempeño inglés ---
map_ing <- c("A-" = 0, "A1" = 1, "A2" = 2, "B1" = 3, "B+" = 4)

# --- Codificación ---
ord_cod <- ord %>%
  mutate(
    fami_educacionmadre = unname(map_edu_mampap[clean_txt(fami_educacionmadre)]),
    fami_educacionpadre = unname(map_edu_mampap[clean_txt(fami_educacionpadre)]),
    fami_personashogar = unname(map_personas[clean_txt(fami_personashogar)]),
    fami_cuartoshogar = suppressWarnings(as.numeric(str_extract(as.character(fami_cuartoshogar), "\\d+"))),
    desemp_ingles = unname(map_ing[str_to_upper(desemp_ingles)])
  )

glimpse(ord_cod)
Rows: 532,789
Columns: 5
$ fami_educacionmadre <dbl> 1, 4, 1, 8, 8, 4, 2, 4, 4, 4, 0, 4, 3, 5, 6, 1, 6,~
$ fami_educacionpadre <dbl> 1, 1, 1, 8, 8, 4, 3, 3, 4, 4, 0, 3, 3, 3, 4, 0, 4,~
$ fami_personashogar  <dbl> 3, 2, 4, 2, 3, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 3,~
$ fami_cuartoshogar   <dbl> 4, 1, 2, 2, 2, 3, 2, 2, 3, 2, 4, 2, 1, 3, 3, 2, 3,~
$ desemp_ingles       <dbl> 2, 0, 0, 1, 0, 1, 0, 0, 2, 2, 3, 0, 0, 2, 1, 3, 0,~
# Exportar base ordinal codificada
write_csv(ord_cod, "cod_saber_11_22_1_ord.csv")
cat("\n Variables ordinales codificadas correctamente (0–9 según nivel)\n")

 Variables ordinales codificadas correctamente (0–9 según nivel)
# ORGANIZACION DE EDAD CALCULADA
num <- num %>%
  mutate(edad_calculada = as.integer(round(edad_calculada, 0)))
glimpse(num)
Rows: 532,789
Columns: 14
$ punt_ingles                   <dbl> 60, 43, 45, 56, 37, 56, 38, 45, 64, 59, ~
$ punt_matematicas              <dbl> 44, 41, 30, 52, 30, 65, 34, 26, 57, 49, ~
$ punt_sociales_ciudadanas      <dbl> 50, 29, 42, 43, 32, 58, 34, 40, 40, 36, ~
$ punt_c_naturales              <dbl> 41, 42, 36, 48, 35, 60, 35, 43, 56, 36, ~
$ punt_lectura_critica          <dbl> 50, 44, 53, 51, 32, 61, 43, 48, 63, 49, ~
$ punt_global                   <dbl> 237, 197, 203, 245, 163, 303, 183, 198, ~
$ edad                          <dbl> 18, 18, 18, 19, 19, 17, 17, 18, 17, 17, ~
$ edad_calculada                <int> 18, 18, 18, 19, 19, 17, 17, 18, 17, 17, ~
$ dif_edad                      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0~
$ fami_estratovivienda          <dbl> 2, 2, 1, 2, 2, 3, 1, 1, 4, 1, 2, 1, 2, 3~
$ cole_cod_dane_establecimiento <dbl> 183247000272, 176001001702, 105001001121~
$ cole_cod_dane_sede            <dbl> 183247000272, 176001001702, 105001001121~
$ cole_codigo_icfes             <dbl> 671586, 731349, 719096, 708081, 4663, 71~
$ periodo                       <dbl> 20224, 20224, 20224, 20224, 20224, 20224~
# UNIÓN FINAL DE TODAS LAS BASES
cod_saber11_2022_1 <- bind_cols(
  geog,
  bin_cod,
  ord_cod,
  nom,
  num
)

write_csv(cod_saber11_2022_1, "cod_saber11_2022_1.csv")
cat("\n Base consolidada exportada: cod_saber11_2022_1.csv\n")

 Base consolidada exportada: cod_saber11_2022_1.csv
# Verificación final (conteo de NA)

na_resumen <- sapply(cod_saber11_2022_1, function(x) sum(is.na(x)))
cat("\nResumen de valores faltantes por variable:\n")

Resumen de valores faltantes por variable:
print(na_resumen[na_resumen > 0])
named integer(0)
# Muestra estructura final
glimpse(cod_saber11_2022_1)
Rows: 532,789
Columns: 55
$ cole_depto_ubicacion          <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ cole_mcpio_ubicacion          <chr> "El Doncello", "Cali", "Medellin", "Gala~
$ cole_cod_depto_ubicacion      <chr> "18", "76", "05", "08", "13", "11", "44"~
$ cole_cod_mcpio_ubicacion      <chr> "18247", "76001", "05001", "08296", "136~
$ estu_depto_presentacion       <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ estu_mcpio_presentacion       <chr> "El Doncello", "Cali", "Medellin", "Bara~
$ estu_depto_reside             <chr> "Caqueta", "Valle", "Antioquia", "Atlant~
$ estu_mcpio_reside             <chr> "El Doncello", "Cali", "Medellin", "Gala~
$ estu_cod_depto_presentacion   <chr> "18", "76", "05", "08", "13", "11", "44"~
$ estu_cod_mcpio_presentacion   <chr> "18247", "76001", "05001", "08078", "136~
$ estu_cod_reside_depto         <chr> "18", "76", "05", "08", "13", "11", "44"~
$ estu_cod_reside_mcpio         <chr> "18247", "76001", "05001", "08296", "136~
$ fecha_examen_ref              <date> 2022-12-31, 2022-12-31, 2022-12-31, 202~
$ estu_consecutivo              <chr> "sb11202240536228", "sb11202240218341", ~
$ cole_bilingue                 <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0~
$ fami_tieneautomovil           <int> 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1~
$ fami_tienecomputador          <int> 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1~
$ fami_tieneinternet            <int> 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1~
$ fami_tienelavadora            <int> 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1~
$ cole_sede_principal           <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1~
$ estu_privado_libertad         <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0~
$ fami_educacionmadre           <dbl> 1, 4, 1, 8, 8, 4, 2, 4, 4, 4, 0, 4, 3, 5~
$ fami_educacionpadre           <dbl> 1, 1, 1, 8, 8, 4, 3, 3, 4, 4, 0, 3, 3, 3~
$ fami_personashogar            <dbl> 3, 2, 4, 2, 3, 2, 2, 2, 2, 2, 2, 1, 1, 2~
$ fami_cuartoshogar             <dbl> 4, 1, 2, 2, 2, 3, 2, 2, 3, 2, 4, 2, 1, 3~
$ desemp_ingles                 <dbl> 2, 0, 0, 1, 0, 1, 0, 0, 2, 2, 3, 0, 0, 2~
$ estu_genero                   <chr> "F", "M", "F", "F", "F", "M", "F", "F", ~
$ cole_naturaleza               <chr> "Oficial", "Oficial", "Oficial", "Oficia~
$ cole_area_ubicacion           <chr> "Urbano", "Urbano", "Urbano", "Urbano", ~
$ cole_caracter                 <chr> "Tecnico/Academico", "Tecnico/Academico"~
$ cole_calendario               <chr> "A", "A", "A", "A", "A", "A", "A", "A", ~
$ cole_jornada                  <chr> "Unica", "Unica", "Unica", "Unica", "Ma\~
$ cole_genero                   <chr> "Mixto", "Mixto", "Mixto", "Mixto", "Mix~
$ cole_nombre_establecimiento   <chr> "I.E. Jorge Abel Molina", "Institucion E~
$ cole_nombre_sede              <chr> "Jorge Abel Molina", "Institucion Educat~
$ estu_tipodocumento            <chr> "TI", "TI", "TI", "CR", "CC", "TI", "TI"~
$ estu_estadoinvestigacion      <chr> "publicar", "publicar", "publicar", "pub~
$ estu_estudiante               <chr> "estudiante", "estudiante", "estudiante"~
$ estu_fechanacimiento          <date> 2004-12-30, 2004-12-30, 2004-12-30, 200~
$ estu_nacionalidad             <chr> "Colombia", "Colombia", "Colombia", "Col~
$ estu_pais_reside              <chr> "Colombia", "Colombia", "Colombia", "Col~
$ punt_ingles                   <dbl> 60, 43, 45, 56, 37, 56, 38, 45, 64, 59, ~
$ punt_matematicas              <dbl> 44, 41, 30, 52, 30, 65, 34, 26, 57, 49, ~
$ punt_sociales_ciudadanas      <dbl> 50, 29, 42, 43, 32, 58, 34, 40, 40, 36, ~
$ punt_c_naturales              <dbl> 41, 42, 36, 48, 35, 60, 35, 43, 56, 36, ~
$ punt_lectura_critica          <dbl> 50, 44, 53, 51, 32, 61, 43, 48, 63, 49, ~
$ punt_global                   <dbl> 237, 197, 203, 245, 163, 303, 183, 198, ~
$ edad                          <dbl> 18, 18, 18, 19, 19, 17, 17, 18, 17, 17, ~
$ edad_calculada                <int> 18, 18, 18, 19, 19, 17, 17, 18, 17, 17, ~
$ dif_edad                      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0~
$ fami_estratovivienda          <dbl> 2, 2, 1, 2, 2, 3, 1, 1, 4, 1, 2, 1, 2, 3~
$ cole_cod_dane_establecimiento <dbl> 183247000272, 176001001702, 105001001121~
$ cole_cod_dane_sede            <dbl> 183247000272, 176001001702, 105001001121~
$ cole_codigo_icfes             <dbl> 671586, 731349, 719096, 708081, 4663, 71~
$ periodo                       <dbl> 20224, 20224, 20224, 20224, 20224, 20224~