Ejemplo Vinos

Contexto

Estos datos son el resultado de un análisis químico de vinos cultivados en la misma región de Italia pero derivados de tres cultivares diferentes.

El análisis determinó las cantidads de 13 componentes que se encuentran en cada uno de los 3 cultivares.

Instalar paquetes e importar librarías

#install.packages("cluster") # Para agrupamientos 
library(cluster)
#install.packages("ggplot2") # Para graficar
library(ggplot2)
#install.packages("factoextra") # Visualizar clusters
library(factoextra)
#install.packages("data.table") # Conjunto de datos grandes
library(data.table)
#install.packages("tidyverse")
library(tidyverse)

Importar la base de datos

datos <- read.csv("wine_dataset.csv")

Entender la base de datos

summary(datos)
##     alcohol        malic_acid         ash        alcalinity_of_ash
##  Min.   :11.03   Min.   :0.740   Min.   :1.360   Min.   :10.60    
##  1st Qu.:12.36   1st Qu.:1.603   1st Qu.:2.210   1st Qu.:17.20    
##  Median :13.05   Median :1.865   Median :2.360   Median :19.50    
##  Mean   :13.00   Mean   :2.336   Mean   :2.367   Mean   :19.49    
##  3rd Qu.:13.68   3rd Qu.:3.083   3rd Qu.:2.558   3rd Qu.:21.50    
##  Max.   :14.83   Max.   :5.800   Max.   :3.230   Max.   :30.00    
##    magnesium      total_phenols     flavanoids    nonflavanoid_phenols
##  Min.   : 70.00   Min.   :0.980   Min.   :0.340   Min.   :0.1300      
##  1st Qu.: 88.00   1st Qu.:1.742   1st Qu.:1.205   1st Qu.:0.2700      
##  Median : 98.00   Median :2.355   Median :2.135   Median :0.3400      
##  Mean   : 99.74   Mean   :2.295   Mean   :2.029   Mean   :0.3619      
##  3rd Qu.:107.00   3rd Qu.:2.800   3rd Qu.:2.875   3rd Qu.:0.4375      
##  Max.   :162.00   Max.   :3.880   Max.   :5.080   Max.   :0.6600      
##  proanthocyanins color_intensity       hue         od280.od315_of_diluted_wines
##  Min.   :0.410   Min.   : 1.280   Min.   :0.4800   Min.   :1.270               
##  1st Qu.:1.250   1st Qu.: 3.220   1st Qu.:0.7825   1st Qu.:1.938               
##  Median :1.555   Median : 4.690   Median :0.9650   Median :2.780               
##  Mean   :1.591   Mean   : 5.058   Mean   :0.9574   Mean   :2.612               
##  3rd Qu.:1.950   3rd Qu.: 6.200   3rd Qu.:1.1200   3rd Qu.:3.170               
##  Max.   :3.580   Max.   :13.000   Max.   :1.7100   Max.   :4.000               
##     proline           target      
##  Min.   : 278.0   Min.   :0.0000  
##  1st Qu.: 500.5   1st Qu.:0.0000  
##  Median : 673.5   Median :1.0000  
##  Mean   : 746.9   Mean   :0.9382  
##  3rd Qu.: 985.0   3rd Qu.:2.0000  
##  Max.   :1680.0   Max.   :2.0000

Escalar la base de datos

datos_escalados <- scale(datos)
datos_escalados <- subset(datos_escalados, select= -target)

Generar los segmentos

grupos <- 3 #Inicio de cualquier valor, luego se verifica y se ajusta
segmentos <- kmeans(datos_escalados, grupos)

Asignar grupos a los datos

asignacion <- cbind(datos, cluster = segmentos$cluster)

Graficar los clusters

fviz_cluster(segmentos, data=datos)

Optimizar la cantidad de grupos

# La cantidad óptima de grupos corresponde al punto más alto de la gráfica
set.seed(123)
optimizacion <- clusGap(datos_escalados, FUN=kmeans, nstart=1, K.max=10)
plot(optimizacion, xlab="Número de clusters")

Comparar segmentos

promedio <- aggregate(asignacion, by=list(asignacion$cluster), FUN=mean)
promedio
##   Group.1  alcohol malic_acid      ash alcalinity_of_ash magnesium
## 1       1 12.25092   1.897385 2.231231          20.06308  92.73846
## 2       2 13.67677   1.997903 2.466290          17.46290 107.96774
## 3       3 13.13412   3.307255 2.417647          21.24118  98.66667
##   total_phenols flavanoids nonflavanoid_phenols proanthocyanins color_intensity
## 1      2.247692  2.0500000            0.3576923        1.624154        2.973077
## 2      2.847581  3.0032258            0.2920968        1.922097        5.453548
## 3      1.683922  0.8188235            0.4519608        1.145882        7.234706
##         hue od280.od315_of_diluted_wines   proline    target cluster
## 1 1.0627077                     2.803385  510.1692 1.0000000       1
## 2 1.0654839                     3.163387 1100.2258 0.0483871       2
## 3 0.6919608                     1.696667  619.0588 1.9411765       3
table(asignacion$cluster)
## 
##  1  2  3 
## 65 62 51

Ejercicio México 2024

Instalar paquetes e importar librarías

#install.packages("sf") # Análisis de datos espaciales
library(sf)
## Linking to GEOS 3.13.0, GDAL 3.10.1, PROJ 9.5.1; sf_use_s2() is TRUE
#install.packages("rnaturalearth") #Proporciona límites grográficos
library(rnaturalearth)
#install.packages("rnaturalearthdata") #Datos de geografía
library(rnaturalearthdata)
## 
## Adjuntando el paquete: 'rnaturalearthdata'
## The following object is masked from 'package:rnaturalearth':
## 
##     countries110
#install.packages("devtools")
library(devtools) #Instalar paquetes de fuentes externas
## Cargando paquete requerido: usethis
devtools::install_github("ropensci/rnaturalearthhires") #Mapa de Mexico particular
## WARNING: Rtools is required to build R packages, but is not currently installed.
## 
## Please download and install Rtools 4.4 from https://cran.r-project.org/bin/windows/Rtools/.
## Skipping install of 'rnaturalearthhires' from a github remote, the SHA1 (153b0ea5) has not changed since last install.
##   Use `force = TRUE` to force installation

Obtener mapa de México

mexico <- ne_states(country = "Mexico", returnclass = "sf")

Importar la base de datos

datosmex <- read.csv("mexico2024.csv")

Entender la base de datos

summary(datosmex)
##     Estado            Población      PIB.per.cápita   Esperanza.de.vida
##  Length:32          Min.   : 0.700   Min.   : 44387   Min.   :73.50    
##  Class :character   1st Qu.: 1.875   1st Qu.: 84672   1st Qu.:74.50    
##  Mode  :character   Median : 3.050   Median :118147   Median :75.00    
##                     Mean   : 3.947   Mean   :133393   Mean   :75.00    
##                     3rd Qu.: 4.975   3rd Qu.:151772   3rd Qu.:75.53    
##                     Max.   :17.400   Max.   :481697   Max.   :76.50    
##  Tasa.de.pobreza Tasa.de.alfabetización
##  Min.   :13.30   Min.   :86.50         
##  1st Qu.:28.20   1st Qu.:94.42         
##  Median :35.25   Median :96.50         
##  Mean   :37.54   Mean   :95.61         
##  3rd Qu.:46.20   3rd Qu.:97.85         
##  Max.   :67.40   Max.   :99.00

Eliminar datos no numéricos

datosmex_numerico <- subset(datosmex, select = -Estado)

Escalar datos

datos_escaladosmex <- scale(datosmex_numerico)

Escalar datos

set.seed(123)
optimizacion <- clusGap(datos_escaladosmex, FUN = kmeans, nstart = 1, K.max = 10)
plot(optimizacion, xlab = "Número de clusters")

Generar los segmentos

grupos <- 3  # Se inicia con un valor y luego se ajusta según el análisis
segmentosmex <- kmeans(datos_escaladosmex, grupos)

Asignar grupos a los datos

datosmex <- cbind(datosmex, clustermex = segmentosmex$cluster)

Graficar los clusters

fviz_cluster(segmentosmex, data = datos_escaladosmex)

Unir Mapa con datos

mexico <- ne_states(country = "Mexico", returnclass = "sf")

Unir el mapa con los datos de clusters

mexico_clusters <- left_join(mexico, datosmex, by = c("name" = "Estado"))

Unir Mapa con datos

ggplot(mexico_clusters) +
  geom_sf(aes(fill = as.factor(clustermex)), color = "black") +
  scale_fill_manual(values = c("green", "yellow", "red")) + 
  labs(title = "Clusters de población por estado de México", fill = "Cluster") + 
  theme_minimal()

LS0tDQp0aXRsZTogIkNsdXN0ZXJzIg0KYXV0aG9yOiAiTWF4aW1pbGlhbm8gR3VldmFyYSBHYXJjaWEiDQpkYXRlOiAiMjAyNS0wMi0xOSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgY29kZV9kb3dubG9hZDogVFJVRQ0KICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgaGlnaGxpZ2h0OiAia2F0ZSINCiAgICANCi0tLQ0KIVtdKGh0dHBzOi8vY2RuLmZvcmJlcy5jb20ubXgvMjAxOC8wOS9CcmluZGlzLWNvbi12aW5vLTY0MHgzNjAuanBnKQ0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogbWFnZW50YTsgIj5FamVtcGxvIFZpbm9zPC9zcGFuPg0KDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogbWFnZW50YTsgIj5Db250ZXh0bzwvc3Bhbj4NCg0KRXN0b3MgZGF0b3Mgc29uIGVsIHJlc3VsdGFkbyBkZSB1biBhbsOhbGlzaXMgcXXDrW1pY28gZGUgdmlub3MgY3VsdGl2YWRvcyBlbiBsYSBtaXNtYSByZWdpw7NuIGRlIEl0YWxpYSBwZXJvIGRlcml2YWRvcyBkZSB0cmVzIGN1bHRpdmFyZXMgZGlmZXJlbnRlcy4NCg0KRWwgYW7DoWxpc2lzIGRldGVybWluw7MgbGFzIGNhbnRpZGFkcyBkZSAxMyBjb21wb25lbnRlcyBxdWUgc2UgZW5jdWVudHJhbiBlbiBjYWRhIHVubyBkZSBsb3MgMyBjdWx0aXZhcmVzLg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG1hZ2VudGE7ICI+SW5zdGFsYXIgcGFxdWV0ZXMgZSBpbXBvcnRhciBsaWJyYXLDrWFzPC9zcGFuPg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCJjbHVzdGVyIikgIyBQYXJhIGFncnVwYW1pZW50b3MgDQpsaWJyYXJ5KGNsdXN0ZXIpDQojaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpICMgUGFyYSBncmFmaWNhcg0KbGlicmFyeShnZ3Bsb3QyKQ0KI2luc3RhbGwucGFja2FnZXMoImZhY3RvZXh0cmEiKSAjIFZpc3VhbGl6YXIgY2x1c3RlcnMNCmxpYnJhcnkoZmFjdG9leHRyYSkNCiNpbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikgIyBDb25qdW50byBkZSBkYXRvcyBncmFuZGVzDQpsaWJyYXJ5KGRhdGEudGFibGUpDQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogbWFnZW50YTsgIj5JbXBvcnRhciBsYSBiYXNlIGRlIGRhdG9zPC9zcGFuPg0KYGBge3J9DQpkYXRvcyA8LSByZWFkLmNzdigid2luZV9kYXRhc2V0LmNzdiIpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkVudGVuZGVyIGxhIGJhc2UgZGUgZGF0b3M8L3NwYW4+DQpgYGB7cn0NCnN1bW1hcnkoZGF0b3MpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkVzY2FsYXIgbGEgYmFzZSBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZGF0b3NfZXNjYWxhZG9zIDwtIHNjYWxlKGRhdG9zKQ0KZGF0b3NfZXNjYWxhZG9zIDwtIHN1YnNldChkYXRvc19lc2NhbGFkb3MsIHNlbGVjdD0gLXRhcmdldCkNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG1hZ2VudGE7ICI+R2VuZXJhciBsb3Mgc2VnbWVudG9zPC9zcGFuPg0KYGBge3J9DQpncnVwb3MgPC0gMyAjSW5pY2lvIGRlIGN1YWxxdWllciB2YWxvciwgbHVlZ28gc2UgdmVyaWZpY2EgeSBzZSBhanVzdGENCnNlZ21lbnRvcyA8LSBrbWVhbnMoZGF0b3NfZXNjYWxhZG9zLCBncnVwb3MpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkFzaWduYXIgZ3J1cG9zIGEgbG9zIGRhdG9zPC9zcGFuPg0KYGBge3J9DQphc2lnbmFjaW9uIDwtIGNiaW5kKGRhdG9zLCBjbHVzdGVyID0gc2VnbWVudG9zJGNsdXN0ZXIpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkdyYWZpY2FyIGxvcyBjbHVzdGVyczwvc3Bhbj4NCmBgYHtyfQ0KZnZpel9jbHVzdGVyKHNlZ21lbnRvcywgZGF0YT1kYXRvcykNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IG1hZ2VudGE7ICI+T3B0aW1pemFyIGxhIGNhbnRpZGFkIGRlIGdydXBvczwvc3Bhbj4NCmBgYHtyfQ0KIyBMYSBjYW50aWRhZCDDs3B0aW1hIGRlIGdydXBvcyBjb3JyZXNwb25kZSBhbCBwdW50byBtw6FzIGFsdG8gZGUgbGEgZ3LDoWZpY2ENCnNldC5zZWVkKDEyMykNCm9wdGltaXphY2lvbiA8LSBjbHVzR2FwKGRhdG9zX2VzY2FsYWRvcywgRlVOPWttZWFucywgbnN0YXJ0PTEsIEsubWF4PTEwKQ0KcGxvdChvcHRpbWl6YWNpb24sIHhsYWI9Ik7Dum1lcm8gZGUgY2x1c3RlcnMiKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogbWFnZW50YTsgIj5Db21wYXJhciBzZWdtZW50b3M8L3NwYW4+DQpgYGB7cn0NCnByb21lZGlvIDwtIGFnZ3JlZ2F0ZShhc2lnbmFjaW9uLCBieT1saXN0KGFzaWduYWNpb24kY2x1c3RlciksIEZVTj1tZWFuKQ0KcHJvbWVkaW8NCnRhYmxlKGFzaWduYWNpb24kY2x1c3RlcikNCmBgYA0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+RWplcmNpY2lvIE3DqXhpY28gMjAyNDwvc3Bhbj4NCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkluc3RhbGFyIHBhcXVldGVzIGUgaW1wb3J0YXIgbGlicmFyw61hczwvc3Bhbj4NCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFfQ0KI2luc3RhbGwucGFja2FnZXMoInNmIikgIyBBbsOhbGlzaXMgZGUgZGF0b3MgZXNwYWNpYWxlcw0KbGlicmFyeShzZikNCiNpbnN0YWxsLnBhY2thZ2VzKCJybmF0dXJhbGVhcnRoIikgI1Byb3BvcmNpb25hIGzDrW1pdGVzIGdyb2dyw6FmaWNvcw0KbGlicmFyeShybmF0dXJhbGVhcnRoKQ0KI2luc3RhbGwucGFja2FnZXMoInJuYXR1cmFsZWFydGhkYXRhIikgI0RhdG9zIGRlIGdlb2dyYWbDrWENCmxpYnJhcnkocm5hdHVyYWxlYXJ0aGRhdGEpDQojaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQ0KbGlicmFyeShkZXZ0b29scykgI0luc3RhbGFyIHBhcXVldGVzIGRlIGZ1ZW50ZXMgZXh0ZXJuYXMNCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigicm9wZW5zY2kvcm5hdHVyYWxlYXJ0aGhpcmVzIikgI01hcGEgZGUgTWV4aWNvIHBhcnRpY3VsYXINCmBgYA0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsgIj5PYnRlbmVyIG1hcGEgZGUgTcOpeGljbzwvc3Bhbj4NCg0KYGBge3J9DQptZXhpY28gPC0gbmVfc3RhdGVzKGNvdW50cnkgPSAiTWV4aWNvIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0KYGBgDQoNCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsgIj5JbXBvcnRhciBsYSBiYXNlIGRlIGRhdG9zPC9zcGFuPg0KYGBge3J9DQpkYXRvc21leCA8LSByZWFkLmNzdigibWV4aWNvMjAyNC5jc3YiKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+RW50ZW5kZXIgbGEgYmFzZSBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0Kc3VtbWFyeShkYXRvc21leCkNCmBgYA0KDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+RWxpbWluYXIgZGF0b3Mgbm8gbnVtw6lyaWNvczwvc3Bhbj4NCmBgYHtyfQ0KZGF0b3NtZXhfbnVtZXJpY28gPC0gc3Vic2V0KGRhdG9zbWV4LCBzZWxlY3QgPSAtRXN0YWRvKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+RXNjYWxhciBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZGF0b3NfZXNjYWxhZG9zbWV4IDwtIHNjYWxlKGRhdG9zbWV4X251bWVyaWNvKQ0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+RXNjYWxhciBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0Kb3B0aW1pemFjaW9uIDwtIGNsdXNHYXAoZGF0b3NfZXNjYWxhZG9zbWV4LCBGVU4gPSBrbWVhbnMsIG5zdGFydCA9IDEsIEsubWF4ID0gMTApDQpwbG90KG9wdGltaXphY2lvbiwgeGxhYiA9ICJOw7ptZXJvIGRlIGNsdXN0ZXJzIikNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyAiPkdlbmVyYXIgbG9zIHNlZ21lbnRvczwvc3Bhbj4NCmBgYHtyfQ0KZ3J1cG9zIDwtIDMgICMgU2UgaW5pY2lhIGNvbiB1biB2YWxvciB5IGx1ZWdvIHNlIGFqdXN0YSBzZWfDum4gZWwgYW7DoWxpc2lzDQpzZWdtZW50b3NtZXggPC0ga21lYW5zKGRhdG9zX2VzY2FsYWRvc21leCwgZ3J1cG9zKQ0KYGBgDQoNCg0KDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+QXNpZ25hciBncnVwb3MgYSBsb3MgZGF0b3M8L3NwYW4+DQpgYGB7cn0NCmRhdG9zbWV4IDwtIGNiaW5kKGRhdG9zbWV4LCBjbHVzdGVybWV4ID0gc2VnbWVudG9zbWV4JGNsdXN0ZXIpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBtYWdlbnRhOyAiPkdyYWZpY2FyIGxvcyBjbHVzdGVyczwvc3Bhbj4NCmBgYHtyfQ0KZnZpel9jbHVzdGVyKHNlZ21lbnRvc21leCwgZGF0YSA9IGRhdG9zX2VzY2FsYWRvc21leCkNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyAiPlVuaXIgTWFwYSBjb24gZGF0b3M8L3NwYW4+DQpgYGB7cn0NCm1leGljbyA8LSBuZV9zdGF0ZXMoY291bnRyeSA9ICJNZXhpY28iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQpgYGANCg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyAiPlVuaXIgZWwgbWFwYSBjb24gbG9zIGRhdG9zIGRlIGNsdXN0ZXJzPC9zcGFuPg0KDQpgYGB7cn0NCm1leGljb19jbHVzdGVycyA8LSBsZWZ0X2pvaW4obWV4aWNvLCBkYXRvc21leCwgYnkgPSBjKCJuYW1lIiA9ICJFc3RhZG8iKSkNCmBgYA0KDQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47ICI+VW5pciBNYXBhIGNvbiBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZ2dwbG90KG1leGljb19jbHVzdGVycykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gYXMuZmFjdG9yKGNsdXN0ZXJtZXgpKSwgY29sb3IgPSAiYmxhY2siKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZWVuIiwgInllbGxvdyIsICJyZWQiKSkgKyANCiAgbGFicyh0aXRsZSA9ICJDbHVzdGVycyBkZSBwb2JsYWNpw7NuIHBvciBlc3RhZG8gZGUgTcOpeGljbyIsIGZpbGwgPSAiQ2x1c3RlciIpICsgDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg==