Está en la página 1de 45

Introduction to Data Mining

for Business Intelligence

Module 3
Principal Component Analysis – PCA
Module 4
Cluster analysis

PCA:

https://www.youtube.com/watch?v=oiR3k9H-7K0&ab_channel=LorenAraujo

CLÚSTER ANALYSIS: https://www.youtube.com/watch?v=7AFuL-1Q8eg&ab_channel=PabloVallejoMedina

CLÚSTER ANALYSIS 2: https://www.youtube.com/watch?v=zyixcd_WKUI&ab_channel=PabloVallejoMedina

https://en.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance

https://en.wikipedia.org/wiki/Canberra_distance

https://en.wikipedia.org/wiki/Chebyshev_distance
Ignacio Puertas García-Figueras UC3M

Principal Component Analysis - PCA


Let us remember the example of the flowers and the crimes in the
USA, both described by four characteristics in each case.
> data("iris")

> data("USArrests")

We want to move from high dimensional data (p variables) to


smaller dimensional data (k << p) using variables that will be
linear combinations of the original ones. There is a balance
between clarity of representation and oversimplification: if we
remove too many variables, we will lose relevant information.
The aim of PCA is to rigidly rotate the axes of p-dimensional
space to obtain the main axes, so The first main axis shows
the maximum variance, the second the second largest, etc. The
covariance between each pair of main axes is zero (the main axes
are uncorrected).
Each main axis is a linear
combination of the two original
variables:

PC1 is
both the direction of maximum
variance and the equation of
greatest fit to the data (the
sum of distances from each
point to the PC1 axis is

minimised).

Página 2 de 45
Ignacio Puertas García-Figueras UC3M

El análisis de componentes principales es una técnica de la


minería de datos que intenta reducir la dimensión de un conjunto
enorme de variables a un nuevo número de variables llamadas
componentes principales o factores latentes. Si estamos en
presencia de un conjunto de datos o base de datos muy grande con
varias variables es muy probables que estas variables estén
correladas entre sí. De ser así, es posible utilizar el análisis
de componentes principales para que nos ayude a comprender de
manera más fácil estos datos. ¿Cómo lo hace? El PCA crea un
nuevo conjunto de nuevas variables con menos datos que el
original, las variables del nuevo conjunto de datos se
denominaran componentes principales o factores latentes y no van
a estar correlados entre sí y van a ser expresados como
combinación lineal de las variables originales.
Antes de llevar a cabo este proceso es necesario llevar a cabo
el preprocesamiento de los datos, esto implica el análisis de
los datos o la detección de valores anómalos. Algunos métodos
son: hist() para entender la distribución de los datos,
boxplot() para comprobar la existencia de datos atípicos,
summary() para ver la descripción numérica del boxplot, pairs()
para observar las relaciones existentes entre las variables.
Como vamos a trabajar con PCA también será necesario llevar a
cabo el método cor() para ver la correlación de los datos entre
las variables originales, de ser así tiene sentido aplicar el
PCA. También es bueno comprobar si tenemos valores ausentes,
para ello which(is.na()). Después procedemos a la discretización
de los datos, el los que transformamos una variable de tipo
numérica a una variable de tipo categórica, por ejemplo, la
variable gender en la que hay ceros y unos, podemos asignar Male
a 0 y Female a 1. A continuación procedemos a la numerización,
que es el proceso inverso a la discretización, es decir, si
tenemos una variable de tipo nominal o categórica, podemos
transformarla en una variable numérica. Por último, llevamos a
cabo la normalización de los datos, que consiste en escalar los
datos, representarlos en una misma magnitud. Este paso se puede
llevar a cabo a partir de varios métodos, pero el más utilizado
es la estandarización, que consiste en restar a cada variable su
media y dividirla por su desviación estándar. Para ello
necesitaremos usar la función scale(). Ejemplo: datosEscalados =
scale(datos).
Ahora si que podemos realizar el análisis de componentes
principales. R nos ofrece dos métodos para llevar a cabo este
análisis: prcomp() y princomp(). Usaremos prcomp que da
resultados mas precisos. Ejemplo: acp = prcomp(datosEscalados),
y después ejecutamos el objeto pcaDatos para que nos muestre las
desviaciones estándar de cada un de los componentes y las

Página 3 de 45
Ignacio Puertas García-Figueras UC3M

variables rotadas en el plano. Con summary(acp) podemos ver que


porcentaje de la variabilidad total explica cada componente
principal o PC (principal component), que se ve en la fila
Proportion of Variance. Por ejemplo, se puede decir que el
componente principal 3 o PC3 explica un 12,65% de la
variabilidad no explicada por PC1 y PC2. Para decidir con
cuantos componentes nos vamos a quedar nos tenemos que basar en
algún criterio, en este caso nos basaremos en el criterio o
regla de kaiser que indicaría lo siguiente: "conservar solamente
aquellos factores cuyos valores propios (eigenvalues) son
mayores a la unidad", aunque el criterio más utilizado es el de
observar el porcentaje de varianza total explicada por cada
componente o factor, y cuando éste llega a un porcentaje
acumulado considerado alto, normalmente cerca del ochenta por
ciento, significa que el número de factores es suficiente.
Siguiendo con el criterio de Kaiser nos dice que la varianza de
cada una de las variables originales debe ser uno, por tanto la
varianza de los componentes principales no debe ser menor a uno,
sino no estarían explicando la suficiente variabilidad original.
Para ello: desv_estandar = acp[[1]] y ejecutamos el objeto
desv_estandar, estos datos son las raíces cuadradas de los
autovalores o varianzas. Pero lo que queremos es observar las
varianzas, para ello: varianzaDatos = desv_estandar^2 y
ejecutamos el objeto varianzaDatos. Escogeremos los PC cuya
varianza sea mayor que uno, y nos aseguramos de que vamos a
explicar la mayor variabilidad posible perdiéndose la menor
información. Ahora procedemos a guardar los PC cuya varianza > 1
en variables llamadas:
PC1 = acp[[2]][,1]
PC2 = acp[[2]][,2]
PC3 = acp[[2]][,3]
PCn = acp[[2]][,n]
Así, con tantas variables como PC Cabe destacar que prcomp,
con variabilidad mayor de uno nos almacenado en pcaDatos, devuelve
haya resultado. Ahora vamos a muchos conjuntos de datos, el
guardarlos en una variable llamada primero, que se obtiene con
Comp_prin y que nos los almacene pcaDatos[[1]], devuelve la sdev
mediante columnas: Comp_prin = o desviación estándar y el
cbind(PC1, PC2, PC3, PCn). segundo, que se obtiene con
Ejecutamos el objeto Comp_prin y se pcaDatos[[2]], devuelve la
puede sacar deducciones como: “El matriz rotada. También podemos
componente principal K explica gran acceder con el símbolo del
parte de … (que será uno de los dólar: pcaDatos$sdev o
nombres de las filas)”. Por ejemplo, pcaDatos$rotation. Para ver
en el caso de los productos, podemos puede devolver algo en
decir que CP3 o PC3 explica muy bien especifico podemos hacer: ?
la variable región, CP1 explica bien prcomp en el apartado de values.
el canal, leche, distintos alimentos
o productos de limpieza, CP2 explica

Página 4 de 45
Ignacio Puertas García-Figueras UC3M

bien los productos frescos, los productos congelados y la


charcutería. Aquí no se tiene en cuenta los signos, ya que
realizamos una transformación ortogonal a la matriz de
correlación, por lo que no tenemos en cuenta los datos como tal
sino la magnitud, que es el peso que le de cada componente a la
variable.

(Para estos pasos que vienen ya hemos descargado el paquete


ade4) Ahora vamos a generar el circulo de correlaciones, esto lo
hacemos a partir de la función s.corcircle() que nos permite
graficar la correlación entre los componentes principales y las
variables originales. Si queremos trabajar, siguiendo con el
ejemplo anterior, con los dos primeros componentes
s.corcircle(Com_prin[,-3], sub = “CP1 y CP2”, possub =
“topright”).
El componente principal 1 explica mucho
mejor las variables canal, productos de
limpieza, dist_Alim y leche. El
componente principal 2 explica mejor las
variables charcutería, productos frescos
y productos congelados.

Página 5 de 45
Ignacio Puertas García-Figueras UC3M

Ahora vamos a representar las coordenadas de los individuos en


el plano, que es el resultado de multiplicar la matriz principal
por los componentes principales. Para ello, primero guardamos en
un objeto los individuos: individuos = acp$x[,1:n] (Siendo la n
el número de componentes principales). Inicializamos el objeto
individuos.
Para representar los individuos en el plano:
s.label(individuos[,-3], label = row.names(nombreDatos), sub =
“Coordenadas de los individuos”, possub = “topright”)

De esta representación podemos deducir que los clientes que se


encuentran en el lado negativo del CP1 como el cliente número 87
o el 87 comprar atendiendo principalmente al canal, comprando
sobre todo productos de limpieza, distintos alimentos y leche.
Los que se encuentran en la zona negativa del CP2 compraran
sobre todo charcutería, productos frescos y productos
congelados, como es el 326 o 182. Los clientes situados en el
medio realizaran sus compras sobre todo basándose en la región.

Ahora haríamos lo mismo con el resto de combinaciones, por


ejemplo si tenemos tres componentes principales cuyas varianzas
están por encima de uno, haremos el s.corcircle() y s.label()
con las combinaciones de PC1 y PC2, PC1 y PC3 y por ultimo PC2 y
PC3.

Página 6 de 45
Ignacio Puertas García-Figueras UC3M

Cluster analysis
What is Cluster Analysis? Cluster analysis or clustering is the
task of grouping a set of objects in such a way that objects in
the same group are more similar to each other than to those in
other groups.

A good clustering method will produce high quality clusters with


high intra-class similarity and low inter-class similarity. The
quality of a clustering result depends on both the similarity
measure used by the method and its implementation. The quality
of a clustering method is also measured by its ability to
discover some or all of the hidden pattern. The distance measure
will determine the similarity between two elements, and it will
influence the shape of the clusters. Some common methods to
measure distance are Euclidean distance measure, Squared
Euclidean distance measure, Manhattan distance measure (city-
block) and Cosine distance measure.
The Euclidean distance measure is the ordinary straight line, is
the distance between tow points in Euclidean space.

Página 7 de 45
Ignacio Puertas García-Figueras UC3M

The Euclidean squared distance measure uses the same equation as


the Euclidean distance metric but does not take the square root.

The Manhattan distance measure is the simple sum of the


horizontal and vertical components or the distance between two
points measured along axes at right angles.

The Cosine distance measure similarity measures the angle


between the two vectors.

Página 8 de 45
Ignacio Puertas García-Figueras UC3M

The Minkowski distance measure is a metric in a normed vector


space which can be considered as a generalization of both the
Euclidean distance and the Manhattan distance.

Minkowski distance is typically used with p being 1 or 2, which


correspond to the Manhattan distance and the Euclidean distance,
respectively. In the limiting case of p reaching infinity, we
obtain the Chebyshev distance:

Similarly, for p reaching negative infinity, we have:

The Canberra distance is a numerical measure of the distance


between pairs of points in a vector space. The Canberra distance
d between vectors p and q in an n-dimensional real vector space
is given as follows: (where p and q are vectors).

Distancias para datos cuantitativos. Código en R


▪ Para la distancia Euclídea: dist(), metric=“euclidean”.
▪ Distancia City-Block o Manhattan: dist() , metric=“manhattan”.
▪ Distancia de Minkowski: dist(), metric=“minkowski”.
dist(x,method=“minkowski”,p=2)
▪ Distancia de Canberra: dist(), metric=“Canberra”.

Página 9 de 45
Ignacio Puertas García-Figueras UC3M

Dissimilarity/Similarity metric: Similarity is expressed in


terms of a distance function, which is typically metric: d(i,
j). There is a separate “quality” function that measures the
“goodness” of a cluster. The definitions of distance functions
are usually very different for interval-scaled, boolean,
categorical, and ordinal variables. Weights should be associated
with different variables based on applications and data
semantics. It is hard to define “similar enough” or “good
enough” – the answer is typically highly subjective.
Major Clustering Approaches
• Partitioning algorithms: Construct various partitions and then
evaluate them by some criterion
• Hierarchy algorithms: Create a hierarchical decomposition of
the set of data (or objects) using some criterion
• Density-based: based on connectivity and density functions
• Grid-based: based on a multiple-level granularity structure
• Model-based: A model is hypothesized for each of the clusters
and the idea is to find the best fit of that model to each other

Página 10 de 45
Ignacio Puertas García-Figueras UC3M

Partitioning Algorithms
Partitioning method: Construct a partition of a database D of n
objects into a set of k clusters. Given a k, find a partition of
k clusters that optimizes the chosen partitioning criterion
– Global optimal: exhaustively enumerate all partitions
– Heuristic methods: k-means and k-medoids algorithms
– k-means (MacQueenʼ67): Each cluster is represented by the
centre of the cluster
– k-medoids or PAM (Partition around medoids) (Kaufman &
Rousseeuwʼ87): Each cluster is represented by one of the
objects in the cluster

The K-Means Clustering Method

The K-Medoids Clustering Method or PAM (Partition around


medoids)
Find representative objects, called medoids, in clusters.
PAM (Partitioning Around Medoids, 1987)
– starts from an initial set of medoids and iteratively replaces
one of the medoids by one of the non-medoids if it improves the
total distance of the resulting clustering
– PAM works effectively for small data sets, but does not scale
well for large data sets.

Página 11 de 45
Ignacio Puertas García-Figueras UC3M

DATA: USArrests. This data set contains statistics on arrests


per 100,000 residents for assault, murder and rape in all 50 US
states in 1973. The percentage of the population in urban areas
is also provided (UrbanPop).
> data("USArrests")
To understand the distribution of the data:
> hist(USArrests$Murder) > hist(USArrests$Assault)

> hist(USArrests$UrbanPop) > hist(USArrests$Rape)

To visualize atypical data:


> boxplot(USArrests)

Página 12 de 45
Ignacio Puertas García-Figueras UC3M

The boxplot analysis in numbers:


> summary(USArrests)
Murder Assault UrbanPop Rape
Min. : 0.800 Min. : 45.0 Min. :32.00 Min. : 7.30
1st Qu.: 4.075 1st Qu.:109.0 1st Qu.:54.50 1st Qu.:15.07
Median : 7.250 Median :159.0 Median :66.00 Median :20.10
Mean : 7.788 Mean :170.8 Mean :65.54 Mean :21.23
3rd Qu.:11.250 3rd Qu.:249.0 3rd Qu.:77.75 3rd Qu.:26.18
Max. :17.400 Max. :337.0 Max. :91.00 Max. :46.00

To observe the existing relations among the variables:


> pairs(USArrests)

To obtain the correlation among the variables:


> cor(USArrests)
Murder Assault UrbanPop Rape
Murder 1.00000000 0.8018733 0.06957262 0.5635788
Assault 0.80187331 1.0000000 0.25887170 0.6652412
UrbanPop 0.06957262 0.2588717 1.00000000 0.4113412
Rape 0.56357883 0.6652412 0.41134124 1.0000000

Página 13 de 45
Ignacio Puertas García-Figueras UC3M

It is also recommended to use which(is.na()) to see the index of


the data in blanc.
> which(is.na(USArrests))
integer(0)

(1) To standardize the data:


> USArrests_standardize = scale(USArrests)

(2) To make the Principal component analysis:


> pca = prcomp(USArrests_standardize)

(3) We initialize the object pca:


> pca
Standard deviations (1, .., p=4):
[1] 1.5748783 0.9948694 0.5971291 0.4164494

Rotation (n x k) = (4 x 4):
PC1 PC2 PC3 PC4
Murder -0.5358995 0.4181809 -0.3412327 0.64922780
Assault -0.5831836 0.1879856 -0.2681484 -0.74340748
UrbanPop -0.2781909 -0.8728062 -0.3780158 0.13387773
Rape -0.5434321 -0.1673186 0.8177779 0.08902432

(4) With summary() we can observe the total percentage of the


variability explained by each principal component or PC. For
instance, PC1 explains a 62% of the total variability, PC2 a
24,74%, PC3 a 8,91% and PC4 a 4,34%.
> summary(pca)
Importance of components:
PC1 PC2 PC3 PC4
Standard deviation 1.5749 0.9949 0.59713 0.41645
Proportion of Variance 0.6201 0.2474 0.08914 0.04336
Cumulative Proportion 0.6201 0.8675 0.95664 1.00000

(5.1) By applying Kaiser rule, we will only take those pc´s


whose variability is larger than one.
> desv_estandar = pca[[1]]
> desv_estandar
[1] 1.5748783 0.9948694 0.5971291 0.4164494

Then we calculate the variance:


> varianza = desv_estandar^2
> varianza
[1] 2.4802416 0.9897652 0.3565632 0.1734301

Página 14 de 45
Ignacio Puertas García-Figueras UC3M

(5.2) Other rules to know which principal components are good


enough:
> library(NbClust)
> library(tidyverse) *No creo que se necesite*
> library(cluster)
> library(factoextra)
> df <- USArrests
> df <- scale(df)
#metodo del codo o rodilla (En este caso no queda muy claro si
nos sugiere 2, 3 o 4 clustes)
> fviz_nbclust(df, kmeans, method = "wss")

#metodo de la silueta (Claramente nos sugiere 2 clusters)


> fviz_nbclust(df, kmeans, method = "silhouette")

Página 15 de 45
Ignacio Puertas García-Figueras UC3M

#metodo de cambio de estadística (También nos sugiere dos


clusters)
> fviz_nbclust(df, kmeans, method = "gap_stat")
Clustering k = 1,2,..., K.max (= 10): .. done
Bootstrapping, b = 1,2,..., B (= 100) [one "." per sample]:
.................................................. 50
.................................................. 100

#Todos los métodos


Por último, R nos permite calcular el número óptimo de clusters
con todos sus métodos disponibles. Los métodos disponibles son:
"kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw",
"tracew", "friedman", "rubin", "cindex", "db", "silhouette",
"duda", "pseudot2", "beale", "ratkowsky", "ball", "ptbiserial",
"gap", "frey", "mcclain", "gamma", "gplus", "tau", "dunn",
"hubert", "sdindex", "dindex", "sdbw", "all" (all indices except
GAP, #Gamma, Gplus and Tau), "alllong" (all indices with Gap,
Gamma, Gplus and Tau included).
> resnumclust<-NbClust(df, distance = "euclidean", min.nc=2,
max.nc=10, method = "kmeans", index = "alllong")
****************************************************************
* Among all indices:
* 13 proposed 2 as the best number of clusters
* 2 proposed 3 as the best number of clusters
* 1 proposed 4 as the best number of clusters
* 1 proposed 5 as the best number of clusters
* 7 proposed 6 as the best number of clusters
* 1 proposed 9 as the best number of clusters
* 3 proposed 10 as the best number of clusters
***** Conclusion *****
* According to the majority rule, the best number of clusters is 2

Página 16 de 45
Ignacio Puertas García-Figueras UC3M

****************************************************************
> fviz_nbclust(resnumclust)
Among all indices:
===================
* 2 proposed 0 as the best number of clusters
* 13 proposed 2 as the best number of clusters
* 2 proposed 3 as the best number of clusters
* 1 proposed 4 as the best number of clusters
* 1 proposed 5 as the best number of clusters
* 7 proposed 6 as the best number of clusters
* 1 proposed 9 as the best number of clusters
* 3 proposed 10 as the best number of clusters

Conclusion
=========================
* According to the majority rule, the best number of clusters is 2 .

>> CONTINUAR CON EL ESTUDIO DE CLÚSTERS MAS ABAJO (PUNTO 9).

Página 17 de 45
Ignacio Puertas García-Figueras UC3M

(6) Now, we proceed to save those PC with variance > 1:


> PC1 = pca[[2]][,1]

> PC2 = pca[[2]][,2]

(7) We save PC1 and PC2 in comp_prin, organized by columns:


> Comp_prin = cbind(PC1, PC2)
> Comp_prin
PC1 PC2
Murder -0.5358995 0.4181809
Assault -0.5831836 0.1879856
UrbanPop -0.2781909 -0.8728062
Rape -0.5434321 -0.1673186

(8) Some graphs:


(8.1)
The first principal component explains better the variables
murder, assault and rape, and the second principal component
explains very well the variable UrbanPop.
> s.corcircle(Comp_prin[,1:2], sub = "CP1 y CP2", possub =
"topright")

Página 18 de 45
Ignacio Puertas García-Figueras UC3M

(8.2) Ahora representamos las coordenadas de los individuos en


el plano:
> individuos = pca$x[,1:2]
> individuos
PC1 PC2
Alabama -0.97566045 1.12200121
Alaska -1.93053788 1.06242692
Arizona -1.74544285 -0.73845954
Arkansas 0.13999894 1.10854226
California -2.49861285 -1.52742672
Colorado -1.49934074 -0.97762966
Connecticut 1.34499236 -1.07798362
Delaware -0.04722981 -0.32208890
Florida -2.98275967 0.03883425
Georgia -1.62280742 1.26608838
Hawaii 0.90348448 -1.55467609
Idaho 1.62331903 0.20885253
Illinois -1.36505197 -0.67498834
Indiana 0.50038122 -0.15003926
Iowa 2.23099579 -0.10300828
Kansas 0.78887206 -0.26744941
Kentucky 0.74331256 0.94880748
Louisiana -1.54909076 0.86230011
Maine 2.37274014 0.37260865
Maryland -1.74564663 0.42335704
Massachusetts 0.48128007 -1.45967706
Michigan -2.08725025 -0.15383500
Minnesota 1.67566951 -0.62590670
Mississippi -0.98647919 2.36973712
Missouri -0.68978426 -0.26070794
Montana 1.17353751 0.53147851
Nebraska 1.25291625 -0.19200440
Nevada -2.84550542 -0.76780502
New Hampshire 2.35995585 -0.01790055
New Jersey -0.17974128 -1.43493745
New Mexico -1.96012351 0.14141308
New York -1.66566662 -0.81491072
North Carolina -1.11208808 2.20561081
North Dakota 2.96215223 0.59309738
Ohio 0.22369436 -0.73477837
Oklahoma 0.30864928 -0.28496113
Oregon -0.05852787 -0.53596999
Pennsylvania 0.87948680 -0.56536050
Rhode Island 0.85509072 -1.47698328
South Carolina -1.30744986 1.91397297
South Dakota 1.96779669 0.81506822
Tennessee -0.98969377 0.85160534
Texas -1.34151838 -0.40833518
Utah 0.54503180 -1.45671524
Vermont 2.77325613 1.38819435
Virginia 0.09536670 0.19772785
Washington 0.21472339 -0.96037394
West Virginia 2.08739306 1.41052627
Wisconsin 2.05881199 -0.60512507
Wyoming 0.62310061 0.31778662

Página 19 de 45
Ignacio Puertas García-Figueras UC3M

Para hacer una representacion de los datos:


> s.label(individuos[,1:2], label = row.names((USArrests)))

Página 20 de 45
Ignacio Puertas García-Figueras UC3M

(9) Estudio de los clústeres.


Mediante los kmeans haremos el cluster análisis utilizando dos
centros que corresponden con el número de clusters recomendado
en el punto 5 y establecemos el nstart a 25 que son el número de
inicialización que hace el kmeas y en función de esto toma los
clusters.
Analizando la tabla de “cluster means” podemos observar que los
estados de USA del tipo 1 son más peligrosos que los del tipo 2,
ya que presentan valores mas altos en asesinatos, asaltos y
secuestros, también están más poblados.
> k2 <- kmeans(df, centers = 2, nstart = 25)
> k2
K-means clustering with 2 clusters of sizes 20, 30

Cluster means:
Murder Assault UrbanPop Rape
1 1.004934 1.0138274 0.1975853 0.8469650
2 -0.669956 -0.6758849 -0.1317235 -0.5646433

Clustering vector:
Alabama Alaska Arizona Arkansas California
1 1 1 2 1
Colorado Connecticut Delaware Florida Georgia
1 2 2 1 1
Hawaii Idaho Illinois Indiana Iowa
2 2 1 2 2
Kansas Kentucky Louisiana Maine Maryland
2 2 1 2 1
Massachusetts Michigan Minnesota Mississippi Missouri
2 1 2 1 1
Montana Nebraska Nevada New Hampshire New Jersey
2 2 1 2 2
New Mexico New York North Carolina North Dakota Ohio
1 1 1 2 2
Oklahoma Oregon Pennsylvania Rhode Island South Carolina
2 2 2 2 1
South Dakota Tennessee Texas Utah Vermont
2 1 1 2 2
Virginia Washington West Virginia Wisconsin Wyoming
2 2 2 2 2

Within cluster sum of squares by cluster:


[1] 46.74796 56.11445
(between_SS / total_SS = 47.5 %)

Available components:
[1] "cluster" "centers" "totss" "withinss" "tot.withinss"
[6] "betweenss" "size" "iter" "ifault"

Página 21 de 45
Ignacio Puertas García-Figueras UC3M

(10) Procedemos a graficar los clusters, para ello:


> fviz_cluster(k2, data=df)

> fviz_cluster(k2, data=df, ellipse.type = "euclid", repel =


TRUE, star.plot = TRUE)

Página 22 de 45
Ignacio Puertas García-Figueras UC3M

> fviz_cluster(k2, data=df, ellipse.type = "norm")

> fviz_cluster(k2, data = df, ellipse.type = "norm",palette =


"Set2", ggtheme = theme_minimal())

Página 23 de 45
Ignacio Puertas García-Figueras UC3M

(11) Ahora, saliéndonos del kmeans, se podría hacer un gráfico


típico de los clústeres jerárquicos.
> res2 <- hcut(df, k = 2, stand = TRUE)
> fviz_dend(res2, rect = TRUE, cex = 0.5,k_colors =
c("red","#2E9FDF"))

Si lo quisiéramos hacer con mas clústeres, por ejemplo con 4:


> res4 <- hcut(df, k = 4, stand = TRUE)
> fviz_dend(res4, rect = TRUE, cex = 0.5,k_colors =
c("red","#2E9FDF","green","black"))

Página 24 de 45
Ignacio Puertas García-Figueras UC3M

(13) Ahora lo que queremos es pasar los clusters a mi df inicial


para trabajar con ellos, es decir que se haga una columna
adicional en la que se indique a que cluster pertenece cada
estado y así poder trabajar más con esto.
Para ello: Le pedimos que meta el cluster del k2 como un factor
dentro del dataframe con el nomrbe “clus”.
> df <- USArrests
> df <- scale(df)
> df <- as.data.frame(df)
> df$clus<-as.factor(k2$cluster)
> head(df)
Murder Assault UrbanPop Rape clus
Alabama 1.24256408 0.7828393 -0.5209066 -0.003416473 1
Alaska 0.50786248 1.1068225 -1.2117642 2.484202941 1
Arizona 0.07163341 1.4788032 0.9989801 1.042878388 1
Arkansas 0.23234938 0.2308680 -1.0735927 -0.184916602 2
California 0.27826823 1.2628144 1.7589234 2.067820292 1
Colorado 0.02571456 0.3988593 0.8608085 1.864967207 1

(14) Ahora viene algo mas complejo, que es el uso de la función


gather, lo que haremos será matizar que la variable cluster de
mi df es un factor, es decir, que va a prohibir que esta
variable cambie. También vamos a cambiar el formato de la tabla,
como de los ancho a lo alto donde se incluirán categorías donde
se indica el nombre de la columna original y a su lado el valor,
esto nos permite ser muy flexible con las visualizaciones.
> df$clus<-factor(df$clus)
> data_long <- gather(df, caracteristica, valor, Murder:Rape,
factor_key=TRUE)
> data_long
clus caracteristica valor
1 1 Murder 1.24256408
2 1 Murder 0.50786248
3 1 Murder 0.07163341
4 2 Murder 0.23234938
5 1 Murder 0.27826823
6 1 Murder 0.02571456
… … … …
50 2 Murder -0.226839120
51 1 Assault 0.782839347
52 1 Assault 1.106822523
53 1 Assault 1.478803206
54 2 Assault 0.230868011
55 1 Assault 1.262814422
56 1 Assault 0.398859287
… … … …
100 2 Assault -0.117113918
101 1 UrbanPop -0.520906615
102 1 UrbanPop -1.211764194

Página 25 de 45
Ignacio Puertas García-Figueras UC3M

103 1 UrbanPop 0.998980059


104 2 UrbanPop -1.073592678
105 1 UrbanPop 1.758923396
… … … …
150 2 UrbanPop -0.382735099
151 1 Rape -0.003416473
152 1 Rape 2.484202941
153 1 Rape 1.042878388
154 2 Rape -0.184916602
155 1 Rape 2.067820292
156 1 Rape 1.864967207

> ggplot(data_long, aes(as.factor(x = caracteristica), y =


valor,group=clus, colour = clus)) + stat_summary(fun = mean,
geom="pointrange", size = 1)+ stat_summary(geom="line")

> ggplot(data_long, aes(as.factor(x = caracteristica), y =


valor,group=clus, colour = clus)) +
+ stat_summary(fun = mean, geom="pointrange", size = 1)+
+ stat_summary(geom="line")
+ geom_point(aes(shape=clus))

Página 26 de 45
Ignacio Puertas García-Figueras UC3M

A first case in PCA: USArrests data

> data("USArrests")
> prcomp(USArrests)
Standard deviations (1, .., p=4):
[1] 83.732400 14.212402 6.489426 2.482790

Rotation (n x k) = (4 x 4):
PC1 PC2 PC3 PC4
Murder 0.04170432 -0.04482166 0.07989066 -0.99492173
Assault 0.99522128 -0.05876003 -0.06756974 0.03893830
UrbanPop 0.04633575 0.97685748 -0.20054629 -0.05816914
Rape 0.07515550 0.20071807 0.97408059 0.07232502

The standard deviations are the eigenvalues of the correlation


matrix, and represent the variability along each component. The
higher the value, the more relevant the corresponding variable
is for visualization purposes. If we want to visualize the
relative importance of each component, we will do the following:
> x11()
> plot(prcomp(USArrests))

Numerically:
> summary(prcomp(USArrests))
Importance of components:
PC1 PC2 PC3 PC4
Standard deviation 83.7324 14.21240 6.4894 2.48279
Proportion of Variance 0.9655 0.02782 0.0058 0.00085
Cumulative Proportion 0.9655 0.99335 0.9991 1.00000

Página 27 de 45
Ignacio Puertas García-Figueras UC3M

As we can see, the variability of the data is mainly explained


by the first principal component PC1 which, as can be seen in
the Rotation matrix, gives a weight of 0.9952 to the Assault
variable, and weights close to zero to the rest. In the previous
table it can be seen that the proportion of variance explained
by the first component PC1 is 96.6%, that is, it is practically
the only relevant one. What is happening? If we look at the data
from USArrests, the magnitude of the assault values is much
greater than that of the other variables. For example, in the
case of Alabama, 236 versus 13.2 for Murder or 21.2 for Rape.
Then it is the variable that is going to have more influence on
the final result, as it is seen in the previous graph. The
second most influential component is PC2, which depends on
UrbanPop, the next variable in magnitude, and so on.
How can we solve this problem of a variable being more
influential simply because it has more range? The answer is
standardisation. Let's repeat the analysis, but standardize the
data:
> prcomp(USArrests, scale = T)
Standard deviations (1, .., p=4):
[1] 1.5748783 0.9948694 0.5971291 0.4164494

Rotation (n x k) = (4 x 4):
PC1 PC2 PC3 PC4
Murder -0.5358995 0.4181809 -0.3412327 0.64922780
Assault -0.5831836 0.1879856 -0.2681484 -0.74340748
UrbanPop -0.2781909 -0.8728062 -0.3780158 0.13387773
Rape -0.5434321 -0.1673186 0.8177779 0.08902432

> plot(prcomp(USArrests,scale=T))

Página 28 de 45
Ignacio Puertas García-Figueras UC3M

> summary(prcomp(USArrests,scale=T))
Importance of components:
PC1 PC2 PC3 PC4
Standard deviation 1.5749 0.9949 0.59713 0.41645
Proportion of Variance 0.6201 0.2474 0.08914 0.04336
Cumulative Proportion 0.6201 0.8675 0.95664 1.00000

For example, by concentrating on PC2, states would be ordered in


terms of their urban population in one direction, with the
number of murders weighted in the opposite direction. In PC3,
the order is mainly given by the number of rapes. We must bear
in mind, in any case, that there is no guarantee of
interpretability in a PCA analysis.

To make the graph of the two first principal components:

> biplot(prcomp(USArrests,scale=T))

We can use alternative libraries for better graphs:


> fviz_pca_ind(prcomp(usa.scaled), title = "PCA - datos
USArrests", ggtheme = theme_classic(), legend = "bottom")

Página 29 de 45
Ignacio Puertas García-Figueras UC3M

Página 30 de 45
Ignacio Puertas García-Figueras UC3M

Europe's economic data


> Europa = read.csv("http://www.instantr.com/wp-
content/uploads/2013/01/europe.csv", header=TRUE)
> Europa2 = Europa[,2:8]
> Europa2.escalado = scale(Europa2)
> pca.Europa2 = prcomp(Europa2.escalado)
> pca.Europa2
Standard deviations (1, .., p=7):
[1] 1.7964314 1.0895519 1.0311113 0.8776993 0.6766451 0.4106993
0.3544600
Rotation (n x k) = (7 x 7):
PC1 PC2 PC3 PC4 PC5 PC6 PC7
Area 0.1248739 0.17287220 -0.8982967395 0.04485040 -0.32401693 0.19011808 0.06664282
GDP -0.5005059 0.13013955 -0.0839557607 -0.08425547 0.39063244 0.63865707 -0.39740844
Inflation 0.4065182 0.36965724 -0.1981946748 0.16468565 0.68950054 -0.32386726 -0.22670030
Life.expect -0.4828733 -0.26524780 -0.2460824604 0.02677144 -0.10178656 -0.60643419 -0.50703130
Military 0.1881116 -0.65826689 -0.2436794326 -0.56237480 0.36814758 0.03559607 0.13730960
Pop.growth -0.4757036 -0.08262198 -0.1636972068 0.39246277 0.34786777 -0.12085562 0.67114668
Unemployment 0.2716558 -0.55320371 -0.0005001357 0.70196791 0.01015874 0.25970497 -0.24466243

> summary(pca.Europa2)
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7
Standard deviation 1.796 1.0896 1.0311 0.8777 0.67665 0.4107 0.35446
Proportion of Variance 0.461 0.1696 0.1519 0.1100 0.06541 0.0241 0.01795
Cumulative Proportion 0.461 0.6306 0.7825 0.8925 0.95795 0.9820 1.00000

> x11()
> plot(pca.Europa2)

> biplot(pca.Europa2)

Página 31 de 45
Ignacio Puertas García-Figueras UC3M

Heptathlon data analysis with FactoMineR


CASO DECAHTLON
> library(factoextra)
> library(FactoMineR)
> data("decathlon2")

The data correspond to athletes who compete in two sporting


events (Desctar and OlympicG). There are 27 athletes described
by 13 variables. We will use the first 23 data to perform PCA.
The data in rows 24 to 27 will be used for prediction.

We select the data (rows and columns/variables) we are going to


use:
> decathlon2.active = decathlon2[1:23,1:10]

We will perform the analysis using Factominer's PCA function,


which by default standardizes the data:
> res.pca = PCA(decathlon2.active,graph=F)
> print(res.pca)
**Results for the Principal Component Analysis (PCA)**
The analysis was performed on 23 individuals, described by 10
variables
*The results are available in the following objects:

name description
1 "$eig" "eigenvalues"
2 "$var" "results for the variables"
3 "$var$coord" "coord. for the variables"
4 "$var$cor" "correlations variables - dimensions"
5 "$var$cos2" "cos2 for the variables"
6 "$var$contrib" "contributions of the variables"
7 "$ind" "results for the individuals"

Página 32 de 45
Ignacio Puertas García-Figueras UC3M

8 "$ind$coord" "coord. for the individuals"


9 "$ind$cos2" "cos2 for the individuals"
10 "$ind$contrib" "contributions of the individuals"
11 "$call" "summary statistics"
12 "$call$centre" "mean of the variables"
13 "$call$ecart.type" "standard error of the variables"
14 "$call$row.w" "weights for the individuals"
15 "$call$col.w" "weights for the variables"

To visualize the eigenvectors and their variances:


> res.pca = PCA(decathlon3.scale,graph=F)
> eig.val
eigenvalue variance.percent cumulative.variance.percent
Dim.1 4.1242133 41.242133 41.24213
Dim.2 1.8385309 18.385309 59.62744
Dim.3 1.2391403 12.391403 72.01885
Dim.4 0.8194402 8.194402 80.21325
Dim.5 0.7015528 7.015528 87.22878
Dim.6 0.4228828 4.228828 91.45760
Dim.7 0.3025817 3.025817 94.48342
Dim.8 0.2744700 2.744700 97.22812
Dim.9 0.1552169 1.552169 98.78029
Dim.10 0.1219710 1.219710 100.00000

> fviz_eig(res.pca,addlabels = T,ylim=c(0,50))

To display the variables, the function get_var_pca() gives the


results for the variables used, which are the coordinates,
correlations and contributions .
> var = get_pca_var(res.pca)
> var
Principal Component Analysis Results for variables
===================================================

Página 33 de 45
Ignacio Puertas García-Figueras UC3M

Name Description
1 "$coord" "Coordinates for the variables"
2 "$cor" "Correlations between variables and dimensions"
3 "$cos2" "Cos2 for the variables"
4 "$contrib" "contributions of the variables"

> fviz_pca_var(res.pca , col.var = "black")

> library(corrplot)
corrplot 0.91 loaded
> corrplot(var$cos2,is.corr=F)

Página 34 de 45
Ignacio Puertas García-Figueras UC3M

> fviz_cos2(res.pca,choice = "var",axes=1:2)

High values indicate a good representation of the variable in


the corresponding principal component.

> fviz_pca_var(res.pca,col.var="cos2",repel=T)

Página 35 de 45
Ignacio Puertas García-Figueras UC3M

Contribution of variables to the principal components. The


variables most correlated with PC1 and PC2 are the most
important in explaining the variability in the data set.
> corrplot(var$contrib,is.corr=F)

We can visualize the contributions of the variables to each


component in the following way:
> fviz_contrib(res.pca,choice="var",axes=1,top=10)

Página 36 de 45
Ignacio Puertas García-Figueras UC3M

> fviz_contrib(res.pca,choice="var",axes=2,top=10)

Total contribution to PC1 and PC2


> fviz_contrib(res.pca,choice="var",axes=1:2,top=10)

Página 37 de 45
Ignacio Puertas García-Figueras UC3M

We can make groups of the variables and visualize them:


> res.km = kmeans(var$coord,centers = 3, nstart = 25)
> grp = as.factor(res.km$cluster)
> fviz_pca_var(res.pca,col.var=grp,legend.title="cluster")

Charts for individuals:


> ind = get_pca_ind(res.pca)
> ind
Principal Component Analysis Results for individuals
===================================================
Name Description
1 "$coord" "Coordinates for the individuals"
2 "$cos2" "Cos2 for the individuals"
3 "$contrib" "contributions of the individuals"

Página 38 de 45
Ignacio Puertas García-Figueras UC3M

> fviz_pca_ind(res.pca)

Biplot: individuals and variables in the same graph:


> fviz_pca_biplot(res.pca,repel=T)

Buen ejemplo:
https://aulaglobal.uc3m.es/pluginfile.php/4792883/mod_resource/c
ontent/2/heptathlon-pca-ade_engl.pdf

Página 39 de 45
Ignacio Puertas García-Figueras UC3M

CLÚSTER ANALYSIS - K-MEDOIDS OR PAM


El análisis PAM o k medoids es como el kmean pero más robusto,
ya que el kmean se muy dependiente de valores atípicos o de como
inician las iteraciones.
> library(fpc)
> library(NbClust)
> library(cluster)
> library(factoextra)
> library(tidyr)
> data("USArrests")
> df <- scale(USArrests)
Para ver más o menos si nuestro data frame (df) es
claustelizable, para ello haremos una representación de la
distancia, que nos dará una visión aproximada de los clusters
que podría llegar a contener.
> x11()
> m.distancia <- get_dist(df, method = "kendall")
> fviz_dist(m.distancia, gradient = list(low = "blue", mid =
"white", high = "red"))

Página 40 de 45
Ignacio Puertas García-Figueras UC3M

Para estimar el número de clústeres:


> fviz_nbclust(df, pam, method = "wss")

> fviz_nbclust(df, pam, method = "silhouette")

> fviz_nbclust(df, pam, method = "gap_stat")

Página 41 de 45
Ignacio Puertas García-Figueras UC3M

> resnumclust <- NbClust(df, distance = "euclidean", min.nc=2,


max.nc=10, method = "median", index = "alllong")
> fviz_nbclust(resnumclust)
Among all indices:
===================
* 2 proposed 0 as the best number of clusters
* 1 proposed 1 as the best number of clusters
* 9 proposed 2 as the best number of clusters
* 1 proposed 3 as the best number of clusters
* 1 proposed 5 as the best number of clusters
* 1 proposed 7 as the best number of clusters
* 1 proposed 8 as the best number of clusters
* 13 proposed 9 as the best number of clusters
* 1 proposed 10 as the best number of clusters

Conclusion
=========================
* According to the majority rule, the best number of clusters is 9.

(resnumclust me dará toda la información desglosada, es decir,


me dirá cuántos clústeres sugiere cada método).

Creamos los 9 clústeres.

> pam9 <- pam(df, 9)


> print(pam9)
> print(pam9)

Medoids:
ID Murder Assault UrbanPop Rape
Alabama 1 1.2425641 0.7828393 -0.5209066 -0.003416473
Alaska 2 0.5078625 1.1068225 -1.2117642 2.484202941
New Mexico 31 0.8292944 1.3708088 0.3081225 1.160319648
California 5 0.2782682 1.2628144 1.7589234 2.067820292
Massachusetts 21 -0.7778653 -0.2611064 1.3444088 -0.526563903
Oklahoma 36 -0.2727580 -0.2371077 0.1699510 -0.131534211
South Dakota 41 -0.9156219 -1.0170672 -1.4190215 -0.900240639
Illinois 13 0.5997002 0.9388312 1.2062373 0.295524916
New Hampshire 29 -1.3059321 -1.3650491 -0.6590781 -1.252564419

Página 42 de 45
Ignacio Puertas García-Figueras UC3M

Clustering vector:
Alabama Alaska Arizona Arkansas California Colorado
1 2 3 1 4 4
Connecticut Delaware Florida Georgia Hawaii Idaho
5 6 3 1 5 7
Illinois Indiana Iowa Kansas Kentucky Louisiana
8 6 9 6 6 1
Maine Maryland Massachusetts Michigan Minnesota Mississippi
9 3 5 3 9 1
Missouri Montana Nebraska Nevada New Hampshire New Jersey
6 7 6 4 9 5
New Mexico New York North Carolina North Dakota Ohio Oklahoma
3 8 1 9 6 6
Oregon Pennsylvania Rhode Island South Carolina South Dakota Tennessee
6 6 5 1 7 1
Texas Utah Vermont Virginia Washington West Virginia
8 5 7 6 6 7
Wisconsin Wyoming
9 6

Objective function:
build swap
0.7439615 0.7435288

Available components:
[1] "medoids" "id.med" "clustering" "objective" "isolation" "clusinfo" "silinfo"
[8] "diss" "call" "data"

Como la opción de utilizar dos clústers también estaba muy


sugerida por los distintos métodos:

> pam2 <- pam(df, 2)


> print(pam2)
Medoids:
ID Murder Assault UrbanPop Rape
New Mexico 31 0.8292944 1.3708088 0.3081225 1.1603196
Nebraska 27 -0.8008247 -0.8250772 -0.2445636 -0.5052109
Clustering vector:
Alabama Alaska Arizona Arkansas California Colorado
1 1 1 2 1 1
Connecticut Delaware Florida Georgia Hawaii Idaho
2 2 1 1 2 2
Illinois Indiana Iowa Kansas Kentucky Louisiana
1 2 2 2 2 1
Maine Maryland Massachusetts Michigan Minnesota Mississippi
2 1 2 1 2 1
Missouri Montana Nebraska Nevada New Hampshire New Jersey
1 2 2 1 2 2
New Mexico New York North Carolina North Dakota Ohio Oklahoma
1 1 1 2 2 2
Oregon Pennsylvania Rhode Island South Carolina South Dakota Tennessee
2 2 2 1 2 1
Texas Utah Vermont Virginia Washington West Virginia
1 2 2 2 2 2
Wisconsin Wyoming
2 2
Objective function:
build swap
1.441358 1.368969

Available components:
[1] "medoids" "id.med" "clustering" "objective" "isolation" "clusinfo" "silinfo"
[8] "diss" "call" "data"

Página 43 de 45
Ignacio Puertas García-Figueras UC3M

> fviz_cluster(pam9, data = df)

> fviz_cluster(pam2, data = df, ellipse.type = "norm")

Ahora incorporamos los datos del clúster al data frame:


> df <- USArrests
> df <- scale(USArrests)
> df<- as.data.frame(df)
> df$clus<-as.factor(pam9$clustering)

Le damos la vuelta al data frame:


> df$clus<-factor(df$clus)
> data_long <- gather(df, caracteristica, valor, Murder:Rape,
factor_key=TRUE)

Página 44 de 45
Ignacio Puertas García-Figueras UC3M

> ggplot(data_long, aes(as.factor(x = caracteristica), y =


valor,group=clus, colour = clus)) +
+ stat_summary(fun = mean, geom="pointrange", size = 1,
aes(shape = clus))+
+ stat_summary(geom="line")

Página 45 de 45

También podría gustarte