Un clustering jerárquico intenta construir una jerarquía a través de divisiones de nuestros datos de forma aglomerativa o dividiendo los datos. Aglomerativa hace agrupacionos de form individual o de forma que se dividan los datos. Estos elementos usan las distáncias para decdiri que clusters deben agruparse y cuáles deben dividirse. Es un proceso recursivo que continua hasta que solo queda un cluster en el caso del aglomerativo, o bien en el caso del divisitivo, hasta que no queda nada más que dividir o repartir en un nuevo cluster.
Usamos el dendograma para representar la jerarquía de clusers.
Usaremos el consumo de proteinas en europa:
protein <- read.csv("../DataSets//protein.csv")
Ignoraremos la varaible categorica de country al ser categórica. Vamos a normalizar y escalar los datos para poder hacer el dendograma:
data <- as.data.frame(scale(protein[,-1])) # quitamos la primera columna
data$Country = protein$Country # volvemos a añadir el país
Vamos a hacer un clustering aglomerativo para ver los paíssi que se acercan con el consumo de proteinas:
rownames(data) = data$Country # damos nombre a las filas con los países
hc <- hclust(dist(data, method = "euclidean"), # con dist indicaremos la distáncia del clustering, usaremos el metodo euclidean, la distancia más usada
method = "ward.D2") # metodo de clusterización para decidir como se hora el nuevo cluster a partir del anterior, es le método de la mínima varianza para hacer un cluster aglomerativo y el que mejor funciona, dado que pondera según el número de elementos del dataset
## Warning in dist(data, method = "euclidean"): NAs introducidos por coerción
hc
##
## Call:
## hclust(d = dist(data, method = "euclidean"), method = "ward.D2")
##
## Cluster method : ward.D2
## Distance : euclidean
## Number of objects: 25
Podemos ver que se han clasificado nuestros 25 países. Vamos a visualizar el cluster:
plot(hc, hang = -0.01, cex = 0.7)
Podemos usar otros métodos, como el simple:
hc2 <- hclust(dist(data, method = "euclidean"),
method = "single") # usamos el metodo simple, método aglometarivo
## Warning in dist(data, method = "euclidean"): NAs introducidos por coerción
plot(hc2, hang=-0.01, cex = 0.7) # hang nos permite poner las etiquetas al final
El método de construcción del cluster determina la forma del dendograma.
EL clustering jerárquico aglomerativo se toma un enfoque de abajo hacia arriba, cada observación del dataset es un cluster en si mismo, y luego se van computando las similitudes o las distancias de cada uno de esos elementos al resto. Juntan aquellos que tengan mas elemento en común o esten a menos distancia, hasta que solo quede un solo cluster.
El método divisitivo empieza desde arriba hacia abajo, todas las observaciones empiezan en un solo cluster, y luego van haciendo divisiones sucesivas en dos o más clusters recursivamente, hasta que solo queda un cluster para cada una de las observaciones.
d <- dist(data, method = "euclidean")
## Warning in dist(data, method = "euclidean"): NAs introducidos por coerción
La anterior matriz nos ha calculado la distancia para cada uno de los países, en cuando al consumo de proteinas. La distáncia euclidia nos compara las coordenadas de las variables.
Vemos el vector de albania:
alb<-data["Albania",-10]
alb
aus<-data["Austria",-10]
aus
# Miramos las distancias entre los dos países haciendo el teorema de pitágoras
sqrt(sum((alb-aus)^2))
## [1] 6.136051
# Calculamos
sum(abs(alb-aus))
## [1] 15.97134
Otros ejemplos de métodos:
hc3 <- hclust(dist(data, method = "euclidean"),
method = "complete")
plot(hc3, hang=-0.01, cex = 0.7)
Para entender las distáncias hemos de entender la variable “merge”, que nos idnica con quién ha sido juntado y en que orden:
head(hc3$merge, 10)
## [,1] [,2]
## [1,] -18 -25
## [2,] -2 -14
## [3,] -6 -20
## [4,] -3 -24
## [5,] -12 4
## [6,] -5 -7
## [7,] -4 1
## [8,] -15 3
## [9,] -10 -13
## [10,] -21 2
En primer lugar nos junta el país número 18 con el número 25, el valor (-) nos indica los objetos básicos. Ejemplo:
Rumania(-18) y Yugoslavia(-25)
Austria(-2) y Países Bajos(-14)
Cuando empezamos a tener números positivos es cuando se emmpiezan a juntar diferentes clusters, en este caso el 4 cluster(Belgia y Alemania) se junta con Irlanda.
library(cluster)
Haremos uso de la función diana, que perite hacer clusterings divisitivos en lulgar de los aglomeravitos, le debemos pasar le dataset original y la distáncia para que haga las divisiones:
dv <- diana(data, metric = "euclidean")
par(mfrow=c(1,2))
plot(dv)
Podemos ver las divisiones que se han llevado gracias a las distancias que imprime por pantalla para cada país. Pdemos ver la profundidad en la quese juntan los diferentes países. Irlanda e Italia no se juntan hasta el final.
Haciendo cortes del dendograma para separ los cluster con la función cut tree:
fit <- cutree(hc, k=4) # con esta función agrupamos los países en 4 categorías
table(fit) # podemos ver los 4 clusters en la tabla
## fit
## 1 2 3 4
## 4 12 5 4
plot(hc, hang = -0.01, cex = 0.7)
rect.hclust(hc, k=4, border="red") # representa con cajitas encuma del plot
Podemos ver que hemos cortado entre 6 y 7. Para k = 5 nos saldría más bajo.
Es una técnica de partición de clustering que se enfoca en dividir n observaciones iniciales en k clusters, de modo que cada observación pertenece al cluster cuyo promedio esté más cercano, sirivendo este como el prototipo del cluster.
Es un método menos cosotos computacionalmente que los anteriores y también más rápido.
Usaremos el mismo dataset de proteinas que hemos usado anteriormente:
protein <- read.csv("../DataSets/protein.csv")
rownames(protein) = protein$Country
protein$Country = NULL
protein.scaled = as.data.frame(scale(protein))
Usaremos la libreria devtools, una librería de git_hub(). Esta librería nos permitirá visualizar los clusters de k means, en el caso que tengamos muchas variables.
library(devtools)
# devtools::install_github("kassambara/factoextra") # ponemos el usuario de git hub dentro de kassambara
Esta libreria nos hace un PCA de forma automática, es una básica para cualquier analista de datos.
Creamos el k-mean:
km <- kmeans(protein.scaled,5) # le pasamos el dataset escalado
km
## K-means clustering with 5 clusters of sizes 2, 5, 10, 2, 6
##
## Cluster means:
## RedMeat WhiteMeat Eggs Milk Fish Cereals
## 1 -0.94948480 -1.1764767 -0.74802044 -1.4583242 1.8562639 -0.3779572
## 2 1.59900650 0.2988565 0.93413079 0.6091128 -0.1422470 -0.5948180
## 3 -0.12189736 0.6101653 0.39727402 0.5711137 0.2486383 -0.6175974
## 4 -0.06811911 -1.0411250 -0.07694947 -0.2057585 0.1075669 0.6380079
## 5 -0.79014185 -0.5267887 -1.16557572 -0.9047559 -0.9504683 1.4383272
## Starch Nuts Fr.Veg
## 1 0.9326321 1.1220326 1.8925628
## 2 0.3451473 -0.3484949 0.1020010
## 3 0.3573866 -0.8823165 -0.3802865
## 4 -1.3010340 1.4997366 1.3659270
## 5 -0.7604664 0.8870168 -0.5373533
##
## Clustering vector:
## Albania Austria Belgium Bulgaria Czechoslovakia
## 5 3 2 5 3
## Denmark E Germany Finland France Greece
## 3 3 3 2 4
## Hungary Ireland Italy Netherlands Norway
## 5 2 4 3 3
## Poland Portugal Romania Spain Sweden
## 3 1 5 1 3
## Switzerland UK USSR W Germany Yugoslavia
## 2 2 5 3 5
##
## Within cluster sum of squares by cluster:
## [1] 4.300578 12.069794 37.502503 2.311516 24.091128
## (between_SS / total_SS = 62.8 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss"
## [5] "tot.withinss" "betweenss" "size" "iter"
## [9] "ifault"
El objeto nos devuelve como estan divididos los 4 clusters. Importante fijarse en el porcentaje de los datos que quedan explicados con este número de clusters: en este caso seá un 66.7%
Podemos saber la media del consumo de cada una de las variables:
aggregate(protein.scaled, by = list(cluster = km$cluster), mean)
Podemos ver la información de cada clusters, para entender las variables escaladas para cada una de las variables. Vamos a visualizar los datos:
library(factoextra)
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_cluster(km, data = protein.scaled)
Importante para clusterización, debemos fijarnos en los outliers porque pueden afectar mucho a la creación de los clusters.
Esta técnica es una variante muy útil para e tratamiento de imágenes. Randomiza, coe muestras aleatorias, para optimizar la función objetivo en su lugar.
library(OpenImageR)
library(ClusterR)
## Loading required package: gtools
img <- readImage("../Images/bird.jpg")
class(img)
## [1] "array"
Podemos redimiensionar la imagen para que sea más óptima de analizar:
img.resize <- resizeImage(img, 350, 350,
method = "bilinear") # hay diferentes metodos, a que usaremos billinear que reduce el efecto de pixelado
imageShow(img.resize) # nos mostraría la imagen si lo intoducimos en a consola de R
Ahora vamos a ver la dimension de la misma:
img.vector <- apply(img, 3, as.vector) # creamos una matriz de 3 en 3
dim(img.vector) # nos muestra cada uno de los pixeles en 3 columnas
## [1] 113232 3
Ahora usaremos el método mini batch k means para predecir el color de un pixel en relación al pixel más cercano:
kmmb<-MiniBatchKmeans(img.vector, clusters = 10, # le pasamos el vector que hemos creado, optaremos por poner 10 cluester, que representan el númer de colores que hay en la imagen (elegimos a ojo humano)
batch_size = 20, num_init = 5,
max_iters = 100, init_fraction = 0.2,
initializer = "kmeans++",
early_stop_iter = 10, verbose = F) # que no se pare núnca hasta la iteración 10
kmmb
## $centroids
## [,1] [,2] [,3]
## [1,] 0.45882353 0.4352941 0.3921569
## [2,] 0.98431373 0.2352941 0.2980392
## [3,] 0.08627451 0.2627451 0.3529412
## [4,] 0.40000000 0.5411765 0.1490196
## [5,] 0.09215686 0.2568627 0.4352941
## [6,] 0.21288515 0.2957983 0.1697479
## [7,] 0.14852941 0.1946078 0.1142157
## [8,] 0.87450980 0.6078431 0.1019608
## [9,] 0.57647059 0.6862745 0.5784314
## [10,] 0.36078431 0.4980392 0.7176471
##
## $WCSS_per_cluster
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,] 0.004398308 0.004183007 0 0 0.01051903 0.07852364 0.05783929
## [,8] [,9] [,10]
## [1,] 0 0 0
##
## $best_initialization
## [1] 1
##
## $iters_per_initialization
## [,1] [,2] [,3] [,4] [,5]
## [1,] 29 16 10 11 17
##
## attr(,"class")
## [1] "k-means clustering"
Ahora usaremos el array veccotrial para ver la predicción:
prmb <- predict_MBatchKMeans(img.vector, kmmb$centroids) # añadimos los centroides que el modelo ha predecido
Vemos los resultados de la predicción:
get.cent.mb <- kmmb$centroids
new.img <- get.cent.mb[prmb,] # nueva imagen en función a los valores predichos
dim(new.img) <- c(nrow(img), ncol(img),3) # redimensionamos l aimagen con el número de filas de la imagen original, y número de columnas de 3 en 3
imageShow(new.img) # muestrame la imagen en consola
Es una variante de k-mean, intenta agrupar los datos alrededor de los medoides. Es una mejora al algoritmo. Es un algoritmo que busca minamizar la distancia entre los puntos que se añaden en el grupo respecto al centro. El centro es un medoide, un objeto del grupo que más se parece al resto del grupo, se acostumbre a encontrar más al centro geometricamente.
importante siempre escalamos para evitar outliers y que ninguna variable domine sobre el resto
Volveremos a hacer uso del dataset anterior:
protein <- read.csv("../DataSets/protein.csv")
rownames(protein) = protein$Country
protein$Country = NULL
protein.scaled <- as.data.frame(scale(protein))
Usaremos la libreria cluster y facotrextra del repositorio de github, y la punción PAM (Partition Around Medoids):
library(cluster)
library(factoextra)
km <- pam(protein.scaled, 4) # evitamos usar la media como centro geometrica, se basa en buscar los k medoides entre todos los datos del dataset
km
## Medoids:
## ID RedMeat WhiteMeat Eggs Milk Fish
## Romania 18 -1.0839304 -0.43204252 -1.2848772 -0.8461152 -0.9651632
## W Germany 24 0.4696633 1.24631815 1.0415022 0.2375653 -0.2598064
## Sweden 20 0.0215113 -0.02598752 0.5046454 1.0679178 0.9451781
## Spain 19 -0.8150392 -1.21708219 0.1467409 -1.1979595 0.7982288
## Cereals Starch Nuts Fr.Veg
## Romania 1.5810786 -0.7196689 1.1220326 -0.7406162
## W Germany -1.2435778 0.5654541 -0.7916675 -0.1862628
## Sweden -1.1615716 -0.3524909 -0.8420280 -1.1840990
## Spain -0.2777275 0.8714358 1.4241958 1.6985391
## Clustering vector:
## Albania Austria Belgium Bulgaria Czechoslovakia
## 1 2 2 1 2
## Denmark E Germany Finland France Greece
## 3 2 3 2 4
## Hungary Ireland Italy Netherlands Norway
## 1 2 4 2 3
## Poland Portugal Romania Spain Sweden
## 2 4 1 4 3
## Switzerland UK USSR W Germany Yugoslavia
## 2 2 1 2 1
## Objective function:
## build swap
## 1.847172 1.839215
##
## Available components:
## [1] "medoids" "id.med" "clustering" "objective" "isolation"
## [6] "clusinfo" "silinfo" "diss" "call" "data"
Podemos ver que a diferencia de antes no tenemos las medias, sino los medoides. Los medoides son los paises como Romania, W germany, Sweden y Spain.
Vamos a representar los datos:
fviz_cluster(km)
Podemos ver como los países que se suponen medoides estan más en el centro.
Es una técnica muy útil en el caso que tengamos datasets granes para reducir el costed de computación.
Aplica la partición alrededor de medoides, como el anterior algortimo.
Seguimos con el dataset anterior:
clarafit <- clara(protein.scaled, 4, samples = 6) # especificamos le número de k y el número de muestras que queremos que nos haga
clarafit
## Call: clara(x = protein.scaled, k = 4, samples = 6)
## Medoids:
## RedMeat WhiteMeat Eggs Milk Fish
## Romania -1.0839304 -0.43204252 -1.2848772 -0.8461152 -0.9651632
## W Germany 0.4696633 1.24631815 1.0415022 0.2375653 -0.2598064
## Sweden 0.0215113 -0.02598752 0.5046454 1.0679178 0.9451781
## Spain -0.8150392 -1.21708219 0.1467409 -1.1979595 0.7982288
## Cereals Starch Nuts Fr.Veg
## Romania 1.5810786 -0.7196689 1.1220326 -0.7406162
## W Germany -1.2435778 0.5654541 -0.7916675 -0.1862628
## Sweden -1.1615716 -0.3524909 -0.8420280 -1.1840990
## Spain -0.2777275 0.8714358 1.4241958 1.6985391
## Objective function: 1.839215
## Clustering vector: Named int [1:25] 1 2 2 1 2 3 2 3 2 4 1 2 4 2 3 2 4 1 ...
## - attr(*, "names")= chr [1:25] "Albania" "Austria" "Belgium" "Bulgaria" "Czechoslovakia" "Denmark" "E Germany" ...
## Cluster sizes: 6 11 4 4
## Best sample:
## [1] Albania Austria Belgium Bulgaria
## [5] Czechoslovakia Denmark E Germany Finland
## [9] France Greece Hungary Ireland
## [13] Italy Netherlands Norway Poland
## [17] Portugal Romania Spain Sweden
## [21] Switzerland UK USSR W Germany
## [25] Yugoslavia
##
## Available components:
## [1] "sample" "medoids" "i.med" "clustering" "objective"
## [6] "clusinfo" "diss" "call" "silinfo" "data"
Tiene la misma estructira que PAM. Visualizamos los datos y vemos los mismos resultados que antes.
fviz_cluster(clarafit)
El clustering puede tenre tendencia a generar clusters donde no debería o ser muy sensible a los outliers. Para ello es importante validar los clusters creados, a través de:
la validación relativa del clustering, cambiando el nombre de k
la validación interna del cluster creado, se analiza la silueta de este o el índice de “dunn”
la vlaidación externa del cluster del usuario para saber como se deberian agrupar los clusters (se usa para elegir el algoritmo que puede ayudar a hacer las agrupaciones en un datset determinado)
la validación de estabilidad del cluster, donde se comparan los clusters sacando datos
Usarmos diferentes librerias:
library(factoextra)
library(cluster)
library(fpc)
library(NbClust)
Cargamos le dataset:
protein <- read.csv("../DataSets/protein.csv")
rownames(protein) = protein$Country
protein$Country = NULL
protein.scaled <- as.data.frame(scale(protein))
Usaremos la función nbClust para encontrar el número óptimo de clusters:
nb <- NbClust(protein.scaled, distance = "euclidean", # usamos la distancia euclidia
min.nc = 2, max.nc = 12, # mínimo y máximo nº de clusters
method = "ward.D2", index = "all") # que téncica usaremos para el cluster aglomerativo
## Warning in pf(beale, pp, df2): NaNs produced
## *** : The Hubert index is a graphical method of determining the number of clusters.
## In the plot of Hubert index, we seek a significant knee that corresponds to a
## significant increase of the value of the measure i.e the significant peak in Hubert
## index second differences plot.
##
## *** : The D index is a graphical method of determining the number of clusters.
## In the plot of D index, we seek a significant knee (the significant peak in Dindex
## second differences plot) that corresponds to a significant increase of the value of
## the measure.
##
## *******************************************************************
## * Among all indices:
## * 6 proposed 2 as the best number of clusters
## * 7 proposed 3 as the best number of clusters
## * 3 proposed 6 as the best number of clusters
## * 1 proposed 7 as the best number of clusters
## * 1 proposed 10 as the best number of clusters
## * 5 proposed 12 as the best number of clusters
##
## ***** Conclusion *****
##
## * According to the majority rule, the best number of clusters is 3
##
##
## *******************************************************************
Entiendiendo los resultados:
Para estar más seguros, podemos visualizar los resultados:
fviz_nbclust(nb) + theme_minimal()
## Among all indices:
## ===================
## * 2 proposed 0 as the best number of clusters
## * 1 proposed 1 as the best number of clusters
## * 6 proposed 2 as the best number of clusters
## * 7 proposed 3 as the best number of clusters
## * 3 proposed 6 as the best number of clusters
## * 1 proposed 7 as the best number of clusters
## * 1 proposed 10 as the best number of clusters
## * 5 proposed 12 as the best number of clusters
##
## Conclusion
## =========================
## * According to the majority rule, the best number of clusters is 3 .
Ya nos muestra los resultados de k = 3. Ahora podemos usar 3 como la variables k:
km.res <- kmeans(protein.scaled, 3)
sil.km <- silhouette(km.res$cluster,
dist(protein.scaled))# calculanos la distancia de los objetos iniciales
sil.sum <- summary(sil.km)
sil.sum
## Silhouette of 25 units in 3 clusters from silhouette.default(x = km.res$cluster, dist = dist(protein.scaled)) :
## Cluster sizes and average silhouette widths:
## 4 10 11
## 0.4187964 0.1936819 0.2068237
## Individual silhouette widths:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -0.03801 0.14773 0.23808 0.23548 0.32609 0.46940
Nos muestra la silueta de los clusters, vamos a visualizar los resultados:
fviz_silhouette(sil.km)
## cluster size ave.sil.width
## 1 1 4 0.42
## 2 2 10 0.19
## 3 3 11 0.21
Podemos ver tantas barras como países en el dataset. Podemos ver variables relavantes como:
Compacidad: Como de comptacto estan los datos
Conectividad: Como de conectados estan los datos
Como de separados estan los datos
Esto lo podemos ver con el análisis de la silueta del k-means, y el valor de “dunn”.
Cuando vemos que la mayoría de países están más lejos de 0, mejor. Los que son negativos o alrededor de 0 quiere decir que estan muy cerca de otros clusters. La linea roja muestra el promdeio de las distancias entre los distintos clusters.
En el caso de valores negativos, puede que ese país debería estar en otro cluster.
fviz_cluster(km.res, data = protein.scaled)
Seguimos con el análisis de la métrica “dunn”:
dd <- dist(protein.scaled, method = "euclidean") # cremaos una variables para analizar la distancia
km_stats <- cluster.stats(dd, km.res$cluster) # calculamos lla distancia respecto los clusters
km_stats$within.cluster.ss # suma de los cuadrados internos del cluster y se suman todos
## [1] 114.7435
km_stats$clus.avg.silwidths # distancia dentro de cada uno de los clusters (promedio)
## 1 2 3
## 0.4187964 0.1936819 0.2068237
km_stats$dunn # Este índice es el cociente entre la distancia más pequeña entre obervaciones que no estan en el mismo cluster entre la distancia de cada elemento de cada cluster. Este valor oude acercarse a 0 o ir hasta infinito, y el objetivo es hacer crecer esta distancia para saber que se ha hecho una buena separación.
## [1] 0.3618008
Vamos a intentar mazimezar el índicie de “dunn”:
kmed <- pam(protein.scaled, 3)
sil.kmed <- silhouette(kmed$clustering,
dist(protein.scaled))
fviz_cluster(kmed, data = protein.scaled)
fviz_silhouette(sil.kmed)
## cluster size ave.sil.width
## 1 1 6 0.31
## 2 2 15 0.38
## 3 3 4 0.21
kmed_stats <- cluster.stats(dd, kmed$clustering)
kmed_stats$within.cluster.ss
## [1] 105.9863
kmed_stats$clus.avg.silwidths
## 1 2 3
## 0.3062056 0.3811136 0.2063242
kmed_stats$dunn
## [1] 0.5678917
Vemos que el indice ha mejorado mucho usando el algorimto de cluusterización de pam. Vemos que la USSR, su silueta es cercana a 0, indicando que podría formar parte de otro cluster.
Podemos analizar otras métricas relevantes:
# comparamos dos algoritmos con las siguientes metricas:
res.com <- cluster.stats(dd, km.res$cluster,
kmed$clustering)
# Indice de corrección aleatoria, indica la similitud entre los dos clusters. El objetivo es maximizarlo:
res.com$corrected.rand
## [1] 0.5243425
# Variación de la información: distancia que existe entre los dos clusters, es una metrica que debe ser minimizada
res.com$vi
## [1] 0.6171538
Los clusters analizados anteriormente encuentran clusters de forma esfeica o convexa, y usan la eurítica para crear los grupos. Esto sistema se ve muy afectado por el ruido en la información, outliers. Vamos a ver dos técnicas más avanzadas:
Usaremos los puntos de un data set como puntos del cluster, del oborde o de ruido, segun si son alcanzables a cierta distancia, a cierta densidad o si estan muy conectados.
Usaremos el dataset multishapes del paquete factoextra:
library(fpc)
library(factoextra)
data("multishapes", package = "factoextra")
# Seleccionamos los datos
par(mfrow=c(1,1))
head(multishapes)
dataPoints <- multishapes[,1:2]
plot(dataPoints)
Vemos que estos puntos siguen una distribución difícil de definir con formas a través de un k-means. Probemos como sería usando un k-means:
km <- kmeans(dataPoints, 5)
fviz_cluster(km, data= dataPoints)
Podemos ver que separa el círculo interior cuando debería juntarlo. El poblema de este dataset es que tiene información que sobra. Usamos otra medotología:
dsFit <- dbscan(dataPoints,
eps = 0.15, MinPts = 5) # parámetro epsilon, que es el radio más pequeño entre vecinos, y puntos mínimos, no crear un cluster a mínimo que hayan 5 punto en el vecindario
dsFit
## dbscan Pts=1100 MinPts=5 eps=0.15
## 0 1 2 3 4 5
## border 31 24 1 5 7 1
## seed 0 386 404 99 92 50
## total 31 410 405 104 99 51
Cuando hacemo sun clustering basados en densidades intentamos llevar a cabo representaciones más allá de las lineales.
Se llama punto del borde aquellos que sus vecinos son inferiores a minimum points. Después tenemos los puntos que estan solos.
Representamos los clusers creados:
fviz_cluster(dsFit, dataPoints, geom = "point")
library(mclust)
## Package 'mclust' version 5.4.2
## Type 'citation("mclust")' for citing this R package in publications.
mclust <- Mclust(dataPoints) # usamos el dataset anterior
plot(mclust)
summary(mclust)
## ----------------------------------------------------
## Gaussian finite mixture model fitted by EM algorithm
## ----------------------------------------------------
##
## Mclust VEV (ellipsoidal, equal shape) model with 9 components:
##
## log.likelihood n df BIC ICL
## -2062.757 1100 45 -4440.653 -4577.743
##
## Clustering table:
## 1 2 3 4 5 6 7 8 9
## 134 187 112 132 128 142 108 104 53
Este proceso es ideal para elegir variables relevantes para entender los datos:
bh <- read.csv("../DataSets//BostonHousing.csv")
library(corrplot)
## corrplot 0.84 loaded
corr <- cor(bh[,-14])
corrplot(corr, method = "circle")
Con la matriz de correlaciones podremos reducir el tamaño del dataset conservando solo las variables relevantes.
Hacemos el análisis de componentes principales:
bh.acp <- prcomp(bh[,-14], scale = T) # con scale igual a true creara el acp a través del modelo de correlaciones:
#scale = T, matriz de correlaciones
#scale = F, matriz de covarianzas
summary(bh.acp)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 2.4752 1.1972 1.11473 0.92605 0.91368 0.81081
## Proportion of Variance 0.4713 0.1103 0.09559 0.06597 0.06422 0.05057
## Cumulative Proportion 0.4713 0.5816 0.67713 0.74310 0.80732 0.85789
## PC7 PC8 PC9 PC10 PC11 PC12
## Standard deviation 0.73168 0.62936 0.5263 0.46930 0.43129 0.41146
## Proportion of Variance 0.04118 0.03047 0.0213 0.01694 0.01431 0.01302
## Cumulative Proportion 0.89907 0.92954 0.9508 0.96778 0.98209 0.99511
## PC13
## Standard deviation 0.25201
## Proportion of Variance 0.00489
## Cumulative Proportion 1.00000
Podemos ver como con pc1 explicamos el 47% de los datos, para pc2 será 58% y subiendo.
plot(bh.acp, type = "lines")
Otras forma de visualización:
biplot(bh.acp, col = c("gray", "red"))
Ahora podemos ver para cada una de las componentes que peso tienen cad auna de las variables.
head(bh.acp$x,5)
## PC1 PC2 PC3 PC4 PC5 PC6
## [1,] -2.096223 0.772348426 0.34260368 0.8908924 0.4226521 -0.3150264
## [2,] -1.455811 0.591399952 -0.69451201 0.4869766 -0.1956820 0.2639620
## [3,] -2.072547 0.599046578 0.16695638 0.7384734 -0.9336102 0.4476516
## [4,] -2.608922 -0.006863826 -0.10018499 0.3433814 -1.1038636 0.6639924
## [5,] -2.455755 0.097615346 -0.07527372 0.4274838 -1.0648705 0.6164372
## PC7 PC8 PC9 PC10 PC11 PC12
## [1,] 0.3183257 -0.2955393 -0.42451671 -0.63957348 -0.03296774 -0.01942101
## [2,] 0.5533137 0.2234488 -0.16679701 -0.08415319 -0.64017631 0.12567304
## [3,] 0.4840809 -0.1050622 0.06970615 0.18020170 -0.48707471 -0.13319472
## [4,] 0.6220253 -0.2556877 -0.34190738 -0.04585594 -0.35985263 -0.50817472
## [5,] 0.7043889 0.1343911 -0.41725486 0.14074052 -0.39475923 -0.49723967
## PC13
## [1,] 0.365613514
## [2,] -0.070649578
## [3,] -0.014007936
## [4,] 0.007839164
## [5,] 0.014260153
Nos muestra para cada una de las obervacioens sus componentes principales.
bh.acp$rotation
## PC1 PC2 PC3 PC4 PC5
## CRIM 0.250951397 -0.31525237 0.24656649 -0.06177071 0.082156919
## ZN -0.256314541 -0.32331290 0.29585782 -0.12871159 0.320616987
## INDUS 0.346672065 0.11249291 -0.01594592 -0.01714571 -0.007811194
## CHAS 0.005042434 0.45482914 0.28978082 -0.81594136 0.086530945
## NOX 0.342852313 0.21911553 0.12096411 0.12822614 0.136853557
## RM -0.189242570 0.14933154 0.59396117 0.28059184 -0.423447195
## AGE 0.313670596 0.31197778 -0.01767481 0.17520603 0.016690847
## DIS -0.321543866 -0.34907000 -0.04973627 -0.21543585 0.098592247
## RAD 0.319792768 -0.27152094 0.28725483 -0.13234996 -0.204131621
## TAX 0.338469147 -0.23945365 0.22074447 -0.10333509 -0.130460565
## PTRATIO 0.204942258 -0.30589695 -0.32344627 -0.28262198 -0.584002232
## B -0.202972612 0.23855944 -0.30014590 -0.16849850 -0.345606947
## LSTAT 0.309759840 -0.07432203 -0.26700025 -0.06941441 0.394561129
## PC6 PC7 PC8 PC9 PC10
## CRIM -0.21965961 0.777607207 -0.153350477 0.26039028 -0.019369130
## ZN -0.32338810 -0.274996280 0.402680309 0.35813749 -0.267527234
## INDUS -0.07613790 -0.339576454 -0.173931716 0.64441615 0.363532262
## CHAS 0.16749014 0.074136208 0.024662148 -0.01372777 0.006181836
## NOX -0.15298267 -0.199634840 -0.080120560 -0.01852201 -0.231056455
## RM 0.05926707 0.063939924 0.326752259 0.04789804 0.431420193
## AGE -0.07170914 0.116010713 0.600822917 -0.06756218 -0.362778957
## DIS 0.02343872 -0.103900440 0.121811982 -0.15329124 0.171213138
## RAD -0.14319401 -0.137942546 -0.080358311 -0.47089067 -0.021909452
## TAX -0.19293428 -0.314886835 -0.082774347 -0.17656339 0.035168348
## PTRATIO 0.27315330 0.002323869 0.317884202 0.25442836 -0.153430488
## B -0.80345454 0.070294759 0.004922915 -0.04489802 0.096515117
## LSTAT -0.05321583 0.087011169 0.424352926 -0.19522139 0.600711409
## PC11 PC12 PC13
## CRIM -0.10964435 -0.086761070 0.045952304
## ZN 0.26275629 0.071425278 -0.080918973
## INDUS -0.30316943 0.113199629 -0.251076540
## CHAS 0.01392667 0.003982683 0.035921715
## NOX 0.11131888 -0.804322567 0.043630446
## RM 0.05316154 -0.152872864 0.045567096
## AGE -0.45915939 0.211936074 -0.038550683
## DIS -0.69569257 -0.390941129 -0.018298538
## RAD 0.03654388 0.107025890 -0.633489720
## TAX -0.10483575 0.215191126 0.720233448
## PTRATIO 0.17450534 -0.209598826 0.023398052
## B 0.01927490 -0.041723158 -0.004463073
## LSTAT 0.27138243 -0.055225960 0.024431677
Esta nos muestra el peso de cada variable para cada componente principal. Mostramos tambien la desviación standar:
bh.acp$sdev
## [1] 2.4752472 1.1971947 1.1147272 0.9260535 0.9136826 0.8108065 0.7316803
## [8] 0.6293626 0.5262541 0.4692950 0.4312938 0.4114644 0.2520104
Si nos quedamos con las 7 componentes (las 7 primeras), tenemos suficiente para explicar toda la información.