Análisis Factorial Exploratorio

Author

Katerin

Published

May 15, 2025

Análisis Factorial Exploratorio en RStudio

Cargar los datos

library(readr)
diabetes <- read_csv("C:/Users/MINEDUCYT/Desktop/CICLOI_2025/SeminarioI/diabetes.csv")
Rows: 768 Columns: 9
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
dbl (9): Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, D...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(diabetes,10)
# A tibble: 10 × 9
   Pregnancies Glucose BloodPressure SkinThickness Insulin   BMI
         <dbl>   <dbl>         <dbl>         <dbl>   <dbl> <dbl>
 1           6     148            72            35       0  33.6
 2           1      85            66            29       0  26.6
 3           8     183            64             0       0  23.3
 4           1      89            66            23      94  28.1
 5           0     137            40            35     168  43.1
 6           5     116            74             0       0  25.6
 7           3      78            50            32      88  31  
 8          10     115             0             0       0  35.3
 9           2     197            70            45     543  30.5
10           8     125            96             0       0   0  
# ℹ 3 more variables: DiabetesPedigreeFunction <dbl>, Age <dbl>, Outcome <dbl>

Ver si existen valores perdidos

sum(is.na(diabetes))
[1] 0

En este caso como observamos no existen valores perdidos por lo que nuestra base de datos es adecuada para seguir con nuestro análisis.

# Renombrar columnas ya que en l base original están en ingles
colnames(diabetes) <- c("Embarazos", "Glucosa", "Presión arterial", "Grosor de la piel", "Insulina", "IMC", "Función de pedigrí de diabetes", "Edad", "Resultado")
# Ver estructura
str(diabetes)
spc_tbl_ [768 × 9] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Embarazos                     : num [1:768] 6 1 8 1 0 5 3 10 2 8 ...
 $ Glucosa                       : num [1:768] 148 85 183 89 137 116 78 115 197 125 ...
 $ Presión arterial              : num [1:768] 72 66 64 66 40 74 50 0 70 96 ...
 $ Grosor de la piel             : num [1:768] 35 29 0 23 35 0 32 0 45 0 ...
 $ Insulina                      : num [1:768] 0 0 0 94 168 0 88 0 543 0 ...
 $ IMC                           : num [1:768] 33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
 $ Función de pedigrí de diabetes: num [1:768] 0.627 0.351 0.672 0.167 2.288 ...
 $ Edad                          : num [1:768] 50 31 32 21 33 30 26 29 53 54 ...
 $ Resultado                     : num [1:768] 1 0 1 0 1 0 1 0 1 1 ...
 - attr(*, "spec")=
  .. cols(
  ..   Pregnancies = col_double(),
  ..   Glucose = col_double(),
  ..   BloodPressure = col_double(),
  ..   SkinThickness = col_double(),
  ..   Insulin = col_double(),
  ..   BMI = col_double(),
  ..   DiabetesPedigreeFunction = col_double(),
  ..   Age = col_double(),
  ..   Outcome = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 

Podemos ver que nuestra base de datos, todas las variables son de tipo numéricas y que cada variable contiene 768 datos cada una.

Determinar las variables independientes

diabetes_seleccionada <- diabetes[, c(1,2, 3, 4, 5, 6, 7, 8)]
head(diabetes_seleccionada,10)
# A tibble: 10 × 8
   Embarazos Glucosa `Presión arterial` `Grosor de la piel` Insulina   IMC
       <dbl>   <dbl>              <dbl>               <dbl>    <dbl> <dbl>
 1         6     148                 72                  35        0  33.6
 2         1      85                 66                  29        0  26.6
 3         8     183                 64                   0        0  23.3
 4         1      89                 66                  23       94  28.1
 5         0     137                 40                  35      168  43.1
 6         5     116                 74                   0        0  25.6
 7         3      78                 50                  32       88  31  
 8        10     115                  0                   0        0  35.3
 9         2     197                 70                  45      543  30.5
10         8     125                 96                   0        0   0  
# ℹ 2 more variables: `Función de pedigrí de diabetes` <dbl>, Edad <dbl>

Escalar los datos

diabetes_escalado <- scale(diabetes_seleccionada)

Matriz de correlación

cor_matrix_diab <- cor(diabetes_escalado)
cor(diabetes_escalado)
                                 Embarazos    Glucosa Presión arterial
Embarazos                       1.00000000 0.12945867       0.14128198
Glucosa                         0.12945867 1.00000000       0.15258959
Presión arterial                0.14128198 0.15258959       1.00000000
Grosor de la piel              -0.08167177 0.05732789       0.20737054
Insulina                       -0.07353461 0.33135711       0.08893338
IMC                             0.01768309 0.22107107       0.28180529
Función de pedigrí de diabetes -0.03352267 0.13733730       0.04126495
Edad                            0.54434123 0.26351432       0.23952795
                               Grosor de la piel    Insulina        IMC
Embarazos                            -0.08167177 -0.07353461 0.01768309
Glucosa                               0.05732789  0.33135711 0.22107107
Presión arterial                      0.20737054  0.08893338 0.28180529
Grosor de la piel                     1.00000000  0.43678257 0.39257320
Insulina                              0.43678257  1.00000000 0.19785906
IMC                                   0.39257320  0.19785906 1.00000000
Función de pedigrí de diabetes        0.18392757  0.18507093 0.14064695
Edad                                 -0.11397026 -0.04216295 0.03624187
                               Función de pedigrí de diabetes        Edad
Embarazos                                         -0.03352267  0.54434123
Glucosa                                            0.13733730  0.26351432
Presión arterial                                   0.04126495  0.23952795
Grosor de la piel                                  0.18392757 -0.11397026
Insulina                                           0.18507093 -0.04216295
IMC                                                0.14064695  0.03624187
Función de pedigrí de diabetes                     1.00000000  0.03356131
Edad                                               0.03356131  1.00000000

En la matriz de correlación vemos que la mayoría de variables no tienen correlación entes ellas la única correlación que se puede considerar “correlación positiva moderada” es Edad con Embarazos ya que su correlación es de 0.54 lo que nos dice que si una variable aumenta la otra también aumenta por lo que se dice que a mayor edad mayor es la probabilidad de haber tenido más de un embarazo.

Las demás variables poseen correlaciones débiles tanto como positivo como negativo.

library(corrplot)
Warning: package 'corrplot' was built under R version 4.5.0
corrplot 0.95 loaded
rosa_palette <- colorRampPalette(c("#7B1FA2", "#E91E63", "#F8BBD0"))(200)

# Graficar la matriz de correlación con tonos rosas
corrplot(cor_matrix_diab,
         method = "color",
         
         col = rosa_palette,
         tl.cex = 0.7,
         addCoef.col = "black")

Al observar este mapa o gráfico de correlación, lo que se dijo anteriormente es lo mismo solo que de una manera más entendible. Edad con Embarazo posee una correlación moderada (r=0.54), IMC con Grosor de la piel posee una correlación débil (r=0.39) ya que está por debajo del 0.5 lo que significa que a mayor índice de masa corporal tiende a poseer más grosor de la piel, Glucosa con Edad poseen una correlación baja (r=0.26) esto significa que a mayor edad tiene a aumentar la glucosa, La Insulina con Grosor de la piel tiene una correlación baja (r=0.44) esto se puede asociar que con acumulación de grasa y la Presión arterial con Edad poseen una correlación baja (0.24) esto se puede asociar con la vejez y que eso aumenta la presión arterial.

Prueba de adecuación KMO

library(psych)
Warning: package 'psych' was built under R version 4.3.2
KMO(cor_matrix_diab)
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = cor_matrix_diab)
Overall MSA =  0.59
MSA for each item = 
                     Embarazos                        Glucosa 
                          0.56                           0.56 
              Presión arterial              Grosor de la piel 
                          0.69                           0.57 
                      Insulina                            IMC 
                          0.57                           0.65 
Función de pedigrí de diabetes                           Edad 
                          0.77                           0.55 

Según las directrices de Kaiser (1974), un punto de corte sugerido para determinar la factorabilidad de los datos de muestro es KMO ≥ 60. El KMO total en este caso es de 0.59, lo que indica que, con base en esta prueba, podamos realizar un análisis factorial ya que aproximándolo nos da 0.60 por lo que si podemos hacer un AFE ya que es aceptable.

Prueba de Bartlett

cortest.bartlett(cor_matrix_diab, n = nrow(diabetes_escalado))
$chisq
[1] 948.2262

$p.value
[1] 1.25755e-181

$df
[1] 28

Si él es menor a 0.05 (p<0.05) nuestro AFE es adecuado en este caso nuestro p_value fue de 1.25755e-181 lo que quiere decir que nuestro p_value es adecuado y podemos seguir con nuestro Análisis Factorial Exploratorio.

Aplicar nuestro Análisis Factorial

num_factores_sin_rotar <- fa(diabetes_escalado, nfactors = 2, rotate = "none", fm = "ml")
print(num_factores_sin_rotar)
Factor Analysis using method =  ml
Call: fa(r = diabetes_escalado, nfactors = 2, rotate = "none", fm = "ml")
Standardized loadings (pattern matrix) based upon correlation matrix
                                 ML2   ML1   h2   u2 com
Embarazos                      -0.04  0.58 0.34 0.66 1.0
Glucosa                         0.31  0.28 0.18 0.82 2.0
Presión arterial                0.32  0.26 0.17 0.83 1.9
Grosor de la piel               0.70 -0.13 0.50 0.50 1.1
Insulina                        0.58 -0.05 0.34 0.66 1.0
IMC                             0.53  0.05 0.28 0.72 1.0
Función de pedigrí de diabetes  0.28  0.03 0.08 0.92 1.0
Edad                            0.00  0.93 0.87 0.13 1.0

                       ML2  ML1
SS loadings           1.38 1.38
Proportion Var        0.17 0.17
Cumulative Var        0.17 0.34
Proportion Explained  0.50 0.50
Cumulative Proportion 0.50 1.00

Mean item complexity =  1.3
Test of the hypothesis that 2 factors are sufficient.

df null model =  28  with the objective function =  1.24 with Chi Square =  948.23
df of  the model are 13  and the objective function was  0.18 

The root mean square of the residuals (RMSR) is  0.05 
The df corrected root mean square of the residuals is  0.08 

The harmonic n.obs is  768 with the empirical chi square  128.47  with prob <  4.2e-21 
The total n.obs was  768  with Likelihood Chi Square =  134.88  with prob <  2.2e-22 

Tucker Lewis Index of factoring reliability =  0.714
RMSEA index =  0.11  and the 90 % confidence intervals are  0.094 0.128
BIC =  48.51
Fit based upon off diagonal values = 0.94
Measures of factor score adequacy             
                                                   ML2  ML1
Correlation of (regression) scores with factors   0.83 0.94
Multiple R square of scores with factors          0.69 0.88
Minimum correlation of possible factor scores     0.38 0.76

Para la variable Embarazo ML1 está asociado moderadamente y explica un 34% de su varianza.

Para la variable Glucosa débil la carga en ambos factores ya que solo un 17.8% de su varianza es explicada.

Para la variable Presión arterial la relación es muy débil.

Para la variable Grosor de la piel esta asociad fuertemente a ML2. Bien explicada.

Para la variable Insulina está asociada a ML2. Aceptable.

Para la variable IMC está asociada moderadamente a ML2.

Para la variable Función de pedigrí tiene baja carga y baja comunalidad por lo que se podría eliminar.

Para la variable Edad tiene fuerte asociación con ML1 eso significa que existe excelente comunalidad.

ML1 representa un factor que está relacionado con edad y embarazos.

ML2 representa un factor que está relacionado con grosor de piel, insulina e IMC.

Determinar número de factores

# Scree plot y eigenvalores
scree(cor(diabetes))

Para determinar el número de factores, observamos los puntos sin relleno y al comparar la línea que está en 1 que es la regla de Kaiser, tomamos los factores que están por encima de él, en este caso es 1 el que sobre pasa a 1 pero tomaremos 2 para mayor análisis por son los únicos factores con eigenvalores mayores a 1. Los puntos rellenados de negro nos ayudarían para un análisis de componentes principales.

fa.parallel(diabetes_escalado, fa = "fa", fm = "ml", n.iter = 100)

Parallel analysis suggests that the number of factors =  3  and the number of components =  NA 

Para determinar el número de factores, los identificamos comparando la línea azul que son los datos reales con las líneas rojas que son los datos que son simulados. Al visualizar el gráfico se toman 2 factores ya que el tercero toca lo que es la línea imaginaria de 1 que observamos en el grafico anterior.

Matriz de cargas factoriales

mfac <- fa(diabetes_escalado, nfactors = 2, rotate = "none", fm = "ml")
print(mfac$loadings)

Loadings:
                               ML2    ML1   
Embarazos                              0.582
Glucosa                         0.315  0.282
Presión arterial                0.319  0.257
Grosor de la piel               0.698 -0.125
Insulina                        0.578       
IMC                             0.529       
Función de pedigrí de diabetes  0.280       
Edad                                   0.933

                 ML2   ML1
SS loadings    1.382 1.376
Proportion Var 0.173 0.172
Cumulative Var 0.173 0.345

Las cargas factoriales nos indican cuanto existe la correlación cada variable con cada uno de los factores.

Para ML1: Para este factor las variables más dominantes son Edad con un valor de 0.933, Embarazos con un valor de 0.582, la variable Glucosa con un valor de 0.282 y la variable Presión arterial con un valor de 0.257

Para ML2: Para este factor las variables que dominan son Grosor de la piel (0.698), Insulina (0.578), IMC (0.529) y la Glucosa (0.315)

Cada factor explica un 17.3% de lo que es la varianza.

Estos ambos explican un 34.5% de la varianza total de los datos.

Varimax

# Rotación Varimax
mod_rot <- fa(diabetes_escalado, nfactors = 2, rotate = "varimax", fm = "ml")
print(mod_rot$loadings)

Loadings:
                               ML2    ML1   
Embarazos                              0.581
Glucosa                         0.310  0.288
Presión arterial                0.315  0.263
Grosor de la piel               0.700 -0.113
Insulina                        0.579       
IMC                             0.528       
Función de pedigrí de diabetes  0.280       
Edad                                   0.933

                 ML2   ML1
SS loadings    1.380 1.378
Proportion Var 0.172 0.172
Cumulative Var 0.172 0.345

Para factor 1: La variable Edad tiene un valor de 0.933 y es muy fuerte, la variable Embarazos con un valor fuerte de 0.581, la variable Glucosa con un valor ligero de 0.288 y la variable Presión arterial con un valor ligero de 0.263

El factor 2 con variables con mayores cargas son: Grosor de la piel con 0.700 (fuerte), Insulina con 0.579 (fuerte), IMC con 0.528 (fuerte), Presión arterial y Glucosa son moderadas con 0.31 y Función de pedigrí de diabetes con un valor ligero de 0.28.

Cada factor explica aproximadamente un 17.2% de lo que es la varianza total, ambos factores juntos explican el 34.4%.

print(mod_rot)
Factor Analysis using method =  ml
Call: fa(r = diabetes_escalado, nfactors = 2, rotate = "varimax", fm = "ml")
Standardized loadings (pattern matrix) based upon correlation matrix
                                 ML2   ML1   h2   u2 com
Embarazos                      -0.05  0.58 0.34 0.66 1.0
Glucosa                         0.31  0.29 0.18 0.82 2.0
Presión arterial                0.31  0.26 0.17 0.83 1.9
Grosor de la piel               0.70 -0.11 0.50 0.50 1.1
Insulina                        0.58 -0.04 0.34 0.66 1.0
IMC                             0.53  0.06 0.28 0.72 1.0
Función de pedigrí de diabetes  0.28  0.04 0.08 0.92 1.0
Edad                           -0.02  0.93 0.87 0.13 1.0

                       ML2  ML1
SS loadings           1.38 1.38
Proportion Var        0.17 0.17
Cumulative Var        0.17 0.34
Proportion Explained  0.50 0.50
Cumulative Proportion 0.50 1.00

Mean item complexity =  1.3
Test of the hypothesis that 2 factors are sufficient.

df null model =  28  with the objective function =  1.24 with Chi Square =  948.23
df of  the model are 13  and the objective function was  0.18 

The root mean square of the residuals (RMSR) is  0.05 
The df corrected root mean square of the residuals is  0.08 

The harmonic n.obs is  768 with the empirical chi square  128.47  with prob <  4.2e-21 
The total n.obs was  768  with Likelihood Chi Square =  134.88  with prob <  2.2e-22 

Tucker Lewis Index of factoring reliability =  0.714
RMSEA index =  0.11  and the 90 % confidence intervals are  0.094 0.128
BIC =  48.51
Fit based upon off diagonal values = 0.94
Measures of factor score adequacy             
                                                   ML2  ML1
Correlation of (regression) scores with factors   0.83 0.94
Multiple R square of scores with factors          0.69 0.88
Minimum correlation of possible factor scores     0.38 0.76

El factor ML1: Las variables que más se asocian es la Edad con un valor de 0.93 y Embarazos con un valor de 0.58

El factor ML2: Las variables más asociadas son el Grosor de piel con un valor de 0.70, la variable Insulina con un valor de 0.58 y IMC con un valor de 0.53

Factores con rotación

library(psych)
fa.diagram(mod_rot)

Las variables asociadas fuertemente para el factor 1 (ML1) son: Edad con una carga de 0.9 y Embarazos con una carga de 0.6

Las variables asociadas fuertemente para el factor 2 (ML2) son: Grosor de la piel con una carga de 0.7, Insulina con una carga de 0.6, IMC con una carga de 0.5, Presión arterial con una carga de 0.3 y Glucosa con una carga de 0.3.

Análisis Factorial Exploratorio en Python

Cargar los datos

import pandas as pd

diabetes = pd.read_csv("C:/Users/MINEDUCYT/Desktop/CICLOI_2025/SeminarioI/diabetes.csv")

print(diabetes.head(10))
   Pregnancies  Glucose  BloodPressure  ...  DiabetesPedigreeFunction  Age  Outcome
0            6      148             72  ...                     0.627   50        1
1            1       85             66  ...                     0.351   31        0
2            8      183             64  ...                     0.672   32        1
3            1       89             66  ...                     0.167   21        0
4            0      137             40  ...                     2.288   33        1
5            5      116             74  ...                     0.201   30        0
6            3       78             50  ...                     0.248   26        1
7           10      115              0  ...                     0.134   29        0
8            2      197             70  ...                     0.158   53        1
9            8      125             96  ...                     0.232   54        1

[10 rows x 9 columns]

Ver si existen valores perdidos

valores_perdidos = diabetes.isna().sum().sum()
print(valores_perdidos)
0
# Asignar nuevos nombres a las columnas de la base de datos
diabetes.columns = [
    "Embarazos", 
    "Glucosa", 
    "Presión arterial", 
    "Grosor de la piel", 
    "Insulina", 
    "IMC", 
    "Función de pedigrí de diabetes", 
    "Edad", 
    "Resultado"
]

print(diabetes.head())
   Embarazos  Glucosa  ...  Edad  Resultado
0          6      148  ...    50          1
1          1       85  ...    31          0
2          8      183  ...    32          1
3          1       89  ...    21          0
4          0      137  ...    33          1

[5 rows x 9 columns]
# Mostrar la estructura de la base de datos
diabetes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 768 entries, 0 to 767
Data columns (total 9 columns):
 #   Column                          Non-Null Count  Dtype  
---  ------                          --------------  -----  
 0   Embarazos                       768 non-null    int64  
 1   Glucosa                         768 non-null    int64  
 2   Presión arterial                768 non-null    int64  
 3   Grosor de la piel               768 non-null    int64  
 4   Insulina                        768 non-null    int64  
 5   IMC                             768 non-null    float64
 6   Función de pedigrí de diabetes  768 non-null    float64
 7   Edad                            768 non-null    int64  
 8   Resultado                       768 non-null    int64  
dtypes: float64(2), int64(7)
memory usage: 54.1 KB

Determinar las variables independientes

# Seleccionamos las primeras 8 columnas ya que la ultima no nos será úti
diabetes_seleccionada = diabetes.iloc[:, 0:8]

print(diabetes_seleccionada.head(10))
   Embarazos  Glucosa  ...  Función de pedigrí de diabetes  Edad
0          6      148  ...                           0.627    50
1          1       85  ...                           0.351    31
2          8      183  ...                           0.672    32
3          1       89  ...                           0.167    21
4          0      137  ...                           2.288    33
5          5      116  ...                           0.201    30
6          3       78  ...                           0.248    26
7         10      115  ...                           0.134    29
8          2      197  ...                           0.158    53
9          8      125  ...                           0.232    54

[10 rows x 8 columns]

Escalar los datos

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

diabetes_escalado = scaler.fit_transform(diabetes_seleccionada)

Matriz de correlación

import pandas as pd
from sklearn.preprocessing import StandardScaler

# Convertir el array escalado a DataFrame
diabetes_escalado_df = pd.DataFrame(diabetes_escalado, columns=diabetes_seleccionada.columns)

# Calcular matriz de correlación
cor_matrix_diab = diabetes_escalado_df.corr()
print(cor_matrix_diab)
                                Embarazos  ...      Edad
Embarazos                        1.000000  ...  0.544341
Glucosa                          0.129459  ...  0.263514
Presión arterial                 0.141282  ...  0.239528
Grosor de la piel               -0.081672  ... -0.113970
Insulina                        -0.073535  ... -0.042163
IMC                              0.017683  ...  0.036242
Función de pedigrí de diabetes  -0.033523  ...  0.033561
Edad                             0.544341  ...  1.000000

[8 rows x 8 columns]
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

# Crear una paleta de colores rosas
rosa_palette = sns.color_palette(["#F8BBD0", "#E91E63", "#7B1FA2"])
custom_cmap = sns.diverging_palette(320, 340, s=85, l=45, n=200, as_cmap=True)

# Graficar la matriz de correlación
plt.figure(figsize=(10, 8))
sns.heatmap(
    cor_matrix_diab, 
    annot=True, 
    cmap=custom_cmap, 
    fmt=".2f", 
    linewidths=0.5, 
    linecolor='white', 
    cbar=True, 
    square=True, 
    annot_kws={"size": 9},
)

plt.title("Matriz de Correlación - Diabetes (Tonos Rosas)", fontsize=14)
plt.xticks(rotation=45, ha='right')
(array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]), [Text(0.5, 0, 'Embarazos'), Text(1.5, 0, 'Glucosa'), Text(2.5, 0, 'Presión arterial'), Text(3.5, 0, 'Grosor de la piel'), Text(4.5, 0, 'Insulina'), Text(5.5, 0, 'IMC'), Text(6.5, 0, 'Función de pedigrí de diabetes'), Text(7.5, 0, 'Edad')])
plt.yticks(rotation=0)
(array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]), [Text(0, 0.5, 'Embarazos'), Text(0, 1.5, 'Glucosa'), Text(0, 2.5, 'Presión arterial'), Text(0, 3.5, 'Grosor de la piel'), Text(0, 4.5, 'Insulina'), Text(0, 5.5, 'IMC'), Text(0, 6.5, 'Función de pedigrí de diabetes'), Text(0, 7.5, 'Edad')])
plt.tight_layout()
plt.show()

Prueba de adecuación KMO

from factor_analyzer.factor_analyzer import calculate_kmo
from sklearn.preprocessing import StandardScaler
import pandas as pd

kmo_all, kmo_model = calculate_kmo(diabetes_escalado_df)

print("Índice KMO general:", round(kmo_model, 3))
Índice KMO general: 0.589
print("Índices KMO individuales por variable:")
Índices KMO individuales por variable:
kmo_df = pd.DataFrame({
    "Variable": diabetes_seleccionada.columns,
    "KMO individual": kmo_all
})
print(kmo_df)
                         Variable  KMO individual
0                       Embarazos        0.564747
1                         Glucosa        0.557003
2                Presión arterial        0.692977
3               Grosor de la piel        0.569892
4                        Insulina        0.568152
5                             IMC        0.650799
6  Función de pedigrí de diabetes        0.772770
7                            Edad        0.547812

Prueba de Bartlett

from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
from sklearn.preprocessing import StandardScaler
import pandas as pd

chi_square_value, p_value = calculate_bartlett_sphericity(diabetes_escalado_df)

print(f"Chi-cuadrado de Bartlett: {chi_square_value:.3f}")
Chi-cuadrado de Bartlett: 948.226
print(f"Valor p: {p_value:.5f}")
Valor p: 0.00000

Aplicar nuestro Análisis Factorial

from factor_analyzer import FactorAnalyzer
from sklearn.preprocessing import StandardScaler
import pandas as pd

# Análisis factorial sin rotación, 2 factores, método máxima verosimilitud
fa = FactorAnalyzer(n_factors=2, rotation=None, method='ml')
fa.fit(diabetes_escalado_df)
FactorAnalyzer(method='ml', n_factors=2, rotation=None, rotation_kwargs={})
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
# Imprimir resultados
loadings = pd.DataFrame(fa.loadings_, index=diabetes_escalado_df.columns, columns=["Factor1", "Factor2"])
print("Cargas factoriales (sin rotación):")
Cargas factoriales (sin rotación):
print(loadings)
                                 Factor1   Factor2
Embarazos                      -0.041898  0.581863
Glucosa                         0.314599  0.282201
Presión arterial                0.319159  0.257128
Grosor de la piel               0.697744 -0.125402
Insulina                        0.577948 -0.045842
IMC                             0.529062  0.046976
Función de pedigrí de diabetes  0.280388  0.030185
Edad                            0.000309  0.933174
# Varianzas explicadas
print("\nVarianzas explicadas:")

Varianzas explicadas:
print("Eigenvalues:", fa.get_eigenvalues()[0][:2])
Eigenvalues: [2.09437995 1.73121014]
print("Proporción de varianza explicada:", fa.get_factor_variance()[1])
Proporción de varianza explicada: [0.17274814 0.17200943]
print("Varianza acumulada:", fa.get_factor_variance()[2])
Varianza acumulada: [0.17274814 0.34475756]

Determinar número de factores

# Obtener eigenvalores
ev, v = fa.get_eigenvalues()

# Graficar Scree Plot
x = range(1, len(ev) + 1)
plt.figure(figsize=(8, 5))
plt.plot(x, ev, marker='o', label="Datos reales")
plt.axhline(y=1, color='r', linestyle='--', label="Eigenvalor = 1")
plt.title('Scree Plot - Eigenvalores')
plt.xlabel('Factor / Componente')
plt.ylabel('Eigenvalor')
plt.legend()
plt.grid(True)
plt.show()

Matriz de cargas factoriales

import numpy as np
import pandas as pd
from factor_analyzer import FactorAnalyzer
from sklearn.preprocessing import StandardScaler

# Obtener las cargas factoriales
loadings = fa.loadings_

print(loadings)
[[-4.18978326e-02  5.81862882e-01]
 [ 3.14599258e-01  2.82201436e-01]
 [ 3.19158592e-01  2.57127781e-01]
 [ 6.97744033e-01 -1.25401816e-01]
 [ 5.77947801e-01 -4.58419036e-02]
 [ 5.29061993e-01  4.69756409e-02]
 [ 2.80388441e-01  3.01852744e-02]
 [ 3.09211630e-04  9.33173991e-01]]

Varimax

import numpy as np
import pandas as pd
from factor_analyzer import FactorAnalyzer
from sklearn.preprocessing import StandardScaler

# Obtener las cargas factoriales después de la rotación
loadings_rot = fa.loadings_

# Imprimir las cargas factoriales después de la rotación
print(loadings_rot)
[[-4.18978326e-02  5.81862882e-01]
 [ 3.14599258e-01  2.82201436e-01]
 [ 3.19158592e-01  2.57127781e-01]
 [ 6.97744033e-01 -1.25401816e-01]
 [ 5.77947801e-01 -4.58419036e-02]
 [ 5.29061993e-01  4.69756409e-02]
 [ 2.80388441e-01  3.01852744e-02]
 [ 3.09211630e-04  9.33173991e-01]]

Factores con rotación

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
from factor_analyzer import FactorAnalyzer
from sklearn.preprocessing import StandardScaler


# Obtener nombres reales de las variables
var_names = diabetes.columns.tolist()[:loadings_rot.shape[0]]

# Crear un gráfico de diagrama usando NetworkX
G = nx.Graph()

# Agregar nodos para los factores
for i in range(loadings_rot.shape[1]):
    G.add_node(f"Factor {i+1}", pos=(i, 1))

# Agregar nodos para las variables con sus nombres reales
for i, var in enumerate(var_names):
    G.add_node(var, pos=(i, 0))

# Agregar las aristas entre variables y factores basadas en las cargas factoriales
threshold = 0.3  # Umbral para mostrar relaciones significativas
for i, var in enumerate(var_names):
    for j in range(loadings_rot.shape[1]):
        if abs(loadings_rot[i, j]) > threshold:
            G.add_edge(var, f"Factor {j+1}", weight=loadings_rot[i, j])

# Obtener posiciones de los nodos
pos = nx.get_node_attributes(G, 'pos')

# Dibujar el gráfico
plt.figure(figsize=(12, 6))
pos = nx.spring_layout(G, seed=42)  # Layout automático reproducible
nx.draw(G, pos, with_labels=True, node_size=2000, node_color='lightgreen', 
        font_size=10, font_weight='bold', edge_color='gray')

# Mostrar el gráfico
plt.title("Diagrama de Cargas Factoriales (Varimax)")
plt.show()