
Importar paquetes y librerias
#install.packages("sf") # Análisis de datos espaciales
#install.packages("rnaturalearth") # Límites geográficos
#install.packages("rnaturalearthdata") # Datos de geografía
#install.packages("devtools")
#install.packages(c("readr","dplyr","stringr","factoextra","cluster"))
library(sf)
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
library(rnaturalearth)
library(rnaturalearthdata)
##
## Attaching package: 'rnaturalearthdata'
## The following object is masked from 'package:rnaturalearth':
##
## countries110
library(devtools)
## Loading required package: usethis
library(readr)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(stringr)
library(factoextra)
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(cluster)
############################
mexico <- ne_states(country = "Mexico", returnclass = "sf")
# names(mexico) # para ver columnas disponibles (incluye 'name' con el nombre del estado)
Importar base de datos
datosmex <- read_csv("~/Documents/Modulo2/Educacion_06_limpia.csv", show_col_types = FALSE)
Estandarizar
datosmex <- datosmex |>
rename(
name = `Entidad federativa`,
Media_superior = `Media superior`
)
datosmex <- datosmex |>
filter(name != "Estados Unidos Mexicanos")
head(datosmex)
## # A tibble: 6 × 7
## name Total Inicial Preescolar Primaria Secundaria Media_superior
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Aguascalientes 400455 3099 51878 160480 74675 56636
## 2 Baja California 951597 7435 96630 384953 186104 147224
## 3 Baja California … 210438 2219 26082 83662 40608 33870
## 4 Campeche 248444 3242 34356 100121 45736 36601
## 5 Coahuila de Zara… 856439 7151 129840 329075 157186 117561
## 6 Colima 186651 3126 22792 74563 34808 30173
Armonizar
datosmex <- datosmex |>
mutate(
name_harmon = case_when(
name == "Ciudad de México" ~ "Distrito Federal", # algunos mapas antiguos usan DF
TRUE ~ name
)
)
# Intento de join con el mapa usando 'name' del shape
mex_join1 <- mexico |>
select(name, geometry) |>
left_join(datosmex, by = join_by(name == name_harmon))
# Detectar no empates
no_match <- mex_join1 |>
filter(is.na(Total)) |>
pull(name)
if (length(no_match) > 0) {
message("Estados no empataron en el primer intento: ", paste(no_match, collapse = ", "))
# Si hay más diferencias de nombre, puedes agregarlas aquí, por ejemplo:
# datosmex$name_harmon <- recode(datosmex$name_harmon,
# "Veracruz de Ignacio de la Llave" = "Veracruz-Llave",
# "Michoacán de Ocampo" = "Michoacán de Ocampo",
# "Coahuila de Zaragoza" = "Coahuila de Zaragoza"
# )
# Y volver a hacer el join si fuera necesario.
}
## Estados no empataron en el primer intento: Coahuila, Veracruz, Michoacán, NA
Escalar la base de datos
# Escalar la base de datos (solo variables numéricas)
############################
# Seleccionamos columnas numéricas para clustering
vars_num <- datosmex |>
select(Total, Inicial, Preescolar, Primaria, Secundaria, Media_superior)
# Escalado (media 0, var 1)
datos_escalados_mex <- scale(vars_num)
Generar los K means
set.seed(123)
grupos_mex <- 3 # Inicio con valor "cualquiera"; puedes optimizar luego
segmentos_mex <- kmeans(datos_escalados_mex, centers = grupos_mex, nstart = 25)
Añadir asignación de cluster
asignacion_mex <- cbind(
datosmex |>
select(name, Total, Inicial, Preescolar, Primaria, Secundaria, Media_superior),
cluster = segmentos_mex$cluster
)
Asignar etiquetas de grupo
asignacion_mex <- asignacion_mex |>
mutate(
cluster_label = case_when(
cluster == 1 ~ "Grupo 1",
cluster == 2 ~ "Grupo 2",
cluster == 3 ~ "Grupo 3",
TRUE ~ paste0("Grupo ", cluster)
)
)
head(asignacion_mex)
## name Total Inicial Preescolar Primaria Secundaria
## 1 Aguascalientes 400455 3099 51878 160480 74675
## 2 Baja California 951597 7435 96630 384953 186104
## 3 Baja California Sur 210438 2219 26082 83662 40608
## 4 Campeche 248444 3242 34356 100121 45736
## 5 Coahuila de Zaragoza 856439 7151 129840 329075 157186
## 6 Colima 186651 3126 22792 74563 34808
## Media_superior cluster cluster_label
## 1 56636 1 Grupo 1
## 2 147224 1 Grupo 1
## 3 33870 1 Grupo 1
## 4 36601 1 Grupo 1
## 5 117561 1 Grupo 1
## 6 30173 1 Grupo 1
Gráfica de los cluster
fviz_cluster(segmentos_mex, data = datos_escalados_mex) +
ggplot2::ggtitle(paste("Clusters k-means con k =", grupos_mex))

LS0tCnRpdGxlOiAiRWR1YWNpw7NuIGVuIE3DqXhpY28iCmF1dGhvcjogIkR5YW5uIEVzdGVmYW5pYSBIZXJuYW5kZXogQXlhbGEiCmRhdGU6ICIyMDI1LTA4LTIxIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgY29kZV9kb3dubG9hZDogVFJVRQogICAgdGhlbWU6IHlldGkKLS0tCiFbXShodHRwczovL2dhY2V0YWVjb25vbWljYS5maW5hbmNlLmJsb2cvd3AtY29udGVudC91cGxvYWRzLzIwMjIvMDYvZWR1Y2FjaW9uLW1leGljby5qcGcpCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+SW1wb3J0YXIgcGFxdWV0ZXMgeSBsaWJyZXJpYXMgPC9zcGFuPgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoInNmIikgICAgICAgICAgICAgICAgICAgICMgQW7DoWxpc2lzIGRlIGRhdG9zIGVzcGFjaWFsZXMKI2luc3RhbGwucGFja2FnZXMoInJuYXR1cmFsZWFydGgiKSAgICAgICAgICMgTMOtbWl0ZXMgZ2VvZ3LDoWZpY29zCiNpbnN0YWxsLnBhY2thZ2VzKCJybmF0dXJhbGVhcnRoZGF0YSIpICAgICAjIERhdG9zIGRlIGdlb2dyYWbDrWEKI2luc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikKI2luc3RhbGwucGFja2FnZXMoYygicmVhZHIiLCJkcGx5ciIsInN0cmluZ3IiLCJmYWN0b2V4dHJhIiwiY2x1c3RlciIpKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHJuYXR1cmFsZWFydGgpCmxpYnJhcnkocm5hdHVyYWxlYXJ0aGRhdGEpCmxpYnJhcnkoZGV2dG9vbHMpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShmYWN0b2V4dHJhKQpsaWJyYXJ5KGNsdXN0ZXIpCmBgYAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbWV4aWNvIDwtIG5lX3N0YXRlcyhjb3VudHJ5ID0gIk1leGljbyIsIHJldHVybmNsYXNzID0gInNmIikKIyBuYW1lcyhtZXhpY28pICAjIHBhcmEgdmVyIGNvbHVtbmFzIGRpc3BvbmlibGVzIChpbmNsdXllICduYW1lJyBjb24gZWwgbm9tYnJlIGRlbCBlc3RhZG8pCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5JbXBvcnRhciBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4KYGBge3J9CmRhdG9zbWV4IDwtIHJlYWRfY3N2KCJ+L0RvY3VtZW50cy9Nb2R1bG8yL0VkdWNhY2lvbl8wNl9saW1waWEuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+RXN0YW5kYXJpemFyIDwvc3Bhbj4KYGBge3J9CmRhdG9zbWV4IDwtIGRhdG9zbWV4IHw+CiAgcmVuYW1lKAogICAgbmFtZSAgICAgICAgICAgID0gYEVudGlkYWQgZmVkZXJhdGl2YWAsCiAgICBNZWRpYV9zdXBlcmlvciAgPSBgTWVkaWEgc3VwZXJpb3JgCiAgKQpgYGAKCmBgYHtyfQpkYXRvc21leCA8LSBkYXRvc21leCB8PgogIGZpbHRlcihuYW1lICE9ICJFc3RhZG9zIFVuaWRvcyBNZXhpY2Fub3MiKQpgYGAKCgpgYGB7cn0KaGVhZChkYXRvc21leCkKYGBgCiMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5Bcm1vbml6YXIgPC9zcGFuPgpgYGB7cn0KZGF0b3NtZXggPC0gZGF0b3NtZXggfD4KICBtdXRhdGUoCiAgICBuYW1lX2hhcm1vbiA9IGNhc2Vfd2hlbigKICAgICAgbmFtZSA9PSAiQ2l1ZGFkIGRlIE3DqXhpY28iIH4gIkRpc3RyaXRvIEZlZGVyYWwiLCAgIyBhbGd1bm9zIG1hcGFzIGFudGlndW9zIHVzYW4gREYKICAgICAgVFJVRSB+IG5hbWUKICAgICkKICApCmBgYAoKCmBgYHtyfQojIEludGVudG8gZGUgam9pbiBjb24gZWwgbWFwYSB1c2FuZG8gJ25hbWUnIGRlbCBzaGFwZQptZXhfam9pbjEgPC0gbWV4aWNvIHw+CiAgc2VsZWN0KG5hbWUsIGdlb21ldHJ5KSB8PgogIGxlZnRfam9pbihkYXRvc21leCwgYnkgPSBqb2luX2J5KG5hbWUgPT0gbmFtZV9oYXJtb24pKQpgYGAKCmBgYHtyfQojIERldGVjdGFyIG5vIGVtcGF0ZXMKbm9fbWF0Y2ggPC0gbWV4X2pvaW4xIHw+CiAgZmlsdGVyKGlzLm5hKFRvdGFsKSkgfD4KICBwdWxsKG5hbWUpCgppZiAobGVuZ3RoKG5vX21hdGNoKSA+IDApIHsKICBtZXNzYWdlKCJFc3RhZG9zIG5vIGVtcGF0YXJvbiBlbiBlbCBwcmltZXIgaW50ZW50bzogIiwgcGFzdGUobm9fbWF0Y2gsIGNvbGxhcHNlID0gIiwgIikpCiAgIyBTaSBoYXkgbcOhcyBkaWZlcmVuY2lhcyBkZSBub21icmUsIHB1ZWRlcyBhZ3JlZ2FybGFzIGFxdcOtLCBwb3IgZWplbXBsbzoKICAjIGRhdG9zbWV4JG5hbWVfaGFybW9uIDwtIHJlY29kZShkYXRvc21leCRuYW1lX2hhcm1vbiwKICAjICAgIlZlcmFjcnV6IGRlIElnbmFjaW8gZGUgbGEgTGxhdmUiID0gIlZlcmFjcnV6LUxsYXZlIiwKICAjICAgIk1pY2hvYWPDoW4gZGUgT2NhbXBvIiA9ICJNaWNob2Fjw6FuIGRlIE9jYW1wbyIsCiAgIyAgICJDb2FodWlsYSBkZSBaYXJhZ296YSIgPSAiQ29haHVpbGEgZGUgWmFyYWdvemEiCiAgIyApCiAgIyBZIHZvbHZlciBhIGhhY2VyIGVsIGpvaW4gc2kgZnVlcmEgbmVjZXNhcmlvLgp9CmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZTsiPkVzY2FsYXIgbGEgYmFzZSBkZSBkYXRvcyA8L3NwYW4+CmBgYHtyfQojIEVzY2FsYXIgbGEgYmFzZSBkZSBkYXRvcyAoc29sbyB2YXJpYWJsZXMgbnVtw6lyaWNhcykKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFNlbGVjY2lvbmFtb3MgY29sdW1uYXMgbnVtw6lyaWNhcyBwYXJhIGNsdXN0ZXJpbmcKdmFyc19udW0gPC0gZGF0b3NtZXggfD4KICBzZWxlY3QoVG90YWwsIEluaWNpYWwsIFByZWVzY29sYXIsIFByaW1hcmlhLCBTZWN1bmRhcmlhLCBNZWRpYV9zdXBlcmlvcikKCmBgYAoKCmBgYHtyfQojIEVzY2FsYWRvIChtZWRpYSAwLCB2YXIgMSkKZGF0b3NfZXNjYWxhZG9zX21leCA8LSBzY2FsZSh2YXJzX251bSkKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+R2VuZXJhciBsb3MgSyBtZWFucyA8L3NwYW4+CmBgYHtyfQoKc2V0LnNlZWQoMTIzKQpncnVwb3NfbWV4IDwtIDMgICMgSW5pY2lvIGNvbiB2YWxvciAiY3VhbHF1aWVyYSI7IHB1ZWRlcyBvcHRpbWl6YXIgbHVlZ28Kc2VnbWVudG9zX21leCA8LSBrbWVhbnMoZGF0b3NfZXNjYWxhZG9zX21leCwgY2VudGVycyA9IGdydXBvc19tZXgsIG5zdGFydCA9IDI1KQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5Bw7FhZGlyIGFzaWduYWNpw7NuIGRlIGNsdXN0ZXIgPC9zcGFuPgpgYGB7cn0KYXNpZ25hY2lvbl9tZXggPC0gY2JpbmQoCiAgZGF0b3NtZXggfD4KICAgIHNlbGVjdChuYW1lLCBUb3RhbCwgSW5pY2lhbCwgUHJlZXNjb2xhciwgUHJpbWFyaWEsIFNlY3VuZGFyaWEsIE1lZGlhX3N1cGVyaW9yKSwKICBjbHVzdGVyID0gc2VnbWVudG9zX21leCRjbHVzdGVyCikKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+QXNpZ25hciBldGlxdWV0YXMgZGUgZ3J1cG8gPC9zcGFuPgpgYGB7cn0KYXNpZ25hY2lvbl9tZXggPC0gYXNpZ25hY2lvbl9tZXggfD4KICBtdXRhdGUoCiAgICBjbHVzdGVyX2xhYmVsID0gY2FzZV93aGVuKAogICAgICBjbHVzdGVyID09IDEgfiAiR3J1cG8gMSIsCiAgICAgIGNsdXN0ZXIgPT0gMiB+ICJHcnVwbyAyIiwKICAgICAgY2x1c3RlciA9PSAzIH4gIkdydXBvIDMiLAogICAgICBUUlVFIH4gcGFzdGUwKCJHcnVwbyAiLCBjbHVzdGVyKQogICAgKQogICkKCmhlYWQoYXNpZ25hY2lvbl9tZXgpCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZTsiPkdyw6FmaWNhIGRlIGxvcyBjbHVzdGVyIDwvc3Bhbj4KYGBge3J9CmZ2aXpfY2x1c3RlcihzZWdtZW50b3NfbWV4LCBkYXRhID0gZGF0b3NfZXNjYWxhZG9zX21leCkgKwogIGdncGxvdDI6OmdndGl0bGUocGFzdGUoIkNsdXN0ZXJzIGstbWVhbnMgY29uIGsgPSIsIGdydXBvc19tZXgpKQpgYGAKCg==