Anàlisis factorial per a Dades mixtes (FAMD)

Author

Dante Conti, Sergi Ramirez, (c) IDEAI

Published

March 7, 2026

Modified

March 7, 2026

1 Introducción

El Análisis Factorial de Datos Mixtos (FAMD) es una potente técnica estadística que se utiliza para analizar conjuntos de datos que contienen variables numéricas y categóricas. Amplía el análisis factorial tradicional para gestionar tipos de datos mixtos, proporcionando una comprensión integral de la estructura subyacente de conjuntos de datos complejos.

flowchart TD
    cat?(¿BBDD Categorica?) --> |"✅"| num_too?(¿Contiene numéricas?)
    num_too? --> |"✅"| FAMD
    num_too? --> |"❌"| multiple_cat?(¿Más de dos columnas?)
    multiple_cat? --> |"✅"| MCA
    multiple_cat? --> |"❌"| CA
    cat? --> |"❌"| groups?(¿Columnas agrupadas?)
    groups? --> |"✅"| MFA
    groups? --> |"❌"| shapes?(Analysing shapes?)
    shapes? --> |"✅"| GPA
    shapes? --> |"❌"| PCA

Para poder realizar los métodos, necesitaremos importar las siguientes librerias:

## Import libraries
library(FactoMineR)
library(factoextra)
import prince
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap, Normalize

2 Planteamiento del problema

Descripció de la columna:

  • Gender: El gènere del client: Home (1), Femení (0).

  • SeniorCitizen: Indica si el client té 65 anys o més: No (0), Sí (1).

  • Partner: El contracte de servei és revenut pel soci: No (0), Sí (1).

  • Dependents: Indica si el client viu amb algun dependent: No (0), Sí (1).

  • Tenure: Indica l’import total de mesos que el client ha estat amb l’empresa.

  • PhoneService: Indica si el client es subscriu al servei de telèfon de casa amb l’empresa: No (0), Sí (1).

  • MultipleLines: Indica si el client es subscriu a diverses línies telefòniques amb l’empresa: No (0), Sí (1).

  • InternetService: Indica si el client es subscriu al servei d’Internet amb l’empresa: No (0), DSL (1), Fibra òptica (2).

  • OnlineSecurity: Indica si el client es subscriu a un servei addicional de seguretat en línia prestat per l’empresa: No (0), Sí (1), NA (2).

  • OnlineBackup: Indica si el client es subscriu a un servei de backup online addicional proporcionat per l’empresa: No (0), Sí (1), NA (2).

  • DeviceProtection: Indica si el client es subscriu a un pla addicional de protecció de dispositius per als seus equips d’Internet proporcionats per l’empresa: No (0), Sí (1), NA (2).

  • TechSupport: Indica si el client es subscriu a un pla de suport tècnic addicional de l’empresa amb temps d’espera reduïts: No (0), Sí (1), NA (2).

  • StreamingTV: Indica si el client utilitza el seu servei d’Internet per transmetre la programació de televisió d’un proveïdor de tercers: No (0), Sí (1), NA (2). L’empresa no cobra cap càrrec addicional per aquest servei.

  • StreamingMovies: Indica si el client utilitza el seu servei d’Internet per transmetre pel·lícules d’un proveïdor de tercers: No (0), Sí (1), NA (2). L’empresa no cobra cap càrrec addicional per aquest servei.

  • Contract: Indica el tipus de contracte actual del client: Mes a mes (0), Un any (1), Dos anys (2).

  • PaperlessBilling: Indica si el client ha triat facturació sense paper: No (0), Sí (1).

  • PaymentMethod: Indica com el client paga la seva factura: transferència bancària - automàtica (0), targeta de crèdit - automàtica (1), xec electrònic (2), xec per correu (3).

  • MonthlyCharges: Indica el total de la quota mensual actual del client per a tots els seus serveis de l’empresa.

  • TotalCharges: Indica el total de càrrecs del client.

  • Churn: Indica si el client es talla o no: No (0), Sí (1).

## Import data
df <- read.csv('https://raw.githubusercontent.com/nchelaru/data-prep/refs/heads/master/telco_cleaned_renamed.csv')

## Preview data
head(df)
  Gender    SeniorCitizen    Partner    Dependents Tenure    PhoneService
1 Female No SeniorCitizen    Partner No Dependents      1 No PhoneService
2   Male No SeniorCitizen No Partner No Dependents     34    PhoneService
3   Male No SeniorCitizen No Partner No Dependents      2    PhoneService
4   Male No SeniorCitizen No Partner No Dependents     45 No PhoneService
5 Female No SeniorCitizen No Partner No Dependents      2    PhoneService
6 Female No SeniorCitizen No Partner No Dependents      8    PhoneService
     MultipleLines InternetService    OnlineSecurity    OnlineBackup
1 No MultipleLines             DSL No OnlineSecurity    OnlineBackup
2 No MultipleLines             DSL    OnlineSecurity No OnlineBackup
3 No MultipleLines             DSL    OnlineSecurity    OnlineBackup
4 No MultipleLines             DSL    OnlineSecurity No OnlineBackup
5 No MultipleLines     Fiber optic No OnlineSecurity No OnlineBackup
6    MultipleLines     Fiber optic No OnlineSecurity No OnlineBackup
     DeviceProtection    TechSupport    StreamingTV    StreamingMovies
1 No DeviceProtection No TechSupport No StreamingTV No StreamingMovies
2    DeviceProtection No TechSupport No StreamingTV No StreamingMovies
3 No DeviceProtection No TechSupport No StreamingTV No StreamingMovies
4    DeviceProtection    TechSupport No StreamingTV No StreamingMovies
5 No DeviceProtection No TechSupport No StreamingTV No StreamingMovies
6    DeviceProtection No TechSupport    StreamingTV    StreamingMovies
        Contract    PaperlessBilling             PaymentMethod MonthlyCharges
1 Month-to-month    PaperlessBilling          Electronic check          29.85
2       One year No PaperlessBilling              Mailed check          56.95
3 Month-to-month    PaperlessBilling              Mailed check          53.85
4       One year No PaperlessBilling Bank transfer (automatic)          42.30
5 Month-to-month    PaperlessBilling          Electronic check          70.70
6 Month-to-month    PaperlessBilling          Electronic check          99.65
  TotalCharges    Churn
1        29.85 No Churn
2      1889.50 No Churn
3       108.15    Churn
4      1840.75 No Churn
5       151.65    Churn
6       820.50    Churn

Visualizamos la estructura de los datos:

str(df)
'data.frame':   7032 obs. of  20 variables:
 $ Gender          : chr  "Female" "Male" "Male" "Male" ...
 $ SeniorCitizen   : chr  "No SeniorCitizen" "No SeniorCitizen" "No SeniorCitizen" "No SeniorCitizen" ...
 $ Partner         : chr  "Partner" "No Partner" "No Partner" "No Partner" ...
 $ Dependents      : chr  "No Dependents" "No Dependents" "No Dependents" "No Dependents" ...
 $ Tenure          : int  1 34 2 45 2 8 22 10 28 62 ...
 $ PhoneService    : chr  "No PhoneService" "PhoneService" "PhoneService" "No PhoneService" ...
 $ MultipleLines   : chr  "No MultipleLines" "No MultipleLines" "No MultipleLines" "No MultipleLines" ...
 $ InternetService : chr  "DSL" "DSL" "DSL" "DSL" ...
 $ OnlineSecurity  : chr  "No OnlineSecurity" "OnlineSecurity" "OnlineSecurity" "OnlineSecurity" ...
 $ OnlineBackup    : chr  "OnlineBackup" "No OnlineBackup" "OnlineBackup" "No OnlineBackup" ...
 $ DeviceProtection: chr  "No DeviceProtection" "DeviceProtection" "No DeviceProtection" "DeviceProtection" ...
 $ TechSupport     : chr  "No TechSupport" "No TechSupport" "No TechSupport" "TechSupport" ...
 $ StreamingTV     : chr  "No StreamingTV" "No StreamingTV" "No StreamingTV" "No StreamingTV" ...
 $ StreamingMovies : chr  "No StreamingMovies" "No StreamingMovies" "No StreamingMovies" "No StreamingMovies" ...
 $ Contract        : chr  "Month-to-month" "One year" "Month-to-month" "One year" ...
 $ PaperlessBilling: chr  "PaperlessBilling" "No PaperlessBilling" "PaperlessBilling" "No PaperlessBilling" ...
 $ PaymentMethod   : chr  "Electronic check" "Mailed check" "Mailed check" "Bank transfer (automatic)" ...
 $ MonthlyCharges  : num  29.9 57 53.9 42.3 70.7 ...
 $ TotalCharges    : num  29.9 1889.5 108.2 1840.8 151.7 ...
 $ Churn           : chr  "No Churn" "No Churn" "Churn" "No Churn" ...
pydf = pd.read_csv('https://raw.githubusercontent.com/nchelaru/data-prep/refs/heads/master/telco_cleaned_renamed.csv')

Visualizamos la estructura de los datos:

pydf.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7032 entries, 0 to 7031
Data columns (total 20 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   Gender            7032 non-null   object 
 1   SeniorCitizen     7032 non-null   object 
 2   Partner           7032 non-null   object 
 3   Dependents        7032 non-null   object 
 4   Tenure            7032 non-null   int64  
 5   PhoneService      7032 non-null   object 
 6   MultipleLines     7032 non-null   object 
 7   InternetService   7032 non-null   object 
 8   OnlineSecurity    7032 non-null   object 
 9   OnlineBackup      7032 non-null   object 
 10  DeviceProtection  7032 non-null   object 
 11  TechSupport       7032 non-null   object 
 12  StreamingTV       7032 non-null   object 
 13  StreamingMovies   7032 non-null   object 
 14  Contract          7032 non-null   object 
 15  PaperlessBilling  7032 non-null   object 
 16  PaymentMethod     7032 non-null   object 
 17  MonthlyCharges    7032 non-null   float64
 18  TotalCharges      7032 non-null   float64
 19  Churn             7032 non-null   object 
dtypes: float64(2), int64(1), object(17)
memory usage: 1.1+ MB

Los datos contienen 20 columnas divididas en: - Numéricas: Tenure, MonthlyCharges y TotalCharges - Categóricas: Gender, SeniorCitizen, Partner, Dependents, PhoneService, MultipleLines, InternetService, OnlineSecurity, OnlineBackup, DeviceProtection, TechSupport, StreamingTV, StreamingMovies, Contract, PaperlessBilling, PaymentMethod y Churn (variable respuesta)

Consejo

El objetivo de este estudio es poder estudiar las relaciones y asociaciones que existen en los clientes de la empresa Telecom.

2.1 Entrenamiento

La función FAMD() del paquete FactoMineRse puede utilizar para calcular los planos factoriales. La descripción de la función es la siguiente:

FAMD (base, ncp = 5, sup.var = NULL, ind.sup = NULL, graph = TRUE)
  • base: Un data.frame con n filas (individuos) y p columnas (variables).

  • ncp: El número de dimensiones que se mantienen en los resultados (por defecto 5)

  • sup.var: Un vector que indica los índices de las variables suplementarias.

  • ind.sup: Un vector que indica los índices de los individuos suplementarios.

  • graph: Un valor lógico. Si es VERDADERO, se muestra un gráfico.

A continuación, vamos a calcular el FAMD de la siguiente manera:

## FAMD
res.famd <- FAMD(df, sup.var = 20, graph = FALSE, ncp = 25)

La salida que obtenemos con la función FAMD() es una lista que incluye:

print(res.famd)
*The results are available in the following objects:

  name          description                             
1 "$eig"        "eigenvalues and inertia"               
2 "$var"        "Results for the variables"             
3 "$ind"        "results for the individuals"           
4 "$quali.var"  "Results for the qualitative variables" 
5 "$quanti.var" "Results for the quantitative variables"

La función prince.FAMD() del paquete princese puede utilizar para calcular los planos factoriales. La descripción de la función es la siguiente:

famd = prince.FAMD(n_components = 2, n_iter = 3, copy = True, check_input = True, random_state = 42, engine = "sklearn", handle_unknown = "error")
  • n_components: El número de dimensiones que se mantienen en los resultados (por defecto 2)

  • n_iter: El número de iteraciones de las cuales ha de realizar el FAMD (por defecto 3)

  • copy: Indica si queremos realizar una copia o por el contrario de la base de datos

  • check_input: Valida las variables de entrada

  • random_state: Asigna una semilla para los cálculos

A continuación, vamos a calcular el FAMD de la siguiente manera:

famdPy = prince.FAMD(n_components=10, random_state=42)
famdPy = famdPy.fit(pydf)

2.2 Visualización e interpretación

Utilizaremos las siguientes funciones del paquete factoextra para poder obtener las interpretaciones correspondientes:

  • get_eigenvalue(res.famd): Extraer los valores propios/varianzas retenidas por cada dimensión (eje).

  • fviz_eig(res.famd): Visualizar los valores propios/varianzas.

  • get_famd_ind(res.famd): Extraer los resultados para individuos.

  • get_famd_var(res.famd): Extraer los resultados de las variables cuantitativas y cualitativas.

  • fviz_famd_ind(res.famd) y fviz_famd_var(res.famd): Visualizar los resultados para individuos y variables, respectivamente.

Aviso

Recordad que, para la interpretación de FAMD se ha de realizar lo mismo hecho en clases anteriores en métodos como el ACP, ACS y ACM.

2.3 Eigenvalues y Eigenvectors

La proporción de varianzas retenidas (eigenvalues) por las diferentes dimensiones (ejes) se puede extraer utilizando la función get_eigenvalue() del paquete factoextra de la siguiente manera:

eig.val <- get_eigenvalue(res.famd)
head(eig.val)
      eigenvalue variance.percent cumulative.variance.percent
Dim.1   5.257621        22.859222                    22.85922
Dim.2   2.855902        12.416963                    35.27619
Dim.3   1.860948         8.091076                    43.36726
Dim.4   1.164287         5.062115                    48.42938
Dim.5   1.049924         4.564885                    52.99426
Dim.6   1.015145         4.413675                    57.40794

La función fviz_eig() o fviz_screeplot() del paquete factoextra se puede utilizar para dibujar el diagrama de codo (los porcentajes de inercia explicados por cada dimensión de FAMD):

fviz_screeplot(res.famd)

La proporción de varianzas retenidas (eigenvalues) por las diferentes dimensiones (ejes) se puede extraer utilizando el método .eigenvalues_ de la siguiente manera:

eigenvalues = famdPy.eigenvalues_
famdPy.eigenvalues_summary
          eigenvalue % of variance % of variance (cumulative)
component                                                    
0             36.181         4.36%                      4.36%
1             26.517         3.19%                      7.55%
2             16.198         1.95%                      9.51%
3             11.046         1.33%                     10.84%
4             10.134         1.22%                     12.06%
5              9.378         1.13%                     13.19%
6              9.195         1.11%                     14.30%
7              9.107         1.10%                     15.39%
8              9.077         1.09%                     16.49%
9              9.066         1.09%                     17.58%

La función fviz_eig() o fviz_screeplot() del paquete factoextra se puede utilizar para dibujar el diagrama de codo (los porcentajes de inercia explicados por cada dimensión de FAMD):

# Hacer el scree plot
plt.figure(figsize=(8, 5))
plt.plot(range(1, len(eigenvalues) + 1), eigenvalues, marker='o')
plt.title('Scree Plot - FAMD')
plt.xlabel('Componentes')
plt.ylabel('Valor propio (Eigenvalue)')
plt.xticks(range(1, len(eigenvalues) + 1))
([<matplotlib.axis.XTick object at 0x000001E6863819D0>, <matplotlib.axis.XTick object at 0x000001E68635A550>, <matplotlib.axis.XTick object at 0x000001E686377F50>, <matplotlib.axis.XTick object at 0x000001E6862F6810>, <matplotlib.axis.XTick object at 0x000001E686408F90>, <matplotlib.axis.XTick object at 0x000001E686329610>, <matplotlib.axis.XTick object at 0x000001E686328490>, <matplotlib.axis.XTick object at 0x000001E686409BD0>, <matplotlib.axis.XTick object at 0x000001E6863CB4D0>, <matplotlib.axis.XTick object at 0x000001E6863BFA10>], [Text(1, 0, '1'), Text(2, 0, '2'), Text(3, 0, '3'), Text(4, 0, '4'), Text(5, 0, '5'), Text(6, 0, '6'), Text(7, 0, '7'), Text(8, 0, '8'), Text(9, 0, '9'), Text(10, 0, '10')])
plt.grid(True)
plt.show()

2.4 Variables

2.4.1 Todas las variables

La función get_mfa_var() del paquete factoextra se utiliza para extraer los resultados de las variables. Por defecto, esta función devuelve una lista con las coordenadas, el coseno\(^2\) y la contribución de todas las variables:

(var <- get_famd_var(res.famd))
FAMD results for variables 
 ===================================================
  Name       Description                      
1 "$coord"   "Coordinates"                    
2 "$cos2"    "Cos2, quality of representation"
3 "$contrib" "Contributions"                  

2.4.1.1 Coordenadas de las componentes

Se puede acceder a los diferentes componentes de la siguiente manera:

head(var$coord[, 1:4])
                      Dim.1        Dim.2        Dim.3        Dim.4
Tenure         0.4206809111 0.2864370404 5.868863e-02 0.0218736221
MonthlyCharges 0.7115470075 0.2017404911 2.527110e-03 0.0009313836
TotalCharges   0.7986771845 0.0407946811 2.999847e-02 0.0137505310
Gender         0.0001947487 0.0001642962 3.424638e-06 0.0015453361
SeniorCitizen  0.0304048842 0.1378319021 5.802770e-03 0.0057238890
Partner        0.0969690101 0.1609366512 6.777893e-02 0.3774002728

2.4.1.2 Coseno\(^2\)

A continuación se muestra el coseno\(^2\) que representa la calidad de la representación en el mapa factorial.

head(var$cos2[, 1:4])
                      Dim.1        Dim.2        Dim.3        Dim.4
Tenure         1.769724e-01 8.204618e-02 3.444355e-03 4.784553e-04
MonthlyCharges 5.062991e-01 4.069923e-02 6.386284e-06 8.674754e-07
TotalCharges   6.378852e-01 1.664206e-03 8.999080e-04 1.890771e-04
Gender         3.792705e-08 2.699325e-08 1.172814e-11 2.388064e-06
SeniorCitizen  9.244570e-04 1.899763e-02 3.367214e-05 3.276290e-05
Partner        9.402989e-03 2.590061e-02 4.593984e-03 1.424310e-01

2.4.1.3 Contribuciones

En el siguiente apartado, podemos visualizar la contribución de cada una de las varaibles a las dimensiones.

head(var$contrib[, 1:4])
                      Dim.1        Dim.2        Dim.3       Dim.4
Tenure          8.001354821 10.029653733 3.1536958900  1.87871471
MonthlyCharges 13.533630663  7.063986094 0.1357969462  0.07999608
TotalCharges   15.190847437  1.428434412 1.6119995933  1.18102638
Gender          0.003704122  0.005752867 0.0001840266  0.13272816
SeniorCitizen   0.578301180  4.826213291 0.3118180199  0.49162203
Partner         1.844351468  5.635230981 3.6421732973 32.41472495

La siguiente figura muestra la correlación entre las variables, tanto cuantitativas como cualitativas, y las dimensiones principales, así como la contribución de las variables a las dimensiones 1 y 2. Se utilizan las siguientes funciones del paquete factoextra:

  • fviz_famd_var(): para representar gráficamente variables cuantitativas y cualitativas

  • fviz_contrib(): para visualizar la contribución de las variables a las dimensiones principales

fviz_famd_var(res.famd, repel = TRUE)

A continuación vamos a visualizar las contribuciones de las variables en la primera dimensión.

# Contribution to the first dimension
fviz_contrib(res.famd, "var", axes = 1)

Seguidamente podemos ver las contribuciones de las variables en la 2a dimensión.

# Contribution to the second dimension
fviz_contrib(res.famd, "var", axes = 2)

La línea discontinua roja en el gráfico anterior indica el valor promedio esperado, si las contribuciones fueran uniformes.

De los gráficos anteriormente expuestos se puede observar que:

  • Las variables más contribuyentes a la primera dimensión són:

  • Las variables que más contribuyen a la segunda dimensión son:

2.4.1.4 Coordenadas de las componentes

Se puede acceder a los diferentes componentes de la siguiente manera:

## famd.row_coordinates(pydf)  ## Individuos
famdPy.column_coordinates_
component                0         1  ...         8             9
variable                              ...                        
MonthlyCharges    0.516084  0.326985  ...  0.000024  2.719971e-04
TotalCharges      0.758263  0.001235  ...  0.001354  1.399417e-06
Churn             0.031624  0.389555  ...  0.001300  1.998385e-03
Contract          0.204277  0.430340  ...  0.003679  9.335352e-04
Dependents        0.014209  0.206706  ...  0.000808  1.045339e-06
DeviceProtection  0.426754  0.002936  ...  0.006802  1.348613e-07
Gender            0.000248  0.000380  ...  0.006765  7.022369e-03
InternetService   0.292035  0.506334  ...  0.005546  1.554956e-03
MultipleLines     0.206875  0.054604  ...  0.002214  4.321594e-04
OnlineBackup      0.349894  0.002057  ...  0.001307  1.451828e-03
OnlineSecurity    0.272749  0.039203  ...  0.010315  1.100983e-03
PaperlessBilling  0.051292  0.241663  ...  0.001531  2.319590e-02
Partner           0.143598  0.096932  ...  0.000460  7.417890e-04
PaymentMethod     0.204439  0.381225  ...  0.020124  1.076496e-03
PhoneService      0.001444  0.012175  ...  0.000041  1.245809e-05
SeniorCitizen     0.012635  0.167889  ...  0.000537  4.012970e-03
StreamingMovies   0.406131  0.088201  ...  0.000606  3.132390e-05
StreamingTV       0.399842  0.090072  ...  0.003217  1.702668e-03
TechSupport       0.335530  0.027956  ...  0.000144  5.169755e-06
Tenure            0.525252  0.173087  ...  0.945035  9.635537e-01

[20 rows x 10 columns]

2.4.1.5 Coseno\(^2\)

A continuación se muestra el coseno\(^2\) que representa la calidad de la representación en el mapa factorial.

famdPy.column_coordinates_ ** 2
component                    0             1  ...             8             9
variable                                      ...                            
MonthlyCharges    2.663429e-01  1.069192e-01  ...  5.978147e-10  7.398242e-08
TotalCharges      5.749627e-01  1.524285e-06  ...  1.834568e-06  1.958368e-12
Churn             1.000095e-03  1.517529e-01  ...  1.690637e-06  3.993541e-06
Contract          4.172909e-02  1.851923e-01  ...  1.353859e-05  8.714880e-07
Dependents        2.018980e-04  4.272720e-02  ...  6.534426e-07  1.092735e-12
DeviceProtection  1.821192e-01  8.619380e-06  ...  4.627334e-05  1.818758e-14
Gender            6.145598e-08  1.445026e-07  ...  4.577077e-05  4.931367e-05
InternetService   8.528444e-02  2.563737e-01  ...  3.075429e-05  2.417889e-06
MultipleLines     4.279747e-02  2.981547e-03  ...  4.902979e-06  1.867618e-07
OnlineBackup      1.224257e-01  4.230329e-06  ...  1.709518e-06  2.107805e-06
OnlineSecurity    7.439183e-02  1.536858e-03  ...  1.064014e-04  1.212164e-06
PaperlessBilling  2.630919e-03  5.840094e-02  ...  2.342487e-06  5.380497e-04
Partner           2.062052e-02  9.395777e-03  ...  2.113838e-07  5.502509e-07
PaymentMethod     4.179515e-02  1.453325e-01  ...  4.049852e-04  1.158845e-06
PhoneService      2.085858e-06  1.482284e-04  ...  1.666081e-09  1.552041e-10
SeniorCitizen     1.596509e-04  2.818686e-02  ...  2.887529e-07  1.610393e-05
StreamingMovies   1.649421e-01  7.779385e-03  ...  3.674741e-07  9.811864e-10
StreamingTV       1.598736e-01  8.112913e-03  ...  1.034660e-05  2.899077e-06
TechSupport       1.125803e-01  7.815585e-04  ...  2.060583e-08  2.672637e-11
Tenure            2.758900e-01  2.995894e-02  ...  8.930918e-01  9.284358e-01

[20 rows x 10 columns]

2.4.1.6 Contribuciones

En el siguiente apartado, podemos visualizar la contribución de cada una de las varaibles a las dimensiones.

(famdPy.column_contributions_)
component                0         1  ...         8             9
variable                              ...                        
MonthlyCharges    0.014264  0.012331  ...  0.000003  3.000298e-05
TotalCharges      0.020957  0.000047  ...  0.000149  1.543644e-07
Churn             0.000874  0.014691  ...  0.000143  2.204343e-04
Contract          0.005646  0.016229  ...  0.000405  1.029748e-04
Dependents        0.000393  0.007795  ...  0.000089  1.153075e-07
DeviceProtection  0.011795  0.000111  ...  0.000749  1.487605e-08
Gender            0.000007  0.000014  ...  0.000745  7.746111e-04
InternetService   0.008071  0.019095  ...  0.000611  1.715214e-04
MultipleLines     0.005718  0.002059  ...  0.000244  4.766988e-05
OnlineBackup      0.009671  0.000078  ...  0.000144  1.601457e-04
OnlineSecurity    0.007538  0.001478  ...  0.001136  1.214453e-04
PaperlessBilling  0.001418  0.009114  ...  0.000169  2.558652e-03
Partner           0.003969  0.003655  ...  0.000051  8.182395e-05
PaymentMethod     0.005650  0.014377  ...  0.002217  1.187443e-04
PhoneService      0.000040  0.000459  ...  0.000004  1.374205e-06
SeniorCitizen     0.000349  0.006331  ...  0.000059  4.426556e-04
StreamingMovies   0.011225  0.003326  ...  0.000067  3.455221e-06
StreamingTV       0.011051  0.003397  ...  0.000354  1.878148e-04
TechSupport       0.009274  0.001054  ...  0.000016  5.702562e-07
Tenure            0.014517  0.006527  ...  0.104116  1.062860e-01

[20 rows x 10 columns]

La siguiente figura muestra la correlación entre las variables, tanto cuantitativas como cualitativas, y las dimensiones principales, así como la contribución de las variables a las dimensiones 1 y 2.

# Coordenadas de las variables (componentes 1 y 2)
coords = famdPy.column_coordinates_

# Elegimos los dos primeros componentes
x = coords[0]
y = coords[1]

plt.figure(figsize=(8, 8))
plt.axhline(0, color='gray', lw=1)
plt.axvline(0, color='gray', lw=1)

# Dibujar solo puntos con etiquetas
plt.scatter(x, y, color='white')

for i in range(len(coords)):
    plt.text(x[i], y[i], coords.index[i], fontsize=9, color="red" , ha='center', va='center')

plt.title("Variables en el plano factorial (FAMD)")
plt.xlabel("Dim 1")
plt.ylabel("Dim 2")
plt.grid(True)
plt.axis('equal')
(np.float64(-0.03791314869182619), np.float64(0.7961761225283498), np.float64(-0.025316678052831332), np.float64(0.531650239109458))
plt.show()

A continuación vamos a visualizar las contribuciones de las variables en la primera dimensión.

# Obtener coordenadas de las variables
coords = famdPy.column_coordinates_

# Calcular la contribución (cos²) al eje 1
# Es la coordenada al cuadrado de cada variable en ese eje
contrib = (coords[0] ** 2)

# Normalizar en porcentaje
contrib_percent = 100 * contrib / contrib.sum()

# Ordenar de mayor a menor
contrib_percent = contrib_percent.sort_values(ascending=False)

# Calcular la media
mean_contrib = 100 / len(contrib_percent)

# Graficar
plt.figure(figsize=(10, 6))
sns.barplot(x=contrib_percent.values, y=contrib_percent.index, palette="Blues_d")
plt.axvline(mean_contrib, color='red', linestyle='--', label=f'Media = {mean_contrib:.2f}%')
plt.xlabel('Contribución al componente 1 (%)')
plt.title('Contribución de variables al eje 1 (FAMD)')
plt.legend()
plt.tight_layout()
plt.show()

Seguidamente podemos ver las contribuciones de las variables en la 2a dimensión.

# Obtener coordenadas de las variables
coords = famdPy.column_coordinates_

# Calcular la contribución (cos²) al eje 1
# Es la coordenada al cuadrado de cada variable en ese eje
contrib = (coords[1] ** 2)

# Normalizar en porcentaje
contrib_percent = 100 * contrib / contrib.sum()

# Ordenar de mayor a menor
contrib_percent = contrib_percent.sort_values(ascending=False)

# Calcular la media
mean_contrib = 100 / len(contrib_percent)

# Graficar
plt.figure(figsize=(10, 6))
sns.barplot(x=contrib_percent.values, y=contrib_percent.index, palette="Blues_d")
plt.axvline(mean_contrib, color='red', linestyle='--', label=f'Media = {mean_contrib:.2f}%')
plt.xlabel('Contribución al componente 2 (%)')
plt.title('Contribución de variables al eje 2 (FAMD)')
plt.legend()
plt.tight_layout()
plt.show()

La línea discontinua roja en el gráfico anterior indica el valor promedio esperado, si las contribuciones fueran uniformes.

De los gráficos anteriormente expuestos se puede observar que:

  • Las variables más contribuyentes a la primera dimensión són:

  • Las variables que más contribuyen a la segunda dimensión son:

2.4.2 Variables cuantitativas

Para extraer los resultados de las variables cuantitativas, se debe realizar el siguiente proceso:

(quanti.var <- get_famd_var(res.famd, "quanti.var"))
FAMD results for quantitative variables 
 ===================================================
  Name       Description                      
1 "$coord"   "Coordinates"                    
2 "$cos2"    "Cos2, quality of representation"
3 "$contrib" "Contributions"                  

A continuación vamos a visualizar el círculo unitario tal y como extraiamos de la aplicación del ACP. Para no superponer las etiquetas de las variables numéricas, vamos a utilizar el parámetro repel = TRUE.

fviz_famd_var(res.famd, "quanti.var", repel = TRUE,
              col.var = "black")

El gráfico de variables (círculo unitario) muestra la relación entre las variables, la calidad de su representación, así como la correlación entre las variables y las dimensiones.

Las variables cuantitativas más contribuyentes se pueden resaltar en el diagrama de dispersión mediante el argumento col.var = "contrib". Esto produce un degradado de colores, que se puede personalizar mediante el argumento gradient.cols.

fviz_famd_var(res.famd, "quanti.var", col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)

Del mismo modo, puede resaltar variables cuantitativas utilizando sus valores cos\(^2\) que representan la calidad de la representación en el mapa factorial. Si una variable está bien representada por dos dimensiones, la suma del cos\(^2\) se aproxima a uno. Para algunos de los elementos, es posible que se requieran más de 2 dimensiones para representar perfectamente los datos.

fviz_famd_var(res.famd, "quanti.var", col.var = "cos2", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)

2.4.3 Variables cualitativas

Al igual que las variables cuantitativas, los resultados de las variables cualitativas se pueden extraer de la siguiente manera:

(quali.var <- get_famd_var(res.famd, "quali.var"))
FAMD results for qualitative variable categories 
 ===================================================
  Name       Description                      
1 "$coord"   "Coordinates"                    
2 "$cos2"    "Cos2, quality of representation"
3 "$contrib" "Contributions"                  

Para visualizar las variables cualitativas, se ha de escribir el siguiente código:

#| echo: true
#| eval: true
#| warning: false
#| message: false
#| error: false

fviz_famd_var(res.famd, "quali.var", col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

La gráfica anterior muestra las categorías de las variables categóricas.

2.5 Individuos

Si se desean hacer gráficos individuales se realiza lo siguiente.

(ind <- get_famd_ind(res.famd))
FAMD results for individuals 
 ===================================================
  Name       Description                      
1 "$coord"   "Coordinates"                    
2 "$cos2"    "Cos2, quality of representation"
3 "$contrib" "Contributions"                  

Para representar gráficamente a los individuos, utilizaremos la función fviz_mfa_ind() del paquete factoextra. Por defecto, los individuos están coloreados en azul. Sin embargo, al igual que las variables, también es posible colorear a los individuos por sus valores de cos2 y contribución:

fviz_famd_ind(res.famd, col.ind = "cos2", 
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)

Las categorias de las variables cualitativas se muestran en negro. Para poder eliminar dichas modalidades, utilizamos el parámetro invisible = "quali.var".

Los individuos con perfiles similares se encuentran cerca en el mapa factorial.

Es posible colorear a los individuos utilizando cualquiera de las variables cualitativas en la tabla de datos inicial. Para ello, se utiliza el argumento habillage en la función fviz_famd_ind().

fviz_mfa_ind(res.famd, 
             habillage = "Churn", # color by groups 
             palette = c("#00AFBB", "#E7B800", "#FC4E07"),
             addEllipses = TRUE, ellipse.type = "confidence", 
             repel = TRUE # Avoid text overlapping
             ) 

Si lo que queremos es colorear los individuos usando múltiples variables categóricas al mismo tiempo, se deberá de utilizar la función fviz_ellipses() del paquete factoextra de la siguiente forma:

fviz_ellipses(res.famd, c("Churn", "Gender"), repel = TRUE)

También se puede identificar que variables categóricas queremos representar con el id de las variables:

fviz_ellipses(res.famd, 1:2, geom = "point")

Aquesta web està creada por Dante Conti y Sergi Ramírez, (c) 2026