Hay problemas que no pueden ser atajados directamente con las técnicas de reducción de variables clásicas como son los componentes principales y el análisis factorial. Precisan un determinado tipo de transformaciones para poder hacerlo.
La idea es simple, pero puede confundir en algunos casos: Se trata de transformar los datos que tenemos a un espacio de mayores dimensiones pero en donde las técnicas de reducción de variables puedan atajar mejor el problema, es decir, realizar una “conversión” que permita entender mejor los datos para poder trabajar mejor con ellos.
Figura 1: Ejemplo de cómo se pueden transformar los datos para poder mejorar las técnicas de reducción de variables.
En la figura 1 puede entenderse mejor la idea que perseguimos y que es ver los datos desde otra manera distinta, más lineal si puede ser, para poder aplicar ahí las técnicas normales de componentes principales.
En nuestro caso, esa función de transformación se llama kernel y como viene siendo habitual nuestro amigo R, está aquí para echarnos una mano con ayuda de la librería kpca, en donde se mezclan estas funciones kernel con la técnica de los componentes principales que todos conocemos. Eso sí, trabajando exclusivamente con variables numéricas.
Veamos un ejemplo con la famosa base de datos “mtcars” que tiene R.
data(mtcars) # traemos el fichero a la memoria aux <- mtcars[,c(3:8)] # seleccionamos una serie de variables numéricas test <- sample(1:32,10) # vamos a trabajar con 10 registros elegidos al azar
library(kernlab) # cargamos la librería que vamos a usar
# ejecutamos el algoritmo y lo guardamos en un objeto que se llama kpc # en este caso usamos como kernel una función laplaciana con un parámetro sigma = 0.2 # y extraemos sólo 2 componente principales
kpc <- kpca(~.,data=aux[test,],kernel=»laplacedot», + kpar=list(sigma=0.2),features=2)
#escribimos las coordenadas de los 10 registros los dos componentes principales > round(pcv(kpc),2) [,1] [,2] [1,] 0.47 -0.18 [2,] 0.47 -0.27 [3,] -1.90 0.00 [4,] 0.48 -1.28 [5,] -1.90 0.00 [6,] 0.47 -0.27 [7,] 0.47 -0.31 [8,] 0.48 1.79 [9,] 0.48 -1.28 [10,] 0.48 1.80
# vemos los datos originales > aux[test,] disp hp drat wt qsec vs Mazda RX4 160.0 110 3.90 2.620 16.46 0 Cadillac Fleetwood 472.0 205 2.93 5.250 17.98 0 Camaro Z28 350.0 245 3.73 3.840 15.41 0 Merc 450SLC 275.8 180 3.07 3.780 18.00 0 Duster 360 360.0 245 3.21 3.570 15.84 0 Ferrari Dino 145.0 175 3.62 2.770 15.50 0 Hornet 4 Drive 258.0 110 3.08 3.215 19.44 1 Lotus Europa 95.1 113 3.77 1.513 16.90 1 Dodge Challenger 318.0 150 2.76 3.520 16.87 0 Fiat 128 78.7 66 4.08 2.200 19.47 1
# realizamos un dibujo para entender cómo se representan estos datos # obteniendo una simlitud de los modelos como puede verse al superponerse los nombres |
plot(rotated(kpc),col=as.factor(substr(rownames(aux[test,]),1,5)), fg=1, xlab=»1st Principal Component»,ylab=»2nd Principal Component») text(rotated(kpc),substr(rownames(aux[test,]),1,4)) |
Figura 2: resultado del algoritmo de kpca sobre los 10 registros seleccionados.
Esto mismo lo podemos realizar con la librería de gráficos ggplot2 y ver cómo se pueden interpretar el resultado de todo el trabajo.
# extraemos la marca de los coches para entender major los gráficos
library(stringi)
pos <- stri_locate_all(pattern = ‘ ‘, rownames(rot), fixed = TRUE)
elem<-(pos)
lp<-length(pos)
for (i in 1:lp)
{
newlist[i]<-c(pos[[i]][1])
if (is.na(newlist[i]))
{newlist[i]=nchar(rownames(rot)[i])}
else
{newlist[i]=newlist[i]-1}
}
#guardamos la marca en un objeto que se llama “names_car”
names_car <- substr(rownames(rot),1, newlist)
# cargamos la librería
library(ggplot2)
#ejecutamos el algortimos en las mismas condiciones que antes
kpc <- kpca(~.,data=aux[test,],kernel=»laplacedot»,
kpar=list(sigma=0.2),features=2)
#guardamos el resultado en un data frame
rot <- as.data.frame(rotated(kpc))
#dibujamos el gráfico con las marcas
ggplot(rot,aes(rot[,1],rot[,2])) +
geom_point(aes(colour = factor(names_car)),size=6) +
ggtitle(«Laplacian con sigma = 0.2»)
Figura 3: Mismo resultado que la figura 2 pero con la librería ggplo2 y el sigma = 0.2
Ejecutando el mismo proceso pero con distintos parámetros sigma obtenemos lo siguiente.
Figura 4: Distintas ejecuciones del algoritmo kpca
Lo que nos sirve para interpretar que el primer componente principal se puede corresponder con la variable “hp”, mientras que el segundo componente principal sería con la variable “qsec”.
Información que nos resume mucho mejor tanto los datos originales como si aplicáramos una técnica clásica de componentes principales sin kernel.
ggplot(aux[test,],aes(hp,qsec)) +
geom_point(aes(colour = factor(names_car)),size=6) +
ggtitle(«Datos originales»)
Figura 5: Datos originales de las variables interpretadas
pr <- prcomp(aux[test,], scale = TRUE)
pr1 <- pr$x[,1]
pr2 <- pr$x[,2]
pr0 <- as.data.frame(cbind(pr1,pr2))
ggplot(pr0,aes(pr1,pr2)) +
geom_point(aes(colour = factor(rownames(pr0))),size=6) +
ggtitle(«Algoritmo prcomp»)
Figura 6: Resultados de un análisis de componentes principales sin kernel
Por lo que, como podemos ver en el gráfico 4, la lucha competitiva se establece en los modelos de los coches basándose en potencia (variable”hp”) y velocidad (variable “qsec”), mostrando esos dos gráficos ese hecho más claramente que los demás, aunque dichas componentes principales no son de todo puros, como lo demuestra la matriz de correlaciones.
round(cor(aux[test,]),2)
disp hp drat wt qsec vs
disp 1.00 0.76 -0.73 0.94 -0.14 -0.58
hp 0.76 1.00 -0.39 0.68 -0.63 -0.72
drat -0.73 -0.39 1.00 -0.69 -0.13 0.34
wt 0.94 0.68 -0.69 1.00 -0.02 -0.62
qsec -0.14 -0.63 -0.13 -0.02 1.00 0.65
vs -0.58 -0.72 0.34 -0.62 0.65 1.00
De ese modo podríamos agrupar el primer componte principal con todas las variables correladas positivamente con “hp”, y la segunda con todas las variables correladas positivamente con “qsec”.
Autor: Pedro José Jiménez López, profesor del Máster en Big Data y Business Intelligence