CURSO.ACADÉMICO CÓDIGO C.SITUACIÓN SITUACIÓN
Min. :2025 Min. : 5000038 Length:1741 Length:1741
1st Qu.:2025 1st Qu.:24009622 Class :character Class :character
Median :2025 Median :37008217 Mode :character Mode :character
Mean :2025 Mean :31949243
3rd Qu.:2025 3rd Qu.:47003453
Max. :2025 Max. :49010965
C.NATURALEZA NATURALEZA C.DENOMINACIÓN.GENÉRICA
Min. :1.000 Length:1741 Min. : 3.00
1st Qu.:1.000 Class :character 1st Qu.: 14.00
Median :1.000 Mode :character Median : 14.00
Mean :1.275 Mean : 44.81
3rd Qu.:2.000 3rd Qu.: 49.00
Max. :2.000 Max. :941.00
DENOMINACIÓN.GENÉRICA DENOMINACIÓN.GENÉRICA.BREVE DENOMINACIÓN.ESPECÍFICA
Length:1741 Length:1741 Length:1741
Class :character Class :character Class :character
Mode :character Mode :character Mode :character
C.VÍA VÍA NOMBRE.DE.LA.VÍA NÚMERO
Length:1741 Length:1741 Length:1741 Min. : 1.00
Class :character Class :character Class :character 1st Qu.: 4.00
Mode :character Mode :character Mode :character Median : 10.50
Mean : 20.68
3rd Qu.: 25.00
Max. :300.00
NA's :595
NÚMERO.EXT. PISO PISO.EXT. ESCALERA
Length:1741 Min. :1.0 Length:1741 Mode:logical
Class :character 1st Qu.:1.0 Class :character NA's:1741
Mode :character Median :1.5 Mode :character
Mean :2.0
3rd Qu.:2.5
Max. :4.0
NA's :1737
LETRA C.PROV C.MUNI C.LOCA
Length:1741 Min. : 5.00 Min. : 1.0 Min. : 1.000
Class :character 1st Qu.:24.00 1st Qu.: 59.0 1st Qu.: 1.000
Mode :character Median :37.00 Median :133.0 Median : 2.000
Mean :31.94 Mean :145.2 Mean : 4.228
3rd Qu.:47.00 3rd Qu.:194.0 3rd Qu.: 5.000
Max. :49.00 Max. :908.0 Max. :301.000
PROVINCIA MUNICIPIO LOCALIDAD C.POSTAL
Length:1741 Length:1741 Length:1741 Min. : 5001
Class :character Class :character Class :character 1st Qu.:24010
Mode :character Mode :character Mode :character Median :37008
Mean :32172
3rd Qu.:47008
Max. :49810
TELÉFONO FAX LETRA.1 CORREO.ELECTRÓNICO
Min. :600436409 Min. :644194608 Length:1741 Length:1741
1st Qu.:923225200 1st Qu.:923402830 Class :character Class :character
Median :975377401 Median :979712853 Mode :character Mode :character
Mean :937908871 Mean :959536538
3rd Qu.:983502182 3rd Qu.:983547103
Max. :987876210 Max. :987972030
NA's :44 NA's :740
WEB COORD..LONGITUD COORD..LATITUD C.R.A
Length:1741 Min. :-6.947 Min. :40.15 Length:1741
Class :character 1st Qu.:-5.650 1st Qu.:41.03 Class :character
Mode :character Median :-4.751 Median :41.65 Mode :character
Mean :-4.871 Mean :41.69
3rd Qu.:-4.314 3rd Qu.:42.34
Max. :-1.920 Max. :43.15
NA's :15 NA's :15
INTERNADO CONCIERTO JORNADA.CONTINUA COMEDOR
Length:1741 Length:1741 Length:1741 Length:1741
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
TRANSPORTE X
Length:1741 Mode:logical
Class :character NA's:1741
Mode :character
Centros Docentes en Castilla y León
Input
Se ha obtenido un conjunto de datos la comunidad de Castilla y León sobre los diversos centros docentes que hay en esa localidad. Los centros docentes abarcan un amplio catálogo de centros de aprendizaje, desde escuelas de infantil y primaria hasta centros docentes de formación militar.
Estos datos se publicaron el 27 de marzo del año 2012. No obstante, se actualizan constantemente, por lo tanto, el año más actualizado del que podemos obtener datos desde esta página web de datos abiertos es el 2025.
A continuación, se comparte el link de la página donde se han obtenido los datos (https://datosabiertos.jcyl.es/) y el enlace a la descarga de los datos iniciales (https://datosabiertos.jcyl.es/web/jcyl/set/es/educacion/centrosdocentes/1284200521439).
Seguidamente, se mostrará un listado de todos los tipos docentes que se abarcan:
unique(centros$DENOMINACIÓN.GENÉRICA) [1] "CENTRO DOCENTE DE FORMACIÓN MILITAR"
[2] "CONSERVATORIO PROFESIONAL DE MUSICA"
[3] "CONSERVATORIO ELEMENTAL DE MUSICA"
[4] "CONSERVATORIO SUPERIOR DE MUSICA"
[5] "COLEGIO DE EDUCACION ESPECIAL"
[6] "COLEGIO DE EDUCACION INFANTIL Y PRIMARIA"
[7] "CENTRO DE EDUCACIÓN OBLIGATORIA"
[8] "COLEGIO DE EDUCACION PRIMARIA"
[9] "CENTRO PUBLICO DE EDUCACION DE PERSONAS ADULTAS"
[10] "CENTRO PUBLICO INTEGRADO DE FORMACION PROFESIONAL"
[11] "CENTRO PRIVADO DE EDUCACION INFANTIL PRIMARIA Y SECUNDARIA"
[12] "CENTRO PRIVADO DE EDUCACION INFANTIL Y PRIMARIA"
[13] "CENTRO PRIVADO DE EDUCACION PRIMARIA Y SECUNDARIA"
[14] "CENTRO PRIVADO DE EDUCACION SECUNDARIA"
[15] "CENTRO PRIVADO DE EDUCACION PRIMARIA"
[16] "CENTRO PRIVADO AUTORIZADO DE ARTES PLASTICAS Y DISEÑO"
[17] "CENTRO PRIVADO AUTORIZADO PROFESIONAL DE DANZA"
[18] "CENTRO PRIVADO AUTORIZADO ELEMENTAL DE DANZA"
[19] "CENTRO PRIVADO AUTORIZADO DE ENSEÑANZAS DEPORTIVAS"
[20] "CENTRO PRIVADO AUTORIZADO DE ENSEÑANZAS DEPORTIVAS DE FÚTBOL"
[21] "CENTRO PRIVADO AUTORIZADO DE ENSEÑANZAS DEPORTIVAS DE INVIERNO"
[22] "CENTRO PRIVADO AUTORIZADO DE ENSEÑANZAS DEPORTIVAS DE HÍPICA"
[23] "CENTRO PRIVADO AUTORIZADO DE ENSEÑANZAS DEPORTIVAS DE SALVAMENTO Y SOCORRISMO"
[24] "CENTRO PRIVADO AUTORIZADO PROFESIONAL DE MUSICA"
[25] "CENTRO PRIVADO AUTORIZADO ELEMENTAL DE MUSICA"
[26] "CENTRO PRIVADO DE EDUCACION ESPECIAL"
[27] "CENTRO PRIVADO DE EDUCACION INFANTIL"
[28] "CENTRO PRIVADO DOCENTE EXTRANJERO EN ESPAÑA"
[29] "CENTRO PRIVADO DE FORMACION PROFESIONAL ESPECIFICA"
[30] "CENTRO PRIVADO INTEGRADO DE FORMACION PROFESIONAL"
[31] "ESCUELA DE ARTE Y SUPERIOR DE DISEÑO"
[32] "ESCUELA DE ARTE Y SUPERIOR DE CONSERVACIÓN Y RESTAURACIÓN DE BIENES CULTURALES"
[33] "ESCUELA DE ARTE Y SUPERIOR DE DISEÑO Y DE CONS. Y RESTAUR. DE BIENES CULTURALES"
[34] "ESCUELA DE DANZA"
[35] "ESCUELA DE EDUCACION INFANTIL"
[36] "ESCUELA DE MUSICA"
[37] "ESCUELA DE MUSICA Y DANZA"
[38] "ESCUELA OFICIAL DE IDIOMAS"
[39] "CENTRO AUTORIZADO DEL VIDRIO"
[40] "CENTRO AUTORIZADO SUPERIOR DE ARTE DRAMATICO"
[41] "INSTITUTO DE EDUCACION SECUNDARIA"
[42] "INSTITUTO DE EDUCACION SECUNDARIA OBLIGATORIA"
Descripción
Al descargar los datos podemos observar varias problemáticas. En primer lugar y una de las mejoras de este dataframe más importantes es que tenemos NAs en las columnas de coordenadas, latitud y longitud.
En segundo lugar, tenemos una columnas completamente vacia, la columna X, que seguramente se crea a causa de la lectura de los datos.
unique(centros$X)[1] NA
Seguidamente tenemos una columna, LETRA.1, que podemos observar que tiene los mismo valores que la variable LETRA.
all(centros$LETRA == centros$LETRA.1, na.rm = TRUE)[1] TRUE
En tercer lugar, vemos que hay columnas que tienen información repetida para todo el dataframe. Todas las observaciones de los centros tienen SITUACIÓN, y por consecuente su código, C.SITUACIÓN con el mismo valor, “Alta” o “A”. Entonces no los tenemos en cuenta porque no se puede realizar ningún estudio de esta variable ya que todas son iguales. Asimismo, eliminaremos el curso académico ya que todos nuestros datos están actualizados hasta el 2025.
unique(centros$SITUACIÓN)[1] "ALTA"
unique(centros$C.SITUACIÓN)[1] "A"
unique(centros$CURSO.ACADÉMICO)[1] 2025
Finalmente, otra dificultad que nos encontramos es que hay variables categóricas que no están denominadas como factor, cosa que puede llevar a errores en los análisis si no se tiene en cuenta.
Tratamiento
Para arreglar casi todas las problemáticas, se han eliminado las columnas que no proporcionan valor a los datos. Así, además de tener menos datos que procesar, tambien eliminamos la irrelevancia.
centros <- centros %>%
select(-CURSO.ACADÉMICO,-SITUACIÓN ,-C.SITUACIÓN, -X, -C.VÍA, -LETRA.1)Seguidamente, se han convertido las columnas categorizadas incorrectamente. Convertimos las variables descriptivas a factores.
centros <- centros %>%
mutate(
NATURALEZA = as.factor(NATURALEZA),
C.NATURALEZA = as.factor(C.NATURALEZA),
DENOMINACIÓN.GENÉRICA = as.factor(DENOMINACIÓN.GENÉRICA),
DENOMINACIÓN.GENÉRICA.BREVE = as.factor(DENOMINACIÓN.GENÉRICA.BREVE),
INTERNADO = as.factor(INTERNADO),
CONCIERTO = as.factor(CONCIERTO),
JORNADA.CONTINUA = as.factor(JORNADA.CONTINUA),
COMEDOR = as.factor(COMEDOR),
TRANSPORTE = as.factor(TRANSPORTE)
)A continuación, se realiza un Forward Encoding para añadir las coordenadas faltantes a nuestras 15 observaciones. Para ello se va a dividir nuestros datos en dos, los que ya tienen coordenadas y los que no. Esto se hace para comprobar si las observaciones con las coordenadas están correctas y para reducir el tiempo computacional a la hora de usar la herramienta de geocodificación de los valores faltantes.
Además, añadimos una nueva columna de llamada DIRECCION. Como su nombre indica pondremos todas las variables que ayudan donde se encuentra un centro en un mismo sitio para poder luego geocodificar.
# creamos las direcciones para todos los centros independientemente de si tiene o no las coordenadas correctamente
centros <- centros %>%
mutate(DIRECCION = paste0(VÍA," ", NOMBRE.DE.LA.VÍA, ", ", NÚMERO, "," , LOCALIDAD, ", ", MUNICIPIO, ", ", PROVINCIA))
# dividimos los datos
centros_sinCF <- centros %>% filter(is.na(COORD..LONGITUD) | is.na(COORD..LATITUD))
centros_conCF <- centros %>%
filter(!(CÓDIGO %in% centros_sinCF$CÓDIGO))En primer lugar, se va a comprobar si las coordenadas que hay están correctas.
# Se deben pasar los centros sin coordenadas faltantes a un objeto tipo sf para poder graficarlos correctamente.
crds_sfCON <- sf::st_as_sf(centros_conCF, coords=c("COORD..LONGITUD","COORD..LATITUD"), crs=4258, na.fail=F)
# Se saca la forma de la comunidad autónoma (Castilla y León)
cast_leon <- esp_get_ccaa() %>% filter(codauto == '07')
# Se hace la gráfica:
ggplot() +
annotation_map_tile(type = "cartolight",
zoom = 8,
alpha = 0.8) +
geom_sf(data = crds_sfCON) +
geom_sf(data = cast_leon,
fill = 'transparent',
color = "black",
size = 0.5) Zoom: 8
Fetching 20 missing tiles
|
| | 0%
|
|==== | 5%
|
|======= | 10%
|
|========== | 15%
|
|============== | 20%
|
|================== | 25%
|
|===================== | 30%
|
|======================== | 35%
|
|============================ | 40%
|
|================================ | 45%
|
|=================================== | 50%
|
|====================================== | 55%
|
|========================================== | 60%
|
|============================================== | 65%
|
|================================================= | 70%
|
|==================================================== | 75%
|
|======================================================== | 80%
|
|============================================================ | 85%
|
|=============================================================== | 90%
|
|================================================================== | 95%
|
|======================================================================| 100%
...complete!
Se puede observar gráficamente que todos los puntos descargados directamente están correctos, todos dentro de la comunidad correspondiente. Además, con este gráfico ya podemos ver como se distribuyen los centros docentes en esta comunidad. Se ve que en las ciudades con más población hay más centros, se pueden diferenciar Burgos, Salamanca, Ávila, León y Ponferrada sobretodo. No obstante, también se comprueba que estén los puntos donde corresponden:
# Validar coordenadas dentro de Castilla y León
all(st_contains(cast_leon, crds_sfCON, sparse = FALSE))[1] TRUE
Se verifica que lo que veemos en la gráfica es verdadero.
Seguidamente, se va a geocodificar las direcciones de centros sin coordenadas, reemplazar los datos antiguos de coordenadas con los nuevos y crear un objeto geoespacial (sf) para graficar posteriormente.
crds <- geo(address = centros_sinCF$DIRECCION, method = "arcgis")Passing 15 addresses to the ArcGIS single address geocoder
Query completed in: 7.4 seconds
Finalmente, vamos a graficar todos los centros docentes:
# Combinar los dataframes con una variable categórica
crds_sfCON <- crds_sfCON %>% mutate(tipo = "Centros con coordenadas originales")
crds_sfSIN <- crds_sfSIN %>% mutate(tipo = "Centros geocodificados")
todos_centros_sf <- bind_rows(crds_sfCON, crds_sfSIN)
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = cast_leon,
fill = FALSE,
color = "black",
weight = 2,
opacity = 1,
label = "Castilla y León") %>%
addCircleMarkers(data = todos_centros_sf %>%
filter(tipo == "Centros con coordenadas originales"),
radius = 4,
color = "red",
fillOpacity = 0.8,
weight = 1,
popup = ~paste(
"<b>Centro:</b>", DENOMINACIÓN.ESPECÍFICA, "<br>",
"<b>Código:</b>", CÓDIGO, "<br>",
"<b>Municipio:</b>", MUNICIPIO, "<br>",
"<b>Provincia:</b>", PROVINCIA, "<br>",
"<b>Dirección:</b>", DIRECCION, "<br>",
"<b>Tipo:</b>", tipo
),
label = ~DENOMINACIÓN.ESPECÍFICA,
group = "Coordenadas originales") %>%
addCircleMarkers(data = todos_centros_sf %>%
filter(tipo == "Centros geocodificados"),
radius = 4,
color = "blue",
fillOpacity = 0.8,
weight = 1,
popup = ~paste(
"<b>Centro:</b>", DENOMINACIÓN.ESPECÍFICA, "<br>",
"<b>Código:</b>", CÓDIGO, "<br>",
"<b>Municipio:</b>", MUNICIPIO, "<br>",
"<b>Provincia:</b>", PROVINCIA, "<br>",
"<b>Dirección:</b>", DIRECCION, "<br>",
"<b>Tipo:</b>", tipo
),
label = ~DENOMINACIÓN.ESPECÍFICA,
group = "Geocodificados") %>%
addLayersControl(
overlayGroups = c("Coordenadas originales", "Geocodificados"),
options = layersControlOptions(collapsed = FALSE)
) %>%
addLegend(
colors = c("red", "blue"),
labels = c("Centros con coordenadas originales", "Centros geocodificados"),
title = "Tipo de coordenadas",
opacity = 0.8
) %>%
setView(lng = -4.5, lat = 41.5, zoom = 7) # Para centrar el mapa en Castilla y LeónAhora ya tenemos todos los centros docentes de Castilla y León correctamente estructurados, geocodificados y graficados. Además, tenemos un gráfico interactivo para observar mejor donde se encuentra cada centro docente.
Vamos a poner todos los datos que tenemos en un mismo dataframe con la geometría (sf), sin la columna de tipo:
todos_centros_sf <- todos_centros_sf %>% select(-tipo)Output
Se ha obtenido un dataframe con toda la geometría de todas las observaciones que teniamos para Castilla y León del 2025. En relación al dataframe con la geometría se ha usado el crs = 4258 (el Europeo).
# Guardar como GeoPackage (GPKG)
st_write(todos_centros_sf, "CentrosDocentes_CastillaLeon_2025.gpkg", delete_dsn = TRUE)El/los fichero(s) generados con este procedimiento/técnica/metodología se puede(n) descargar de aquí.

Proyecto de Innovación Educativa Emergente (PIEE-3898312)
