¿PCA con ordinales y nominales? Tercera entrega. ¡ Que vienen los holandeses !

ciencia de datos
estadística
2020
Author

José Luis Cañadas Reche

Published

June 11, 2020

Hoy vamos a darle una (pequeña) vuelta de tuerca al tema de la reducción de dimensiones ( y por ende la codificación ) con variables categóricas y ordinales.

Aunque puede que muchos no lo sepan, existen dos escuelas derivadas de lo que Tukey llamaba el análisis exploratorio de datos, a saber, la francesa y la holandesa.

La francesa con exponentes como Jean-Paul Benzécri, Saporta o Lebart, resuelven el problema de proyectar las relaciones entre variables categóricas en un hiperplano de menor dimensión de forma analítica.

Por otro lado tenemos la escuela holandesa, que se diferencia de la escuela francesa en la forma de solucionar el problema, ya que la escuela holandesa llega a la solución mediante métodos de optimización numérica. Representantes de esta escuela son Jan de Leeuw o Patrick Mair, que entre otros forman parte del grupo de teoría de datos más conocidos por su pseudónimo “Albert Gifi” en honor al criado de Galton.

En el estupendo artículo de Francois Husson sobre la influencia de Jan de Leeuw en la escuela francesa de análisis de datos, cuenta la relación entre el análisis de correspondencias múltiple (MCA) desarrollado por la escuela francesa y el análisis de homogeneidad por als (homals), de la escuela holandesa.

Para el que quiera profundizar más, recomiendo el libro de Patrick Mair, Modern Psycometrics with R, dónde viene de todo, desde teoría clásica del test, análisis factorial exploratorio y confirmatorio, modelos de ecuaciones estructurales, modelos de preferencia, independent component analysis, mca, homals, multidimensional scaling , análisis de datos funcionales, en fin, de todo.

En el capítulo 8 del libro de Mair se describe muy bien como es su aproximación al problema que consiste básicamente en encontrar una cuantificación de las filas y en una cuantificación de las categorías de las variables (optimal scaling).

Bien, los métodos Gifi, se basan en minimizar una expresión similar a esta

\[ \sigma(X, Y_1, \ldots, Y_m) = \sum_{j=1}^{m}\text{tr}(\boldsymbol{X} - \boldsymbol{G_j\,Y_j} )^\mathsf{T}(\boldsymbol{X} - \boldsymbol{G_j\,Y_j} ) \] dónde \(G_j\) es la matriz indicadora para cada variable \(j\), de dimensión \(n\times k_j\) , dónde \(n\) es el número de observaciones y \(k_j\) el número de categorías de la variable categórica j-ésima. Cada variables categórica \(j\) está asociada con una matriz \(Y_j\) de dimensión \(k_j\times p\) que representa la cuantificación de cada categoría en las p dimensiones que se quieren obtener. Y por último la matriz \(X\) de dimensión \(n\times p\) representa los object scores que no es más que las puntuaciones en la estructura factorial de dimensión \(p\) de las \(n\) filas del conjunto de datos.

Como vemos es un problema de optimización, se quiere minimizar el lado derecho de la ecuación, que básicamente es una suma de cuadrados, es una doble optimización porque por un lado se quiere encontrar la representación de las filas en el espacio p (asimilable a un PCA) y por otro encontrar la mejor cuantificación de las variables categóricas. Esa última parte es a la que los integrantes del grupo Gifi llaman optimal scaling. Para minimizar la expresión anterior, utilizan ALS (alternative least squares).

Veamos ahora la aplicación de esta técnica al mismo conjunto de datos que venimos utilizando

Mostrar / ocultar código
library(Gifi)

datos <- readRDS(here::here("data/science.rds"))
Mostrar / ocultar código
non_linear_pca <-  princals(datos, ndim = 3, ordinal = TRUE) # principal components analisys, with als
Mostrar / ocultar código
summary(non_linear_pca)
#> 
#> Loadings (cutoff = 0.1):
#>             Comp1  Comp2  Comp3 
#> Environment  0.654  0.426       
#> Technology   0.663  0.449 -0.101
#> Industry     0.697  0.352       
#> Future       0.490 -0.555  0.388
#> Benefit      0.284 -0.620 -0.486
#> Comfort      0.429 -0.504 -0.522
#> Work         0.275 -0.485  0.677
#> 
#> Importance (Variance Accounted For):
#>                 Comp1   Comp2   Comp3
#> Eigenvalues     1.935  1.6857  1.1343
#> VAF            27.643 24.0820 16.2041
#> Cumulative VAF 27.640 51.7200 67.9300

En el objeto tenemos diferentes resultados. Por un lado tenemos los transform que se corresponden con el optimal scaling es decir, la forma en que ha codificado cada categoría de cada variable

Mostrar / ocultar código
head(non_linear_pca$transform)
#>       Comfort Environment         Work      Future  Technology    Industry
#> 1 0.036104177  0.07230258  0.101348321 -0.00902167  0.07175901 -0.04238874
#> 2 0.002981012  0.07230258  0.006511849 -0.00902167 -0.02329347 -0.04238874
#> 3 0.002981012 -0.04050230 -0.040242898 -0.05043371  0.07175901  0.06018155
#> 4 0.002981012 -0.03058590 -0.040242898 -0.05043371  0.07175901  0.06018155
#> 5 0.002981012 -0.04050230  0.101348321  0.07654584 -0.04939964 -0.04238874
#> 6 0.036104177 -0.03058590  0.101348321 -0.00902167 -0.02329347  0.06018155
#>        Benefit
#> 1 -0.002042307
#> 2  0.010544848
#> 3  0.010544848
#> 4  0.010544848
#> 5 -0.206714329
#> 6  0.010544848

Y vemos que la categoría agree en la variable Comfort la ha codificado con el valor 0.0029, y la strongly agree con el valor 0.0036

Mostrar / ocultar código
head(datos)
#>          Comfort       Environment           Work         Future     Technology
#> 1 strongly agree    strongly agree strongly agree          agree strongly agree
#> 2          agree    strongly agree          agree          agree          agree
#> 3          agree          disagree       disagree       disagree strongly agree
#> 4          agree             agree       disagree       disagree strongly agree
#> 5          agree strongly disagree strongly agree strongly agree       disagree
#> 6 strongly agree             agree strongly agree          agree          agree
#>         Industry           Benefit
#> 1          agree          disagree
#> 2          agree             agree
#> 3 strongly agree             agree
#> 4 strongly agree             agree
#> 5          agree strongly disagree
#> 6 strongly agree             agree

También tenemos la matriz de correlación inducida

Mostrar / ocultar código
non_linear_pca$rhat
#>                Comfort  Environment         Work     Future   Technology
#> Comfort     1.00000000  0.069270005  0.056874364 0.24201116  0.062523930
#> Environment 0.06927000  1.000000000 -0.007276641 0.06889585  0.446700717
#> Work        0.05687436 -0.007276641  1.000000000 0.41223332 -0.039689240
#> Future      0.24201116  0.068895851  0.412233321 1.00000000  0.025151297
#> Technology  0.06252393  0.446700717 -0.039689240 0.02515130  1.000000000
#> Industry    0.07013247  0.400502817  0.033318166 0.14474834  0.445641042
#> Benefit     0.41522232 -0.058626547  0.095970160 0.22558436 -0.006077812
#>                Industry      Benefit
#> Comfort      0.07013247  0.415222316
#> Environment  0.40050282 -0.058626547
#> Work         0.03331817  0.095970160
#> Future       0.14474834  0.225584363
#> Technology   0.44564104 -0.006077812
#> Industry     1.00000000 -0.032718148
#> Benefit     -0.03271815  1.000000000

Con esta matriz podríamos usarla de input para un pca o un fa estándar, si lo hacemos vemos que es bastante parecido al que salía utilizando las correlaciones policóricas

Mostrar / ocultar código
library(psych)

diagram(fa(non_linear_pca$rhat, nfactors = 3))

Por otra parte tenemos los autovalores

Mostrar / ocultar código
non_linear_pca$evals
#> [1] 1.9350104 1.6857383 1.1342880 0.6047875 0.6015630 0.5345555 0.5040572

Tenemos también las puntuaciones de las filas en la estructura factorial.

Mostrar / ocultar código
head(non_linear_pca$objectscores)
#>            D1           D2         D3
#> 1  1.06418739 -0.167312221  0.6374230
#> 2  0.04046306 -0.009657124 -0.1201745
#> 3  0.31255235  0.884278134 -0.9765450
#> 4  0.37834578  0.932832098 -0.9770415
#> 5 -0.82825240 -0.218690372  3.4749807
#> 6  0.50669540 -0.843197774  0.8433055

Las cuantificaciones de cada categoría en cada dimensión, que es diferente de la transformación de la categoría, esto es la proyección de esas transformaciones en la estructura factorial

Mostrar / ocultar código
non_linear_pca$quantifications
#> $Comfort
#>                             D1           D2           D3
#> strongly disagree -0.165992056  0.194719299  0.201545046
#> disagree          -0.027817443  0.032631640  0.033775519
#> agree              0.001279933 -0.001501443 -0.001554075
#> strongly agree     0.015501757 -0.018184552 -0.018821998
#> 
#> $Environment
#>                            D1          D2            D3
#> strongly disagree -0.02648430 -0.01723503  9.813747e-05
#> disagree          -0.02648430 -0.01723503  9.813747e-05
#> agree             -0.02000000 -0.01301528  7.410994e-05
#> strongly agree     0.04727838  0.03076707 -1.751899e-04
#> 
#> $Work
#>                             D1          D2           D3
#> strongly disagree -0.024770164  0.04369744 -0.060974004
#> disagree          -0.011069125  0.01952722 -0.027247654
#> agree              0.001791135 -0.00315977  0.004409042
#> strongly agree     0.027876650 -0.04917764  0.068620902
#> 
#> $Future
#>                             D1           D2           D3
#> strongly disagree -0.063733186  0.072322188 -0.050523360
#> disagree          -0.024689820  0.028017143 -0.019572419
#> agree             -0.004416558  0.005011755 -0.003501148
#> strongly agree     0.037473008 -0.042523057  0.029706067
#> 
#> $Technology
#>                            D1          D2           D3
#> strongly disagree -0.03275405 -0.02218532  0.004987033
#> disagree          -0.03275405 -0.02218532  0.004987033
#> agree             -0.01544455 -0.01046107  0.002351542
#> strongly agree     0.04757926  0.03222689 -0.007244275
#> 
#> $Industry
#>                            D1          D2           D3
#> strongly disagree -0.02953195 -0.01492016 -0.003358596
#> disagree          -0.02953195 -0.01492016 -0.003358596
#> agree             -0.02953195 -0.01492016 -0.003358596
#> strongly agree     0.04192808  0.02118295  0.004768377
#> 
#> $Benefit
#>                              D1           D2            D3
#> strongly disagree -0.0588285659  0.128096682  0.1004370346
#> disagree          -0.0005812176  0.001265576  0.0009923031
#> agree              0.0030009449 -0.006534429 -0.0051234634
#> strongly agree     0.0091581959 -0.019941579 -0.0156356359

Y entre otras cosas también tenemos los loadings que sería la contribución de cada variable a cada dimensión

Mostrar / ocultar código
non_linear_pca$loadings
#>                    D1         D2           D3
#> Comfort     0.4290025 -0.5035739 -0.521715665
#> Environment 0.6538954  0.4255331 -0.002426704
#> Work        0.2750993 -0.4851472  0.677125400
#> Future      0.4895604 -0.5554953  0.388110179
#> Technology  0.6630399  0.4490954 -0.100984178
#> Industry    0.6966932  0.3519841  0.079233197
#> Benefit     0.2841658 -0.6195394 -0.486304172

Así, por ejemplo vemos que las variables Environment, Technology e Industry son los que tienen una mayor puntuación (en valor absoluto) a la primera dimensión. y vemos que la categoría 4 de Industria (“strongly agree”) tiene un valor positvo en esa dimensión así como Technology y Environment. Básicamente, los individuos que están muy de acuerdo con las afirmaciones siguientes, tendrán una puntuación muy alta en la primera dimensión.

Afirmaciones

Lo interesante de esta técnica es que por un lado nos devuelve una codificación de las variables categóricas (ordinales en este caso) en dimensión 1 y por otro hace la reducción de dimensiones. Nosotros podríamos utilizar la codificación por “optimal scaling” como nuestra “codificación de categóricas” o usar las dimensiones obtenidas, en este caso 3.

La libreria Gifi tiene también para sacar algunos gráficos interesantes

Mostrar / ocultar código
plot(non_linear_pca)

Mostrar / ocultar código
plot(non_linear_pca, plot.type = "transplot")

Dejo para el lector (si hay alguno) la utilización de la función homals del mismo paquete, que es una función más general y permite hacer análisis de correspondencias múltiples utilizando este marco de análisis.

Nota: En este marco “Gifi Methods” entrarían como casos particulares el PCA, MCA, Conjoint Analysis, análisis de correlaciones canónicas, análisis discriminante o la regresión múltiple.