# 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
# 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)
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~
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"
# 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")
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~