Bibliotecas a usar

library(FactoMineR)
library(factoextra)
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(gplots)
## 
## Attaching package: 'gplots'
## The following object is masked from 'package:stats':
## 
##     lowess
library(corrplot)
## corrplot 0.92 loaded
library(ggpubr)
library(ade4)
## 
## Attaching package: 'ade4'
## The following object is masked from 'package:FactoMineR':
## 
##     reconst
library(ca)
library(MASS)
library(ExPosition)
## Loading required package: prettyGraphs

Capitulo 4

Correspondence Analysis

Introduction

El Correspondence analysis (CA) es una extencion de lo visto en el capitulo 3, creado para explorar relaciones entre variables cualitativas. De la misma forma que el analisis de componentes, el CA provee una solucion para visualizar y cuantificar bases de datos en graficos de dos dimensiones. En este capitulo solo se usará el simple correspondence analysis el cual se usa para analizar frecuencias formados por dos datos categoricos y una tabla de datos conocida como contygency table. Dicha tabla proporciona datos tanto para las filas y las columnas las cuales se usan para hacer las graficas y visualizar dicha tabla. El CA es principalmente usado para ver geometricamente similitudes entre las filas y las columnas y poder interpretar de forma correcta y apropiada los datos. Para hacer el CA, en este capitulo se mostrara como generar el CA con codigos de R usando dos paquetes principales:

  • FactoMineR
  • factoextra

Ademas de esto, se verá como aplicar CA usando filas y columnas suplemntarias que son utiles al momento de hacer predicciones y por ultimmo,, se explicara como filtrar los resultados de la CA para guardar solo las variables que mas contribuyan y como se pueden lidiar con datos anomalos.

R packages

existen muchas funciones de diferentes paquetes que nos ayudan a crear el CA, entre ellas estan:

  1. CA del paquete FactoMineR
  2. ca del paquete ca
  3. dudi.coa del paquete ade4
  4. corresp del paquete MASS
  5. epCA del paquete ExPosition

Sin importar cuales funciones se decidan usar, se puede facilmente graficar usando las bibliotecas factoextra y FactoMineR, en este caso se usara la segunda biblioteca.

Data format

Los datos deben ser una tabla de contingencia. Para demostrar como funciona se usaran los datos contenidos en housetasks que provienen del paquete factoextra

data("housetasks")

Graph of contingency tables and chi-square test

La tabla de contingencia no es tan grande, pero al ser un ejemplo es util para visualizar de forma sencilla los datos y demostrar como funciona.

library("gplots")
dt <- as.table(as.matrix(housetasks))
balloonplot(t(dt), main = "housetasks", xlab ="", ylab="", 
            label = FALSE, show.margins = FALSE)

Aqui podemos ver como se puede visualizar la tabla de contigencia usando el paquete balloonplot de la biblioteca gplots en el que el tamaño de las esferas azules representa que persona realiza los trabajos o si se hace de forma conjunta.

chisq <- chisq.test(housetasks)
chisq
## 
##  Pearson's Chi-squared test
## 
## data:  housetasks
## X-squared = 1944.5, df = 36, p-value < 2.2e-16

Para una pequeña tabla de contingencia como esta se puede usar la prueba de chi-cuadrada para evaluar la dependencia de las filas con las columnas, para este caso, la relación entre las filas y las columnas es bastante estrecha.

R code to compute CA

Como se dijo anteriormente, se puede usar la funcion CA para computar el CA que en este caso está basado en los datos de housetasks

library(FactoMineR)
res.ca <- CA(housetasks, graph = FALSE)
print(res.ca)
## **Results of the Correspondence Analysis (CA)**
## The row variable has  13  categories; the column variable has 4 categories
## The chi square of independence between the two variables is equal to 1944.456 (p-value =  0 ).
## *The results are available in the following objects:
## 
##    name              description                   
## 1  "$eig"            "eigenvalues"                 
## 2  "$col"            "results for the columns"     
## 3  "$col$coord"      "coord. for the columns"      
## 4  "$col$cos2"       "cos2 for the columns"        
## 5  "$col$contrib"    "contributions of the columns"
## 6  "$row"            "results for the rows"        
## 7  "$row$coord"      "coord. for the rows"         
## 8  "$row$cos2"       "cos2 for the rows"           
## 9  "$row$contrib"    "contributions of the rows"   
## 10 "$call"           "summary called parameters"   
## 11 "$call$marge.col" "weights of the columns"      
## 12 "$call$marge.row" "weights of the rows"

Podemos ver como se creo la CA y agregando el codigo de lista se genera un output que vemos arriba

Stadistical significance

Para interpretar un CA, el primer paso es evaluar la relacion de las columnas con las filas, como se vio anteriormente, se puede usar chi-cuadrado para esto, si el estadistico que se obtiene es alto significa que las filas y las columnas son dependientes y estan enlazados

chi2 <- 1944.456
df <- (nrow(housetasks) - 1) * (ncol(housetasks) - 1)
pval <- pchisq(chi2, df = df, lower.tail = FALSE)
pval
## [1] 0

Eigenvalues / Variances

Se examina el numero de ejes que se tienen bajo consideración determinando los eigenvalues, para esto se usa la funcion get_eigenvalue

library("factoextra")
eig.val <- get_eigenvalue(res.ca)
eig.val
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1  0.5428893         48.69222                    48.69222
## Dim.2  0.4450028         39.91269                    88.60491
## Dim.3  0.1270484         11.39509                   100.00000
fviz_screeplot(res.ca, addlabels = TRUE, ylim = c(0, 50))

Con este grafico se muestra como el primer valor es el mas grande y los dos siguientes son menores, esto quiere decir que que en el primer eje hay mas datos que en los otros dos

fviz_screeplot(res.ca) +
  geom_hline(yintercept = 33.33, linetype = 2, color = "green")

En esta grafica se añadio una linea punteada verde que muestra el dato promedio para el eigenvalue, por ende, se puede concluir que las dimmensiones 1 y 2 al contener la mayoria de los datos son mejores para el CA

Biplot

En este caso, se puede usar la funcion fviz_ca_biplot para generar un biplot de las variables en las filas y columnas

fviz_ca_biplot(res.ca, repel = TRUE)

A este tipo de grafica se le conoce como symetric plot y muestra el patron global de los datos, las filas se representan con los puntos azules y las columnas con tiangulos rojos. La distancia entre los puntos azules y rojos representa la similaridad entre los datos.

Graph of row variables

Results

La funcion get_ca_row se usa para extraer los resultados de las variables en las filas. La funcion muestra una lista que contiene los coordinates, el cos2, el contribution y la inertia de las variables en las filas.

row <- get_ca_row(res.ca)
row
## Correspondence Analysis - Results for rows
##  ===================================================
##   Name       Description                
## 1 "$coord"   "Coordinates for the rows" 
## 2 "$cos2"    "Cos2 for the rows"        
## 3 "$contrib" "contributions of the rows"
## 4 "$inertia" "Inertia of the rows"

A continuacion, se muestra como estos datos pueden ser usados para generar graficos de esta forma.

head(row$coord)
##                 Dim 1      Dim 2       Dim 3
## Laundry    -0.9918368  0.4953220 -0.31672897
## Main_meal  -0.8755855  0.4901092 -0.16406487
## Dinner     -0.6925740  0.3081043 -0.20741377
## Breakfeast -0.5086002  0.4528038  0.22040453
## Tidying    -0.3938084 -0.4343444 -0.09421375
## Dishes     -0.1889641 -0.4419662  0.26694926
head(row$cos2)
##                Dim 1     Dim 2      Dim 3
## Laundry    0.7399874 0.1845521 0.07546047
## Main_meal  0.7416028 0.2323593 0.02603787
## Dinner     0.7766401 0.1537032 0.06965666
## Breakfeast 0.5049433 0.4002300 0.09482670
## Tidying    0.4398124 0.5350151 0.02517249
## Dishes     0.1181178 0.6461525 0.23572969
head(row$contrib)
##                 Dim 1    Dim 2    Dim 3
## Laundry    18.2867003 5.563891 7.968424
## Main_meal  12.3888433 4.735523 1.858689
## Dinner      5.4713982 1.321022 2.096926
## Breakfeast  3.8249284 3.698613 3.069399
## Tidying     1.9983518 2.965644 0.488734
## Dishes      0.4261663 2.844117 3.634294

Coordinates of row points

El siguiente codigo de R muestra los coordinates de cada fila en cada dimension

head(row$coord)
##                 Dim 1      Dim 2       Dim 3
## Laundry    -0.9918368  0.4953220 -0.31672897
## Main_meal  -0.8755855  0.4901092 -0.16406487
## Dinner     -0.6925740  0.3081043 -0.20741377
## Breakfeast -0.5086002  0.4528038  0.22040453
## Tidying    -0.3938084 -0.4343444 -0.09421375
## Dishes     -0.1889641 -0.4419662  0.26694926

Usando la funcion fviz_ca_row se pueden visualizar los datos de las filas como se ve a continuacion

fviz_ca_row(res.ca, repel = TRUE)

fviz_ca_row(res.ca, col.row = "darkgreen", shape.row = 10, repel = TRUE)

Como vemos, se puede alterar la forma de los puntos y el color en que se muestra los datos agragando pocas lineas de codigo

Quality of representation of rows

El resultado de los datos muestran que la tabla de contingencia esta bien representada. Pero se puede medir la calidad de la representacion de las filas usando la variable de coseno cuadrado (cos2). El cos2 mide el grado de asociacion entre las filas y columnas y un eje particular. una forma de extraer esta medicion es la siguiente

head(row$cos2, 4)
##                Dim 1     Dim 2      Dim 3
## Laundry    0.7399874 0.1845521 0.07546047
## Main_meal  0.7416028 0.2323593 0.02603787
## Dinner     0.7766401 0.1537032 0.06965666
## Breakfeast 0.5049433 0.4002300 0.09482670

Podemos ver que todos los datos estan entre 0 y 1 y que la suma de las 3 dimensiones tiene como resultado un numero cercano a 1. Para conocer la calidad de las representaciones solo se debe sumar y entre mas cercano se este al 1 mejor será la calidad.

fviz_ca_row(res.ca, col.row = "cos2",
            gradient.cols = c("#00AFBB", "#FFFF00", "#008f39"),
            repel = TRUE)

Podemos ver que para este grafico se representaron las mediciones de cos2 mediante colores, el azul representa un cos2 bajo, el amarillo un cos2 medio y verde un cos2 alto para cada uno de los datos estudiados.

fviz_ca_row(res.ca, alpha.row = "cos2", repel = TRUE)

Otra forma de representar los datos es cambiando la transparencia de los puntoos, así, a mayor transparencia menor sera el cos2 para esos datos.

library("corrplot")
corrplot(row$cos2, is.corr = TRUE)

Podemos ver como al usar la biblioteca corrplot y la funcion con el mismo nombre podemos obtener de los mismos datos en forma de tabla con nivel de cos2 en forma de esferas

fviz_cos2(res.ca, choice = "row", axes = 1:2)

Tambien se puede crear una grafica de barras que contenga los valores de cos2 usando la funcion fviz_cos2. Donde podemos observar que todos los puntos con la unica excepcion de official estan bien representados con las primeras dos dimensiones.

Contributions of rows to the dimensions

Para poder medir la proporcion que cada variable contribuye a las dimensiones se puede hacer de esta forma.

head(row$contrib)
##                 Dim 1    Dim 2    Dim 3
## Laundry    18.2867003 5.563891 7.968424
## Main_meal  12.3888433 4.735523 1.858689
## Dinner      5.4713982 1.321022 2.096926
## Breakfeast  3.8249284 3.698613 3.069399
## Tidying     1.9983518 2.965644 0.488734
## Dishes      0.4261663 2.844117 3.634294

Con los datos obtenidos en esta matriz podemos darnos cuenta que las filas que mas contribuyen a las dimensiones tambien son las mas importantes para explicar la variabilidad en la serie de datos.

library("corrplot")
corrplot(row$contrib, is.corr = FALSE)

De la misma forma que se hizo con anterioridad, se puede usar la función corrplot para graficar en forma de tabla los valores obtenidos de las contribuciones. Los resultados obtenidos se ven en la tabla anterior

fviz_contrib(res.ca, choice = "row", axes = 1, top = 10)

fviz_contrib(res.ca, choice = "row", axes = 2, top = 10)

Podemos observar como la funcion fviz_contrib se puede usar para generar un diagrama de barras con los datos de contribucion para la dimension 1 y 2, la linea roja muestra el valor promedio para cada una de las variables.

fviz_contrib(res.ca, choice = "row", axes = 1:2, top = 10)

En este grafico se muestra la contribucion total de las dos dimensiones y su valor prommedio

fviz_ca_row(res.ca, col.row = "contrib",
            gradient.cols = c("#00AFBB", "#FFFF00", "#008F39"),
            repel = TRUE)

Como se hizo con cos2, se puede ver las variables que mas contribuyen a las dimensiones con color verde y las variables que menos contribuyenn con color azul

fviz_ca_row(res.ca, alpha.row = "contrib",
            repel = TRUE)

De la misma forma, se puede controlar la transparencia para poder mostrar la contribucion de las variables.

Graph of column variables

Results

Para este caso get_ca_col se usa para extraer los datos contenidos en las columnas. De la misma forma qque en el caso de las filas, devuelve valores para coordinates, cos2, contribution y inertia de las variables en las columnas.

col <- get_ca_col(res.ca)
col
## Correspondence Analysis - Results for columns
##  ===================================================
##   Name       Description                   
## 1 "$coord"   "Coordinates for the columns" 
## 2 "$cos2"    "Cos2 for the columns"        
## 3 "$contrib" "contributions of the columns"
## 4 "$inertia" "Inertia of the columns"

Para poder acceder a los diferentes componentes se realiza el siguiente codigo

head(col$coord)
##                   Dim 1      Dim 2       Dim 3
## Wife        -0.83762154  0.3652207 -0.19991139
## Alternating -0.06218462  0.2915938  0.84858939
## Husband      1.16091847  0.6019199 -0.18885924
## Jointly      0.14942609 -1.0265791 -0.04644302
head(col$cos2)
##                   Dim 1     Dim 2       Dim 3
## Wife        0.801875947 0.1524482 0.045675847
## Alternating 0.004779897 0.1051016 0.890118521
## Husband     0.772026244 0.2075420 0.020431728
## Jointly     0.020705858 0.9772939 0.002000236
head(col$contrib)
##                 Dim 1     Dim 2      Dim 3
## Wife        44.462018 10.312237 10.8220753
## Alternating  0.103739  2.782794 82.5492464
## Husband     54.233879 17.786612  6.1331792
## Jointly      1.200364 69.118357  0.4954991

Plots: quality and contribution

Usando fviz_ca_col se puede producir graficas que muestren los puntos de las columnas, el grafico mas simple de crear es el siguiente.

fviz_ca_col(res.ca)

Como en los graficos de filas, se puede hacer un gradiente de colores para visualizar los valores de cos2

fviz_ca_col(res.ca, col.col = "cos2",
            gradient.cols = c("#00AFBB", "#FFFF00", "#008F39"),
            repel = TRUE)

fviz_cos2(res.ca, choice = "col", axes = 1:2)

Tambien se puede visualizar las mediciones de cos2 mediante un grafico de barras como el anterior

fviz_contrib(res.ca, choice = "col", axes = 1:2)

En este grafico se agrego una linea punteada para medir el valor medio de los datos

Biplot options

Un Biplot es un tipo de grafico que muestra las columnas en 2 o 3 dimensiones. Estos tipos de graficos se mostraron anteriormente pero ahora se mostraran diferentes tipos de CA biplots

Symmetric biplot

El primer tipo de biplot es el symmetric biplot y es el que habia usado en los casos anteriores en el que las filas y las columnas se representan en el mismo grafico y mediante la distancia se conoce la relación de la fila con las columnas. Este biplot es el que se muestra a continuación.

fviz_ca_biplot(res.ca, repel = TRUE)

Asymmetric biplot

Para hacer un Asymmetric biplot las filas se grafican desde el Standard coordinates y las columnas se grafican desde el principale coordinates.

fviz_ca_biplot(res.ca, 
               map = "rowprincipal", arrow = c(TRUE, TRUE),
               repel = TRUE)

Como vemos, esta es la forma de hacer un asymmetric biplot, se puede graficar mediante la funcion fviz_ca_biplot. Para calcular la similitud entre las variables se ve lo similares que son las flechas, entre mas similares sean en largo y grado de inclinación mas parecidos son las variables de filas y columnas.

Contribution biplot

En el caso de realizar un symmetric biplot se hace dificil saber que variables contribuyen mas a la solucion del CA. Para esto, se hace el contribution biplot. En este tipo de biplot, los puntos se originan desde el centro como en el asymmetric biplot, la diferencia es que entre mas contribuyan al CA mas largo será la flecha, y en caso de que contribuya poco la linea será corta

fviz_ca_biplot(res.ca, map = "colgreen", arrow = c(TRUE, TRUE),
               repel = TRUE)

Podemos ver con esta grafica que las columnas contribuyen mas que las columnas, pues sus flechas son mas largas, tambien se puede observar que holidays y repairs son las filas que mas contribuyen.

Dimension description

Para identificar facilmente las filas y las columnas que estan mas asociadas con las dimensiones principales se puede emplear la función dimdesc y el output nos dira cuales son los mas cercanos, como se ve a continuacion, en el cual se ve como se usa tomando como ejemplo la dimension 1

res.desc <- dimdesc(res.ca, axes = c(1,2))
head(res.desc[[1]]$row, 4)
##                 coord
## Laundry    -0.9918368
## Main_meal  -0.8755855
## Dinner     -0.6925740
## Breakfeast -0.5086002
head(res.desc[[1]]$col, 4)
##                   coord
## Wife        -0.83762154
## Alternating -0.06218462
## Jointly      0.14942609
## Husband      1.16091847

Para el siguiente chunk de codigo se ve la misma funcion para la dimension 2

res.desc[[2]]$row
##                 coord
## Holidays   -1.4350066
## Finances   -0.6178684
## Insurance  -0.4737832
## Dishes     -0.4419662
## Tidying    -0.4343444
## Shopping   -0.4033171
## Official    0.2536132
## Dinner      0.3081043
## Breakfeast  0.4528038
## Main_meal   0.4901092
## Laundry     0.4953220
## Driving     0.6534143
## Repairs     0.8642647
res.desc[[2]]$col
##                  coord
## Jointly     -1.0265791
## Alternating  0.2915938
## Wife         0.3652207
## Husband      0.6019199

Supplementary elements

Data format

Para esta seccion se usará la serie de datos children contenida en FactoMineR

data("children")

Specification in CA

Como se ha mencionado antes, las filas y columnas suplementarias no se usan para la definicion de las principales dimensiones. Debido a esto, los coordinates se predicen usando unicamente la informacion suministrada por la CA en las filas y columnas activas. Si se quiere especificar filas y columnas suplementarias se puede usar la funcion CA de la siguiente forma.

res.ca <- CA (children, row.sup = 15:18, col.sup = 6:8,
              graph = FALSE)

Biplot of rows and columns

fviz_ca_biplot(res.ca, repel = TRUE)

En este biplot se añadieron no solo las filas y columnas activas, tambien se añadieron las complementarias y la manera de identificar es mediante el color, los azules mas oscuros son las filas suplementarias y las de rojo oscuro son las columnas suplementarias, el resto del biplot es de la misma forma que antes, filas en azul y columnas en rojo.

fviz_ca_biplot(res.ca, repel = TRUE,
               invisible = c("row.sup", "col.cup"))

Si se quiere ocultar las filas y columnas suplementarias solo se le debe añadir el argumento invisible y el resultado es algo parecido al grafico anterior

Supplementaty rows

Los resultados predictivos (como coordinates y cos2) se hallan de la siguiente forma para las filas suplementarias

res.ca$row.sup
## $coord
##                  Dim 1     Dim 2      Dim 3      Dim 4
## comfort      0.2096705 0.7031677 0.07111168  0.3071354
## disagreement 0.1462777 0.1190106 0.17108916 -0.3132169
## world        0.5233045 0.1429707 0.08399269 -0.1063597
## to_live      0.3083067 0.5020193 0.52093397  0.2557357
## 
## $cos2
##                   Dim 1      Dim 2       Dim 3      Dim 4
## comfort      0.06892759 0.77524032 0.007928672 0.14790342
## disagreement 0.13132177 0.08692632 0.179649183 0.60210272
## world        0.87587685 0.06537746 0.022564054 0.03618163
## to_live      0.13899699 0.36853645 0.396830367 0.09563620
fviz_ca_row(res.ca, repel = TRUE)

Este grafico nos muestra las filas activas y las suplementarias

Supplementary columns

La forma de hallar los resultados predictivos para las columnas suplementarias se actua así

res.ca$col.sup
## $coord
##                  Dim 1       Dim 2       Dim 3       Dim 4
## thirty      0.10541339 -0.05969594 -0.10322613  0.06977996
## fifty      -0.01706444  0.04907657 -0.01568923 -0.01306117
## more_fifty -0.17706810 -0.04813788  0.10077299 -0.08517528
## 
## $cos2
##                Dim 1      Dim 2       Dim 3       Dim 4
## thirty     0.1375601 0.04411543 0.131910759 0.060278490
## fifty      0.0108695 0.08990298 0.009188167 0.006367804
## more_fifty 0.2860989 0.02114509 0.092666735 0.066200714
fviz_ca_col(res.ca, repel = TRUE)

Este grafico es la representacion visual de las columnas activas y las suplementarias

Filtering results

En el caso que se contenga una gran cantidad de filas y columnas se puede visualizar solo algunas de ellas usando el argumento select.row para el caso de las filas y select.col para el caso de las columnas, como se ve a continuacion para las filas

fviz_ca_row(res.ca, select.row = list(cos2 = 0.8), repel = TRUE)

fviz_ca_row(res.ca, select.row = list(cos = 5), repel = TRUE)

name <- list(name = c("employment", "fear", "future"))
fviz_ca_row(res.ca, select.row = name)

Podemos observar en este grafico que de la misma forma se pueden seleccionar por nombres

fviz_ca_biplot(res.ca, select.row = list(contrib = 5),
               select.col = list(contrib = 5)) +
  theme_minimal()

Otra forma de seleccionar filas y columnas es usando las que mas contribuyen, como se ve en el anterior grafico

Outliers

Los outliers son puntos que poseen altos valores co-ordinates y grandes contribuciones. Dichos datos, se muestran en las graficas muy lejos del centro. En el caso que hayan, los puntos de filas y columnas tendran tendencia a ser clusters en el grafico lo que dificulta la interpretacion de los mismos. Aunque en las dos series de datos que se tocaron en este capitulo no se presentan outliers, si los hubiera se deben suprimir o tratar como puntos suplementarios cuando se realice la CA

Exporting results

Export plots to PDF/PNG files

Si se quiere guardar las diferentes graficas en archivos PDF o PNG se empieza creando el grafico de interes como un objeto, luego, los graficos pueden ser exportados en un solo archivo. Los siguientes codigos muestran la forma de hacerlo

library(ggpubr)
scree.plot <- fviz_eig(res.ca)
biplot.ca <- fviz_ca_biplot(res.ca)
ggexport(plotlist = list(scree.plot, biplot.ca),
         filename = "CA.pdf")
## file saved to CA.pdf

Export results to txt/cvs files

Es mucho mas sencillo que lo visto anteriormente, pues solo debe usarse la funcion write.infile y estara listo.

write.infile(res.ca, "ca.txt", sep = "\t")
write.infile(res.ca, "ca.csv", sep = ";")

Summary

Para concluir, se describio como crear e interpretar un Correspondence analysis (CA) mediante la funcion CA del paquete FactoMineR. posterior a esto, se uso el paquete factoextra para producir visualizaciones de los resultados obtenidos. Como se dijo al principio del capitulo, existen otros paquetes y funciones que realizan las mismas CA y visualizaciones, entre estas se encuentran las siguientes.

  1. Usando dudi.coa
library("ade4")
res.ca <- dudi.coa(housetasks, scannf = FALSE, nf = 5)
  1. Usando ca
library(ca)
res.ca <- ca(housetasks)
  1. Usando corresp
library(MASS)
res.ca <- corresp(housetasks, nf = 3)
  1. Usando epCA
library("ExPosition")
res.ca <- epCA(housetasks, graph = FALSE)

De la forma que se use, todas las graficas pueden ser creadas y visualizadas mediante el paquete factoextra.

fviz_eig(res.ca)

fviz_ca_biplot(res.ca)

Fin de la presentación