---
title: "KMeans"
author: "Ricardo R. Palma"
date: "`r Sys.Date()`"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

# Agrupación K-Means

En el enfoque de partición de R, las observaciones se dividen en grupos K y se reorganizan para formar los grupos más cohesivos posibles de acuerdo con un criterio dado. Hay dos métodos: K-medias y partición alrededor de mediodes *PAM*. En este artículo, basado en el capítulo 16 de R in Action, Second Edition, el autor Rob Kabacoff analiza la agrupación de K-means.

El algoritmo k-means podría utilizarse en el contexto del mantenimiento industrial.

Supongamos que tienes un conjunto de datos históricos sobre el rendimiento y la vida útil de diferentes componentes de maquinaria en una planta industrial. Estos datos pueden incluir variables como la temperatura de funcionamiento, la vibración, el consumo de energía, la carga de trabajo, entre otros.[@lin_research_2019]

El objetivo sería utilizar el algoritmo k-means para identificar grupos o clusters de componentes que tengan un comportamiento similar en términos de su rendimiento y vida útil. Esto puede ayudar a los ingenieros y operarios de mantenimiento a entender mejor el comportamiento de los componentes y tomar decisiones más informadas sobre el mantenimiento preventivo o la sustitución de los mismos.

El proceso podría seguir los siguientes pasos:

* Preparación de datos: Reunir y preparar los datos históricos relevantes de los componentes de maquinaria. Esto puede incluir la recopilación de variables, como la temperatura, la vibración, el consumo de energía, etc., para cada componente en diferentes momentos.

* Selección de características: Identificar las características relevantes para el análisis. Puedes realizar un análisis de correlación o utilizar el conocimiento experto para seleccionar las variables más significativas que pueden influir en el rendimiento y la vida útil de los componentes.

* Normalización de datos: Normalizar los datos para asegurarse de que todas las características tengan la misma escala y rango. Esto es importante para que todas las variables tengan una influencia equitativa en el algoritmo k-means.

* Elección del número de clusters (k): Determinar el número de clusters que deseas encontrar. Puedes utilizar métodos como el método del codo (elbow method) o la silueta (silhouette) para evaluar diferentes valores de k y seleccionar el más adecuado.

* Aplicación del algoritmo k-means: Ejecutar el algoritmo k-means en los datos normalizados, agrupando los componentes en los k clusters determinados. El algoritmo asignará cada componente al cluster más cercano en función de las características seleccionadas.

* Análisis e interpretación de los resultados: Analizar los resultados del clustering para identificar patrones y comportamientos similares entre los componentes. Puedes examinar las características de cada cluster para entender qué factores pueden estar relacionados con un mayor rendimiento o una vida útil más larga. Esto puede ayudar a tomar decisiones de mantenimiento más precisas y eficientes.

Atención que este es solo un ejemplo de cómo se podría aplicar el algoritmo k-means en el mantenimiento industrial. La selección de variables, la normalización de datos y la interpretación de los resultados pueden variar según el contexto y los objetivos específicos del estudio de mantenimiento. No es lo mismo utilizar esta técnica para mantenimiento en la industria alimenticia que en la industria nuclear. Cada campo de aplicación debería respetar los procedimiento Hazop sugerido por las normas y buenas prácticas recomendadas.










## Bibliografía recomendada

![R In Action por Robert  Kabacoff](https://images.manning.com/720/960/resize/book/1/82c427b-3e8b-423d-b49f-948cebab0a0b/kabacoff2_cover.png)

PAM es por lejos el más comunmente utilizado, pero existen otros como *CLARA*, *MELISSA*, y otros tantos que se adaptan a diferentes problemas. En el caso de la localización de las balizas de satélites como el ARSAT e incluso de los nano satélites como el FossaSat-1 (cubesat) este método es muy utilizado. Ver [Satelites para internet de las cosas Industriales](https://www.hackster.io/news/fossasat-1-an-open-source-satellite-for-the-internet-of-things-7f31cab00ef5).
Todas estas tecnologías de satélites de bajo costo están permitiendo mejorar la competitividad y eficiencia de las cadenas de suministros en todo el planeta. En especial esta tipo de tecnología sirve para ver el deterioro de las propiedades alimenticias de cargas en línea y en tiempo real.  A pesar de ello en gran parte de latinoamérica y caribe estas tecnología aún están por descubrirse.
Se han utilizado varios métodos del **skimr()** (un sustituto de **summary()** ), pero el paquete que utilizaremos para esta tarea específica será **cluster()** paquete exitosamente para problemas de congestion de puertos y misiones de vacunación post covid de el paquete :  [ClusteR](https://cran.r-project.org/web/views/Cluster.html)  




## Agrupación K-means 

El método de partición más común es el análisis de clúster de K-means. Conceptualmente, el algoritmo K-means: 

1. Selecciona K centroides (K filas elegidas al azar) 
2. Asigna cada punto de datos a su centroide más cercano 
3. Recalcula los centroides como el promedio de todos los puntos de datos en un clúster (es decir, los centroides son vectores medios de p-longitud, donde p es el número de variables) 
4. Asigna puntos de datos a sus centroides más cercanos 
5. Continúa los pasos 3 y 4 hasta que no se reasignen las observaciones o se alcance el número máximo de iteraciones (R usa 10 como valor predeterminado). [@bezerra_extracting_2019]

Los detalles de implementación de este enfoque pueden variar. R utiliza un algoritmo eficiente de Hartigan y Wong (1979) que divide las observaciones en grupos k de tal manera que la suma de cuadrados de las observaciones a sus centros de clúster asignados es un mínimo. Esto significa que en los pasos 2 y 4, cada observación se asigna al clúster con el valor más pequeño de:

$$ SS_{(k)}= \sum_{i=1}^n  \sum_{j=1}^p( x_{ij}- \bar{x_{kj}}) ²$$
Donde $k$ es un cluster, $x_{ij}$ es el valor de la variable $j ésima$ para la observación $iésima$, y $\bar{x}_{kj}$ es la media de la variable j_{p} para el cluster k_i . 

La agrupación en clústeres K-means puede manejar conjuntos de datos más grandes que los enfoques de clúster jerárquicos. Además, las observaciones no se comprometen permanentemente a un grupo. Se mueven cuando al hacerlo mejora la solución general. Sin embargo, el uso de medioides implica que todas las variables deben ser continuas y el enfoque puede verse gravemente afectado por valores atípicos. Por ejemplo k-means no es aplicable para localización de pallets en sistemas de posición flotante si dentro del edificio hay muros o barreras que impiden la circulación entre racks.[@runkler_data_2020]

También se desempeñan mal en presencia de grupos no convexos (por ejemplo, en forma de U o celdas de manufactura flexible). El formato de la función K-means en R es:

$$kmeans(x, centros)$$ 
donde $x$ es un conjunto de datos numéricos (matriz o data.frame) y $centros$ es el número de clústeres a extraer. Es un parámetro arbitrario que elijo y con el que pruebo o simulo alternativas. Por su bajo costo computacional converge razonablemente bien a una solución. 

La función devuelve la pertenencia de casos al clúster, los centroides, las sumas de cuadrados (dentro, entre y total) y los tamaños de cada clúster.

Dado que el análisis de clústeres de K-medias comienza con k centroides elegidos al azar, se puede obtener una solución diferente cada vez que se invoca la función.
Utilice la función set.seed() para garantizar que los resultados sean reproducibles, en especial si publicas en papers. 

![Convergencia de K-Means(Gentileza de Wikicommons )](images/K-means_convergence.gif)
Además, este enfoque de agrupación puede ser sensible a la selección inicial de centroides. La función $kmeans()$ tiene una opción o parámetro $nstart$ que intenta varias configuraciones iniciales e informa sobre la mejor. Por ejemplo, agregando $nstart=25$ generará 25 configuraciones iniciales. Este enfoque a menudo muy recomendable. A diferencia de la agrupación jerárquica, la agrupación en clústeres de *K-means* requiere que el número de clústeres que se extraer se especifique de antemano. Una vez más, el paquete *NbClust()* se puede utilizar como guía para estimar un número inicial de clusters acpetable. Además, puede ser útil un gráfico de las sumas totales de cuadrados dentro de los grupos contra el número de clústeres en una solución de K-means. Una curva en el gráfico puede sugerirnos el número apropiado de clústeres. [@li_nonparametric_2021]

El gráfico se puede producir mediante la siguiente función.




A efectos de sostener un estilo único en los gráficos amenudo conviene crear una función de ploteo en la que repito los parámetros.


```{r}
wssplot <- function(data, nc=15, seed=1234){
               wss <- (nrow(data)-1)*sum(apply(data,2,var))
               for (i in 2:nc){
                    set.seed(seed)
                    wss[i] <- sum(kmeans(data, centers=i)$withinss)}
                plot(1:nc, wss, type="b", xlab="Número de Clusters",
                     ylab="Suma cuadrática dentro de cada grupo")}
```


El parámetro de datos es el conjunto de datos numéricos que se analizará, $nc$ es el número máximo de grupos a considerar y la semilla es una semilla de número aleatorio. Aquí, se analiza un conjunto de datos que contiene 13 mediciones químicas en 178 muestras de vino italiano. Los datos provienen originalmente del Repositorio de Aprendizaje Automático de la UCI (http://www.ics.uci.edu/~mlearn/MLRepository.html), pero también se pueden acceder a ellos a través del paquete de [rattle](https://cran.r-project.org/web/packages/rattle.data/index.html). 
En el listado se proporciona un análisis de conglomerado de K-means para los datos.[@kumar_colour_2022]




```{r}
library(readr)
wine <- read_csv("http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data")
```

*Dimensiones:*

columna | Propiedad
--------+-----------
  1) |Alcohol
 	2) |Ácido Malico
 	3) |Cenizas
	4) |Alcalinidad de las cenizas  
 	5) |Magnecio
	6) |Fenoles Totales 
 	7) |Flavonoides 
 	8) |Fenoles no flavonoides 
 	9) |Proantocianinas 
	10)|Intensidad de Color 
 	11)|Tinte
 	12)|OD280/OD315 de vinos diluídos
 	13)|Prolina          

```{r}
nombres <- list( "Type", 
  "Alcohol",
"Ácido Malico",
 "Cenizas",
"Alcalinidad de las cenizas"  ,
 "Magnecio",
"Fenoles Totales", 
 "Flavonoides" ,
"Fenoles no flavonoides", 
 "Proantocianinas" ,
	"Intensidad de Color", 
 	"Tinte",
 	"OD280/OD315 de vinos diluídos",
"Prolina"                )


colnames(wine) <- nombres

```


Generaremos un reporte exploratorio automático con la biblioteca skim

```{r}
library(skimr)
skim(wine)
```


Procederemos a escalar el dataset, que es un poco menos eficiente que normalizar, pero es más rápido y nos muestra algunas de las herramientas de la biblioteca **skimr**. [@chen_evidential_2018]

```{r}
df <- scale(wine[-1]) 
wssplot(df)     
```


Cargaremos la biblioteca **NbClust()** para usar el método kmeasn que ella proporciona. 

```{r}
library(NbClust)
set.seed(1234)
nc <- NbClust(df, min.nc=2, max.nc=15, method="kmeans")
table(nc$Best.n[1,])
```
Dado que las variables varían en rango, se estandarizan antes de la agrupación (función $scale()$) es muy importante utiulizarla ya que esta biblioteca es muy sensible al error si no se aplica normalizado.

A continuación, el número de clústeres se determina mediante las funciones *wwsplot()* y $NbClust()$ . La Figura  indica que hay una clara caída en la suma de cuadrados dentro de los grupos cuando se pasa de 1 a 3 grupos. Después de tres clústeres, esta disminución disminuye, lo que sugiere que una solución de 3 clústeres puede ser una buena opción para los datos. 

En la siguiente figura, 14 de los 24 criterios proporcionados por el paquete $NbClust$ sugieren una solución de 3 clústeres. 

Tenga en cuenta que no se pueden calcular los 30 criterios para cada conjunto de datos. Se obtiene una solución final de clúster con la función kmeans() y se imprimen los centroides de clúster. 

Dado que los centroides proporcionados por la función se basan en datos estandarizados, la función $aggregate()$ se utiliza junto con las pertenencias al clúster para determinar las medias variables para cada clúster en la métrica original (o desescalando).

```{r}
barplot(table(nc$Best.n[1,]), 
          xlab="Numer of Clusters", ylab="Number of Criteria",
          main="Number of Clusters Chosen by 26 Criteria")
```

¿Cuantas muestras hay en cada grupo?

```{r}
set.seed(1234)
fit.km <- kmeans(df, 3, nstart=25)                           #3
fit.km$size
```

*Dónde estan los centroides?*

```{r}
fit.km$centers  
```

Mira con detenimiento los valores entregados por $$fit$(...)$$


```{r}
plot(fit.km$centers)
```



*Matriz de confusión*

```{r}
ct.km <- table(wine$Type, fit.km$cluster)
ct.km  
```



Como podemos ver se nos ha indicado que es muy probable que existan **3 categorías** o grupos en los que podemos clasificar o etiquetar este dataset.
La matriz de confusión es muy buena.


