Está en la página 1de 80

ANÁLISIS FACTORIAL EXPLORATORIO DE LA VARIABLE ENSEÑANZA VIRTUAL EN RSTUDIO

# Instalamos librerías

install.packages("readxl")

install.packages("psych")

install.packages("corrplot")

install.packages("corrr")

# Cargamos las librerías

library(readxl)

library(psych)

library(corrplot)

library(corrr)

# Leemos los datos de un fichero en excel

datosEV = read_excel("C:\\ejemplos\\EncuestaSVJ.xlsx",sheet="EV")

datosEV

View(datosEV)

SALIDA:
# Estudio de condiciones previas

# Calculamos la matriz de correlación

matriz_correlacion = cor(datosEV)
# Vemos y analizamos la matriz de correlación para ver si hay interrelación entre nuestras
variables

View(matriz_correlacion)

SALIDA:

# Vemos que la mayoría de correlaciones están sobre 0.3

cov(datosEV)

> cov(datosEV)

E1 E2 E3 E4 E5 E6 E7 E8

E1 1.4197050 0.8334317 0.8145919 0.6463717 0.8070403 0.7258997 0.7192920 0.6132547

E2 0.8334317 1.6207080 0.7899508 0.6423206 0.6969125 0.7224779 0.6335693 0.4741003

E3 0.8145919 0.7899508 1.6638151 0.4945919 0.9498132 0.7348279 0.7936873 0.6933727

E4 0.6463717 0.6423206 0.4945919 1.2508161 0.6425959 0.6414553 0.5148476 0.5288102

E5 0.8070403 0.6969125 0.9498132 0.6425959 1.7353786 0.7480826 1.2426745 0.7686922

E6 0.7258997 0.7224779 0.7348279 0.6414553 0.7480826 1.2331170 0.6674926 0.6771288

E7 0.7192920 0.6335693 0.7936873 0.5148476 1.2426745 0.6674926 1.7711898 0.7447001

E8 0.6132547 0.4741003 0.6933727 0.5288102 0.7686922 0.6771288 0.7447001 1.1069420

E9 0.5432842 0.6040905 0.4816912 0.5032842 0.5204326 0.7076500 0.5509931 0.5718387

E10 0.6035005 0.5558702 0.6315831 0.4923894 0.8865290 0.6633235 0.8119567 0.6744149

E11 0.7672370 0.7227729 0.8786037 0.5805703 1.1914258 0.8419272 1.0364798 0.7835595


E12 0.6002753 0.6295379 0.6065290 0.5691642 0.6740216 0.6433825 0.8646608 0.6190364

E13 0.6851524 0.5375418 0.6707571 0.4718191 0.8462144 0.6080629 0.8932547 0.7352999

E14 0.7457620 0.5388201 0.6315634 0.5813176 0.8399607 0.6980924 0.9040511 0.7298328

E15 0.6708751 0.6045231 0.6312291 0.5864307 0.6394100 0.6891642 0.6563225 0.5430482

E16 0.5650344 0.6331367 0.6619272 0.3961455 0.7459194 0.6015339 0.6436382 0.5023795

E9 E10 E11 E12 E13 E14 E15 E16

E1 0.5432842 0.6035005 0.7672370 0.6002753 0.6851524 0.7457620 0.6708751 0.5650344

E2 0.6040905 0.5558702 0.7227729 0.6295379 0.5375418 0.5388201 0.6045231 0.6331367

E3 0.4816912 0.6315831 0.8786037 0.6065290 0.6707571 0.6315634 0.6312291 0.6619272

E4 0.5032842 0.4923894 0.5805703 0.5691642 0.4718191 0.5813176 0.5864307 0.3961455

E5 0.5204326 0.8865290 1.1914258 0.6740216 0.8462144 0.8399607 0.6394100 0.7459194

E6 0.7076500 0.6633235 0.8419272 0.6433825 0.6080629 0.6980924 0.6891642 0.6015339

E7 0.5509931 0.8119567 1.0364798 0.8646608 0.8932547 0.9040511 0.6563225 0.6436382

E8 0.5718387 0.6744149 0.7835595 0.6190364 0.7352999 0.7298328 0.5430482 0.5023795

E9 1.1979548 0.6531760 0.7286136 0.7385644 0.5245624 0.6983677 0.5821829 0.5223206

E10 0.6531760 1.3818682 1.0027139 0.6906588 0.8458210 0.7002163 0.5921337 0.6329990

E11 0.7286136 1.0027139 1.5947493 0.7064307 0.8590757 0.8042675 0.7195674 0.6721927

E12 0.7385644 0.6906588 0.7064307 1.3911504 0.8020059 0.9033628 0.7415536 0.6527827

E13 0.5245624 0.8458210 0.8590757 0.8020059 1.4578564 0.9737266 0.7347886 0.7185841

E14 0.6983677 0.7002163 0.8042675 0.9033628 0.9737266 1.4530777 0.7761652 0.6662537

E15 0.5821829 0.5921337 0.7195674 0.7415536 0.7347886 0.7761652 1.0558112 0.6093609

E16 0.5223206 0.6329990 0.6721927 0.6527827 0.7185841 0.6662537 0.6093609 1.5299312

>

# Gráfico de las correlaciones

corrplot(cor(datosEV), order = "hclust", tl.col='black', tel.cex=1)

SALIDA:

> corrplot(cor(datosEV), order = "hclust", tl.col='black', tel.cex=1)


Warning messages:
1: In text.default(pos.xlabel[, 1], pos.xlabel[, 2], newcolnames, srt = tl.srt, :
"tel.cex" is not a graphical parameter
2: In text.default(pos.ylabel[, 1], pos.ylabel[, 2], newrownames, col = tl.col, :
"tel.cex" is not a graphical parameter
3: In title(title, ...) : "tel.cex" is not a graphical parameter
>

# La mayoría de las correlaciones entre las variables se encuentran sobre el valor de 0.4, lo cual
es un buen indicador

# Cálculo de los estimadores del Test de Bartlett y el MSA(KMO)

# Queremos rechazar la hipótesis nula que las variables no son correlacionales

bartlett.test(datosEV)

SALIDA:

> bartlett.test(datosEV)

Bartlett test of homogeneity of variances

data: datosEV
Bartlett's K-squared = 40.508, df = 15, p-value =
0.0003799

Warning messages:
1: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
2: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
3: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
4: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
5: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
6: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
7: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
8: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
9: In doTryCatch(return(expr), name, parentenv, handler) :
"tel.cex" is not a graphical parameter
>

# Vemos que el valor de ρ es menor que el valor de significancia de 0.05, por lo que
rechazamos la hipótesis nula y podemos decir que nuestras variables si están correlacionadas

# Determinmante de la matriz de correlación

det(matriz_correlacion)

SALIDA:

> det(matriz_correlacion)

[1] 6.023443e-05

>

# El determinante de la matriz de correlación es cercano a cero

# Las variables están correlacionadas, tiene sentido hacer el Análisis Factorial Exploratorio

# Usamos el indicador KMO, el cual nos dice como una variable puede ser explicada a través de
las demás

KMO(datosEV)

SALIDA:

> KMO(datosEV)
Kaiser-Meyer-Olkin factor adequacy

Call: KMO(r = datosEV)

Overall MSA = 0.94

MSA for each item =

E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12 E13

0.96 0.93 0.95 0.94 0.91 0.96 0.93 0.96 0.92 0.95 0.94 0.94 0.93

E14 E15 E16

0.94 0.95 0.96

>

# Los valores están por encima de 0.5, pero es mejor si son mayores a 0.7, con lo que estamos
listos para realizar el Análisis Factorial Exploratorio

# Análisis Factorial, iniciamos con 3 factores sin rotar

analFact = factanal(datosEV, factors = 3, rotation = "none", scores = "Bartlett")

analFact

SALIDA:

> analFact = factanal(datosEV, factors = 3, rotation = "none", scores = "Bartlett")

> analFact

Call:

factanal(x = datosEV, factors = 3, scores = "Bartlett", rotation = "none")

Uniquenesses:

E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11

0.484 0.521 0.526 0.593 0.165 0.353 0.363 0.466 0.492 0.482 0.322

E12 E13 E14 E15 E16

0.395 0.359 0.312 0.367 0.649

Loadings:

Factor1 Factor2 Factor3

E1 0.681 0.210
E2 0.583 0.127 0.350

E3 0.651 0.208

E4 0.581 0.152 0.215

E5 0.804 -0.433

E6 0.733 0.182 0.276

E7 0.746 -0.226 -0.173

E8 0.729

E9 0.632 0.317

E10 0.716

E11 0.805 -0.164

E12 0.699 0.291 -0.177

E13 0.736 -0.302

E14 0.756 0.210 -0.268

E15 0.742 0.289

E16 0.588

Factor1 Factor2 Factor3

SS loadings 7.895 0.681 0.573

Proportion Var 0.493 0.043 0.036

Cumulative Var 0.493 0.536 0.572

Test of the hypothesis that 3 factors are sufficient.

The chi square statistic is 138.44 on 75 degrees of freedom.

The p-value is 1.16e-05

>

# Análisis Factorial con rotación varimax para tener mejores resultados

analFactRot = factanal(datosEV, factors = 3, rotation = "varimax", scores = "Bartlett")

analFactRot

SALIDA:

> analFactRot = factanal(datosEV, factors = 3, rotation = "varimax", scores = "Bartlett")


> analFactRot

Call:

factanal(x = datosEV, factors = 3, scores = "Bartlett", rotation = "varimax")

Uniquenesses:

E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11

0.484 0.521 0.526 0.593 0.165 0.353 0.363 0.466 0.492 0.482 0.322

E12 E13 E14 E15 E16

0.395 0.359 0.312 0.367 0.649

Loadings:

Factor1 Factor2 Factor3

E1 0.564 0.297 0.331

E2 0.631 0.171 0.228

E3 0.488 0.192 0.447

E4 0.535 0.270 0.219

E5 0.303 0.222 0.833

E6 0.675 0.333 0.284

E7 0.200 0.415 0.651

E8 0.394 0.451 0.418

E9 0.522 0.467 0.133

E10 0.335 0.429 0.471

E11 0.435 0.329 0.617

E12 0.348 0.660 0.218

E13 0.205 0.658 0.408

E14 0.283 0.708 0.326

E15 0.510 0.566 0.230

E16 0.340 0.375 0.308

Factor1 Factor2 Factor3


SS loadings 3.176 3.104 2.869

Proportion Var 0.198 0.194 0.179

Cumulative Var 0.198 0.392 0.572

Test of the hypothesis that 3 factors are sufficient.

The chi square statistic is 138.44 on 75 degrees of freedom.

The p-value is 1.16e-05

>

# Determinamos el número de factores

# Valores propios

ev = eigen(matriz_correlacion) # Obtención de los autovalores

ev

SALIDA:

> ev = eigen(matriz_correlacion) # Obtención de los autovalores

There were 18 warnings (use warnings() to see them)

> ev

eigen() decomposition

$values

[1] 8.3518500 1.0538790 0.9581659 0.7459430 0.6937302 0.5753718 0.5526124 0.5039080

[9] 0.4358902 0.4300266 0.3711596 0.3265545 0.2953303 0.2540524 0.2465903 0.2049358

$vectors

[,1] [,2] [,3] [,4] [,5] [,6]

[1,] -0.2476281 -0.26593987 0.212115955 -0.05786524 -0.293421417 0.164125700

[2,] -0.2176679 -0.46586457 0.236678094 -0.23271912 0.097184620 -0.331376957

[3,] -0.2336865 -0.06779315 0.439916227 -0.19451968 -0.008706711 0.434046889

[4,] -0.2142866 -0.40556673 -0.027848915 0.35479675 -0.335062795 -0.288907062

[5,] -0.2646218 0.26537733 0.377987230 0.09380610 -0.057189008 -0.255371831

[6,] -0.2651253 -0.26046703 0.013930694 0.16237094 0.208359286 0.229300534

[7,] -0.2531897 0.35345333 0.150005621 0.05895741 -0.189953074 -0.384201300


[8,] -0.2606710 0.11735303 -0.005215104 0.27705911 -0.018600417 0.459253377

[9,] -0.2349684 -0.21053120 -0.366416254 0.20146111 0.478945669 -0.001080736

[10,] -0.2543602 0.24005116 -0.016458501 0.16915620 0.387620499 -0.098160398

[11,] -0.2776952 0.17754291 0.206648264 0.21320508 0.273166033 -0.071254908

[12,] -0.2538482 0.01057909 -0.411116912 -0.11216882 -0.096313332 -0.222116767

[13,] -0.2594653 0.30580467 -0.180569108 -0.17195100 -0.209037875 0.162926879

[14,] -0.2665313 0.13480567 -0.328364643 -0.04065287 -0.305371305 0.106040183

[15,] -0.2685319 -0.14031727 -0.224933655 -0.13330245 -0.179696787 0.087049504

[16,] -0.2155670 0.03517612 -0.042603924 -0.69795785 0.276097575 -0.075187815

[,7] [,8] [,9] [,10] [,11] [,12]

[1,] 0.07146694 0.41933501 -0.3812013 0.27074934 -0.41005590 -0.33714207

[2,] 0.25316543 0.28756121 0.2685009 0.20020796 0.42213213 0.18502260

[3,] 0.25152188 -0.24330189 0.3426530 -0.29537778 -0.30721399 0.17770935

[4,] -0.51637177 -0.20062347 0.2420752 -0.01512547 -0.17360859 0.12386105

[5,] -0.08349309 -0.17717199 -0.1860636 0.01924259 -0.06325779 0.18336124

[6,] -0.06789386 -0.18761976 -0.3096143 -0.13533291 0.44871840 -0.35253734

[7,] 0.30875323 -0.21640518 -0.1212809 0.08055468 0.13568554 -0.24935510

[8,] -0.07389551 -0.19900146 0.2934115 0.46462073 0.22582731 -0.13060648

[9,] 0.27487096 -0.07671759 -0.1559394 0.17132638 -0.26766105 0.30197218

[10,] -0.23359862 0.44390570 0.2689296 -0.11767481 -0.23136607 -0.25953848

[11,] -0.01980581 0.11348014 -0.1669012 -0.22309947 0.03930188 0.22934586

[12,] 0.34929033 -0.18219971 0.3280327 -0.10277798 -0.18246496 -0.36741125

[13,] -0.14388496 0.39345085 0.2096365 0.01687809 0.25026704 0.16941501

[14,] 0.09256223 0.01110299 -0.2427821 0.15797987 -0.01790827 0.43493940

[15,] -0.06903743 0.05008329 -0.1678548 -0.61664654 0.15042502 -0.01810421

[16,] -0.44941264 -0.28731467 -0.1101533 0.22148537 -0.09373993 -0.06083004

[,13] [,14] [,15] [,16]

[1,] -0.09823652 0.003615597 -0.123775302 -0.01476090

[2,] -0.02594945 0.127287789 0.131143363 0.02640975

[3,] 0.17732376 -0.153604695 0.072604038 -0.08700180

[4,] 0.06167327 -0.154824801 -0.055536282 -0.15857918


[5,] 0.04403395 0.180479769 -0.076101659 0.69865134

[6,] 0.49541819 -0.058087171 -0.095425253 0.04216608

[7,] -0.09053836 -0.448953119 0.236824696 -0.30250096

[8,] -0.40507591 0.193829011 0.110147532 0.03688855

[9,] -0.14410014 -0.384272745 -0.035498328 0.16911313

[10,] 0.20117363 0.046661360 0.432459302 0.02357513

[11,] -0.21407102 0.312499654 -0.430773067 -0.49941529

[12,] 0.08740106 0.344122971 -0.347656169 0.08160911

[13,] 0.11177555 -0.436195835 -0.421146161 0.12469343

[14,] 0.38619656 0.323800848 0.349699254 -0.19607957

[15,] -0.50281826 0.010381767 0.285719681 0.16352546

[16,] -0.07482156 -0.001707348 -0.002965111 -0.13282232

>

# Observamos que tres variables tienen valores sobre el valor de 1 o muy cercano, con lo que
comprobamos que tres es el número adecuado de factores que debemos utilizar

# Gráfico de sedimentación

# Función que nos va permitir visualizar gráficamente la relación entre factores

install.packages("nFactors")

library(nFactors) # parallel() function que determina el número de factores a ser extraidos

ap = parallel(subject=nrow(datosEV), var=ncol(datosEV), rep=100, cent=0.05)

ns = nScree(x=ev$values, aparallel=ap$eigen$qevpea)

plotnScree(nS, xlab="Número de Componentes", ylab="Autovalores",

main="Solución por valores para determinar el

número de factores o componentes")

SALIDA:

> ap = parallel(subject=nrow(datosEV), var=ncol(datosEV), rep=100, cent=0.05)

> nS <- nScree(x=ev$values, aparallel=ap$eigen$qevpea)

> nS <- nScree(x=ev$values, aparallel=ap$eigen$qevpea)

> plotnScree(nS, xlab="Número de Componentes", ylab="Autovalores",


+ main="Solución por valores para determinar el número de factores o componentes")

>

# Regla de Kaiser: consiste en calcular los valores propios de la matriz de correlaciones R

# y tomar como número de factores propios superior a 1

eigen(matriz_correlacion)

SALIDA:

> eigen(matriz_correlacion)
eigen() decomposition
$values
[1] 8.3518500 1.0538790 0.9581659 0.7459430 0.6937302 0.5753718
[7] 0.5526124 0.5039080 0.4358902 0.4300266 0.3711596
0.3265545
[13] 0.2953303 0.2540524 0.2465903 0.2049358

$vectors
[,1] [,2] [,3] [,4] [,5]
[1,] -0.2476281 -0.26593987 0.212115955 -0.05786524 -0.293421417
[2,] -0.2176679 -0.46586457 0.236678094 -0.23271912 0.097184620
[3,] -0.2336865 -0.06779315 0.439916227 -0.19451968 -0.008706711
[4,] -0.2142866 -0.40556673 -0.027848915 0.35479675 -0.335062795
[5,] -0.2646218 0.26537733 0.377987230 0.09380610 -0.057189008
[6,] -0.2651253 -0.26046703 0.013930694 0.16237094 0.208359286
[7,] -0.2531897 0.35345333 0.150005621 0.05895741 -0.189953074
[8,] -0.2606710 0.11735303 -0.005215104 0.27705911 -0.018600417
[9,] -0.2349684 -0.21053120 -0.366416254 0.20146111 0.478945669
[10,] -0.2543602 0.24005116 -0.016458501 0.16915620 0.387620499
[11,] -0.2776952 0.17754291 0.206648264 0.21320508 0.273166033
[12,] -0.2538482 0.01057909 -0.411116912 -0.11216882 -0.096313332
[13,] -0.2594653 0.30580467 -0.180569108 -0.17195100 -0.209037875
[14,] -0.2665313 0.13480567 -0.328364643 -0.04065287 -0.305371305
[15,] -0.2685319 -0.14031727 -0.224933655 -0.13330245 -0.179696787
[16,] - 0.2155670 0.03517612 -0.042603924 -0.69795785 0.276097575
[,6] [,7] [,8] [,9] [,10]
[1,] 0.164125700 0.07146694 0.41933501 -0.3812013 0.27074934
[2,] -0.331376957 0.25316543 0.28756121 0.2685009 0.20020796
[3,] 0.434046889 0.25152188 -0.24330189 0.3426530 -0.29537778
[4,] -0.288907062 -0.51637177 -0.20062347 0.2420752 -0.01512547
[5,] -0.255371831 -0.08349309 -0.17717199 -0.1860636 0.01924259
[6,] 0.229300534 -0.06789386 -0.18761976 -0.3096143 -0.13533291
[7,] -0.384201300 0.30875323 -0.21640518 -0.1212809 0.08055468
[8,] 0.459253377 -0.07389551 -0.19900146 0.2934115 0.46462073
[9,] -0.001080736 0.27487096 -0.07671759 -0.1559394 0.17132638
[10,] -0.098160398 -0.23359862 0.44390570 0.2689296 -0.11767481
[11,] -0.071254908 -0.01980581 0.11348014 -0.1669012 -0.22309947
[12,] -0.222116767 0.34929033 -0.18219971 0.3280327 -0.10277798
[13,] 0.162926879 -0.14388496 0.39345085 0.2096365 0.01687809
[14,] 0.106040183 0.09256223 0.01110299 -0.2427821 0.15797987
[15,] 0.087049504 -0.06903743 0.05008329 -0.1678548 -0.61664654
[16,] -0.075187815 -0.44941264 -0.28731467 -0.1101533 0.22148537
[,11] [,12] [,13] [,14] [,15]
[1,] -0.41005590 -0.33714207 -0.09823652 0.003615597 -0.123775302
[2,] 0.42213213 0.18502260 -0.02594945 0.127287789 0.131143363
[3,] -0.30721399 0.17770935 0.17732376 -0.153604695 0.072604038
[4,] -0.17360859 0.12386105 0.06167327 -0.154824801 -0.055536282
[5,] -0.06325779 0.18336124 0.04403395 0.180479769 -0.076101659
[6,] 0.44871840 -0.35253734 0.49541819 -0.058087171 -0.095425253
[7,] 0.13568554 -0.24935510 -0.09053836 -0.448953119 0.236824696
[8,] 0.22582731 -0.13060648 -0.40507591 0.193829011 0.110147532
[9,] -0.26766105 0.30197218 -0.14410014 -0.384272745 -0.035498328
[10,] -0.23136607 -0.25953848 0.20117363 0.046661360 0.432459302
[11,] 0.03930188 0.22934586 -0.21407102 0.312499654 -0.430773067
[12,] -0.18246496 -0.36741125 0.08740106 0.344122971 -0.347656169
[13,] 0.25026704 0.16941501 0.11177555 -0.436195835 -0.421146161
[14,] -0.01790827 0.43493940 0.38619656 0.323800848 0.349699254
[15,] 0.15042502 -0.01810421 -0.50281826 0.010381767 0.285719681
[16,] -0.09373993 -0.06083004 -0.07482156 -0.001707348 -0.002965111
[,16]
[1,] -0.01476090
[2,] 0.02640975
[3,] -0.08700180
[4,] -0.15857918
[5,] 0.69865134
[6,] 0.04216608
[7,] -0.30250096
[8,] 0.03688855
[9,] 0.16911313
[10,] 0.02357513
[11,] -0.49941529
[12,] 0.08160911
[13,] 0.12469343
[14,] -0.19607957
[15,] 0.16352546
[16,] -0.13282232

>

# Cálculo de las puntuaciones factoriales

puntuaciones_fact = analFactRot$scores

puntuaciones_fact

SALIDA:

puntuaciones_fact = analFactRot$scores

> puntuaciones_fact

Factor1 Factor2 Factor3

[1,] -0.122114999 -0.723811956 1.023548e-01

[2,] 0.205637778 -0.313702797 2.966645e-01

[3,] 0.651364243 -0.099555443 -4.563137e-01

[4,] -1.561172221 -1.784539108 -3.249729e-01

[5,] 0.642848623 -0.588593580 1.511478e+00

[6,] -1.219653698 -1.177786616 -4.479079e-01

[7,] 0.838203123 -1.524855269 7.415732e-01

[8,] 0.422997264 -0.147752366 5.460313e-01

[9,] 0.133838046 1.428973015 -2.911205e+00

[10,] 0.540097920 -0.056402782 -8.352899e-01

[11,] 0.549260376 -0.822450536 -1.515795e+00

[12,] -0.396647950 0.482483022 8.854207e-02

[13,] 0.791596949 0.175273708 -6.490638e-01

[14,] 0.954747332 -0.007016809 -1.117746e-01

[15,] -0.558828394 -1.307383430 2.577335e-01

[16,] -0.530379321 -0.447534090 -2.219937e-01

[17,] 1.221469855 -0.256810376 -9.705819e-01

[18,] -0.671965298 -1.773435790 -7.945730e-01


[19,] 1.108209436 -0.408021788 -3.153673e-02

[20,] 1.998885133 -0.162362926 1.670224e+00

[21,] -0.134672653 -0.614499644 1.514913e+00

[22,] 0.776658131 -0.407947040 2.332857e-01

[23,] -0.029135788 -0.199062452 8.908082e-01

[24,] 0.639807728 0.434843025 -9.329025e-01

[25,] 0.528706380 -0.412655533 -1.125128e+00

[26,] -0.547482254 0.180425476 3.433762e-01

[27,] 0.224356422 -0.572292936 3.462626e-01

[28,] 2.336988431 -0.639531019 -3.570436e-01

[29,] 1.819889840 -0.184221949 -1.526935e+00

[30,] -2.383224791 -0.737542988 -5.955771e-02

[31,] -0.105876971 -1.654698250 5.240856e-01

[32,] 0.549475579 -0.603692157 -9.873877e-01

[33,] -0.238672602 3.649808689 -2.557974e+00

[34,] 0.007654105 -1.432719982 5.990309e-01

[35,] 3.675992852 -4.305355271 -9.837057e-01

[36,] 0.109243066 1.035589788 -3.248281e-01

[37,] 1.017326595 -0.408574749 -2.505422e+00

[38,] -0.244792135 -0.149858868 7.214717e-02

[39,] 0.195002599 -1.669923885 -9.534080e-01

[40,] 0.758260697 -1.344258651 1.172427e-01

[41,] 0.768723027 -0.406428641 -1.691677e+00

[42,] 0.534765931 0.754304405 1.033736e+00

[43,] 1.602126134 -1.709997552 -7.753206e-01

[44,] -0.644634500 -0.251472720 -2.584463e+00

[45,] 0.911374200 -1.308490717 2.949650e-01

[46,] 0.988766546 1.371451723 -8.481420e-01

[47,] 1.173179600 0.655261408 6.085051e-01

[48,] -1.240884394 1.798110515 -2.344042e+00

[49,] -2.119020164 -1.368750486 -2.259789e-01


[50,] 0.513003097 -0.250872372 2.039762e-01

[51,] 0.598945130 -0.244329668 3.548500e-01

[52,] -0.725422113 0.876458127 4.721501e-01

[53,] -2.267104858 -1.725005622 -1.677109e-01

[54,] 1.225014440 -2.493354832 -2.461939e+00

[55,] -0.189005368 -0.300303158 -4.041308e-01

[56,] 0.807241241 -0.629928602 -5.546841e-01

[57,] 0.236693115 -1.205418893 -3.200392e-01

[58,] 0.402394351 -0.063578878 1.046805e+00

[59,] -0.720853136 2.321398567 -6.195323e-01

[60,] 1.666818208 -0.702819165 9.829620e-01

[61,] 0.943967499 0.263745435 4.460043e-05

[62,] 2.142016258 -0.319585288 -3.272816e-01

[63,] -1.546378515 -0.235569242 -9.412046e-01

[64,] -0.017230664 -0.179602328 -2.369480e+00

[65,] -0.018936342 -0.210433356 5.180587e-01

[66,] 0.451275005 1.051502613 -8.605987e-01

[67,] 0.558485809 0.562760475 -1.584691e+00

[68,] -0.560250006 0.068728732 5.506939e-01

[69,] -1.183244454 0.090151279 -2.168756e-01

[70,] 1.264071014 0.394721067 -1.152927e-01

[71,] -0.731129141 0.310234339 5.645321e-01

[72,] 0.767681997 -0.454488982 9.612943e-02

[73,] -1.977042991 -0.167891094 -2.787468e-01

[74,] 1.842153425 1.217327274 1.280723e+00

[75,] 4.275920171 0.927620004 -4.353935e+00

[76,] -0.018936342 -0.210433356 5.180587e-01

[77,] -1.172500016 1.911378379 -5.128415e-01

[78,] 1.334200820 -0.701177764 1.792234e-01

[79,] -0.211446620 -0.690237167 6.001609e-01

[80,] -1.307301363 1.189116837 -2.303615e+00


[81,] 0.539921186 3.356757819 -4.951811e+00

[82,] 1.364937108 -0.027832212 7.378997e-01

[83,] 0.183978521 0.550990360 5.587645e-02

[84,] 1.301972955 0.690637465 -2.756734e-01

[85,] 1.167392946 0.584819025 7.571212e-01

[86,] 1.798237425 -0.860535759 1.115691e-01

[87,] 2.723373660 -1.082452034 -2.429923e-01

[88,] -1.989965935 3.085515585 -3.247397e+00

[89,] 0.167008365 -0.271467145 -8.691279e-02

[90,] -1.935426979 3.829707381 -3.370830e+00

[91,] 1.434338255 -1.355988373 -2.486099e-01

[92,] -0.750688595 -0.517947134 -3.939532e-02

[93,] -0.872591491 2.348759876 -1.124473e+00

[94,] -0.091903673 0.980341472 -1.089262e+00

[95,] 0.169210657 0.075015249 2.481696e-01

[96,] -1.265291822 1.938897891 1.357419e+00

[97,] -0.734177755 1.081009894 2.228567e-01

[98,] 1.298573510 0.950921144 -2.901769e-01

[99,] 0.714922424 1.086771102 -2.762355e+00

[100,] -0.882504691 -0.932456638 1.197376e-01

[101,] -0.004360504 0.462701786 -6.347701e-01

[102,] 0.513663657 0.599326409 1.511846e-01

[103,] 0.569103335 -0.495775195 -3.968341e-01

[104,] 1.320532990 -0.183366160 -1.574744e+00

[105,] 0.911608542 0.503446959 8.993910e-01

[106,] -0.389579580 -0.590701814 -9.630488e-02

[107,] 1.300839760 1.496489362 1.313359e+00

[108,] 0.442884504 0.583415290 5.113167e-01

[109,] -0.949481225 -0.924313671 1.367263e-01

[110,] -0.396617268 -0.513891027 -4.717207e-01

[111,] 0.541565395 -0.973567441 1.466746e-02


[112,] 1.837974640 1.011143706 7.172659e-01

[113,] -0.224240545 -1.367150658 4.629443e-02

[114,] 0.668388369 1.430859482 -2.133546e-01

[115,] 0.489117863 -0.459782690 -7.461357e-01

[116,] -0.552334131 1.663054339 3.255651e-01

[117,] -0.304821658 1.744428983 -1.458050e+00

[118,] 1.289385476 -0.826340014 -4.758254e-01

[119,] -0.189838368 -1.266455988 -3.216903e-02

[120,] -0.324737016 -2.068607972 -1.737658e-01

[121,] 0.988086912 0.516690454 -1.210213e+00

[122,] 0.307142543 -0.767326031 1.284871e+00

[123,] 0.367096070 1.187034882 6.074717e-02

[124,] -4.047540793 0.800925236 -1.281643e+00

[125,] -0.801006964 0.043341406 1.065308e+00

[126,] 0.844450208 0.577810238 1.113864e-01

[127,] -0.433219876 -0.165460864 7.012618e-01

[128,] 0.074726915 1.078083618 1.592212e+00

[129,] -0.831364759 -0.936151820 3.898284e-02

[130,] -1.058590531 -0.255772476 -9.202955e-02

[131,] -0.860946887 0.995569682 1.184713e+00

[132,] 1.842153425 1.217327274 1.280723e+00

[133,] 0.207535515 0.609893880 -3.390826e-01

[134,] 0.777722144 -0.614834150 9.903986e-02

[135,] -2.508586843 0.505537617 -1.626098e+00

[136,] 1.248547131 -0.410178508 -1.119625e+00

[137,] 1.070011246 -1.754940918 -1.482179e+00

[138,] 0.639113398 0.358972727 -1.447504e-01

[139,] 2.791158552 -3.426245907 -6.256455e-01

[140,] -0.733901205 2.153713998 -9.548418e-01

[141,] 0.217088942 0.977613189 -1.449699e+00

[142,] 0.470706467 -1.558944169 -3.218837e-01


[143,] -0.771509920 0.845162426 -1.524903e+00

[144,] 1.425867815 -1.051701307 7.870230e-01

[145,] -0.580801006 0.411966263 -4.173271e-01

[146,] -0.696657820 0.795342730 1.813379e-01

[147,] -0.453690820 0.126261516 -5.346815e-01

[148,] -0.384529708 -1.252887806 -6.860605e-02

[149,] 0.093396328 -0.529863378 -1.097612e+00

[150,] 1.360794689 -1.636751762 -7.868634e-01

[151,] 0.388625771 0.788395145 -7.701555e-01

[152,] -0.733146466 0.253782253 -1.011653e+00

[153,] 2.565013787 -2.097440356 -9.548374e-01

[154,] -0.613398942 2.612265102 -5.898813e-01

[155,] 0.707980283 -0.932965599 -1.215834e+00

[156,] -2.047528655 -0.953934908 -7.695469e-01

[157,] -1.886775098 -1.174391493 -4.118853e-01

[158,] 1.422852777 -0.441804736 -6.493733e-01

[159,] -1.229905219 0.517561956 -2.102900e-01

[160,] 0.599927500 1.154479254 -1.043415e-01

[161,] -0.136587719 -0.491584405 -2.367238e-01

[162,] 1.031216415 -0.082000709 -4.492664e-01

[163,] -0.491928327 -0.669706427 1.581333e+00

[164,] 0.354185677 0.075780143 1.229243e+00

[165,] 0.886551791 0.460042819 9.065469e-01

[166,] 0.625503226 1.116625425 7.072492e-01

[167,] -0.070479369 -0.819090068 3.437166e-01

[168,] -1.480971688 -0.519302929 7.220968e-01

[169,] 0.760579929 -0.295122532 3.419052e-01

[170,] -0.336244057 -0.513889222 -3.543867e-01

[171,] 0.524423465 -0.062605038 3.141796e-01

[172,] 0.851219675 -1.977460146 7.474607e-01

[173,] -0.018936342 -0.210433356 5.180587e-01


[174,] -1.185751446 -0.149253933 1.739940e-01

[175,] -0.829873722 -1.498716809 9.044858e-01

[176,] -1.411309924 -0.198416585 8.835009e-01

[177,] 0.079206938 -0.347423554 7.284818e-01

[178,] -1.665117949 0.381261056 7.634805e-01

[179,] -0.694797517 2.302409838 8.732095e-01

[180,] -0.903717272 1.863163539 1.347736e+00

[181,] 0.295798696 1.546719931 8.397228e-01

[182,] -0.018936342 -0.210433356 5.180587e-01

[183,] -1.087508057 -0.327032938 5.074726e-01

[184,] -1.223402408 1.804220807 2.251752e+00

[185,] -2.981602623 0.725074009 9.871180e-01

[186,] 0.042768695 0.791198036 2.140925e+00

[187,] -2.084099504 -3.401273188 1.118564e+00

[188,] -0.143174198 -1.009016166 4.576376e-01

[189,] -3.778742177 1.811308367 1.160292e+00

[190,] -0.006293464 -0.325742535 5.736114e-01

[191,] -2.167892380 -1.783528139 -4.900653e-01

[192,] -0.861169217 0.143220048 7.371136e-01

[193,] -0.018936342 -0.210433356 5.180587e-01

[194,] -0.215448004 1.148142848 1.364927e+00

[195,] -0.558453665 0.691783031 1.602506e+00

[196,] -0.425091576 -1.644994605 1.142834e+00

[197,] -2.024004348 -0.114812905 5.483350e-03

[198,] -0.178853400 -0.575900053 1.274611e+00

[199,] -2.423086066 -0.056614465 8.993492e-01

[200,] -0.860755992 -0.204246367 5.236572e-01

[201,] -0.093081398 -2.526991952 1.509140e-01

[202,] 1.703497173 -0.044220301 1.056176e+00

[203,] -0.917778679 -1.723617617 9.783391e-01

[204,] -0.429940207 1.142484088 1.803430e+00


[205,] 1.140031873 1.447927132 1.497049e+00

[206,] -2.385234609 -0.908812673 1.735434e-02

[207,] 1.514384196 0.814103664 1.376357e+00

[208,] -0.215950099 0.010154640 1.466277e+00

[209,] 0.424662439 0.288445650 1.160463e+00

[210,] 0.580079866 -0.086619995 1.946208e+00

[211,] 0.251603113 0.587772748 1.682508e+00

[212,] -0.380906031 0.353462953 1.495519e+00

[213,] -0.457595155 0.934569478 4.019225e-01

[214,] 0.491748085 0.775045402 1.114624e+00

[215,] -0.506218874 -0.273060694 1.488512e+00

[216,] -0.507939932 0.656987052 1.515181e+00

[217,] 1.477101105 0.699836792 5.628771e-01

[218,] -0.097921042 -0.823321713 9.784709e-01

[219,] 0.341494479 -0.145327531 1.326880e+00

[220,] -1.386309076 0.552772816 2.864723e-01

[221,] -0.639762206 0.713509969 9.489457e-01

[222,] -1.160234247 -0.951959053 4.513030e-01

[223,] -3.206329003 0.985868607 1.977288e+00

[224,] -3.008810548 1.739728647 1.006669e+00

[225,] 0.514796567 1.940190131 6.930906e-01

[226,] -1.152339873 2.393995352 1.378456e+00

>
ANÁLISIS FACTORIAL CONFIRMATORIO DE LA VARIABLE ENSEÑANZA VIRTUAL EN RSTUDIO

library(readxl)

install.packages("semPlot")

library(semPlot)

library(lavaan)

# Leemos(cargamos) los datos de un fichero en excel

datosEV=read_excel("C:\\ejemplos\\EncuestaSVJ.xlsx",sheet="EV")

View(datosEV)

SALIDA:

# Especificar el modelo, cada línea es un factor latente

# con sus indicadores siguiendo el =~ (lea este símbolo "se mide por")
Modelo_confir = ' Factor1 =~ E3 + E5 + E7 + E8 + E10 + E11

Factor2 =~ E9 + E12 + E13 + E14 + E15 + E16

Factor3 =~ E1 + E2 + E4 + E6'

Modelo_confir

SALIDA:

> Modelo_confir = ' Factor1 =~ E3 + E5 + E7 + E8 + E10 + E11

+ Factor2 =~ E9 + E12 + E13 + E14 + E15 + E16

+ Factor3 =~ E1 + E2 + E4 + E6'

> Modelo_confir

[1] " Factor1 =~ E3 + E5 + E7 + E8 + E10 + E11\n Factor2 =~ E9 + E12 + E13 + E14 + E15 + E16\n
Factor3 =~ E1 + E2 + E4 + E6"

# Corremos el modelo

modelo = cfa(Modelo_confir, data = datosEV)

sumary(modelo, fit.measures = TRUE)

SALIDA:

> modelo = cfa(Modelo_confir, data = datosEV)

> summary(modelo, fit.measures = TRUE)

lavaan 0.6-7 ended normally after 40 iterations

Estimator ML

Optimization method NLMINB

Number of free parameters 35

Number of observations 226

Model Test User Model:

Test statistic 244.042

Degrees of freedom 101

P-value (Chi-square) 0.000


Model Test Baseline Model:

Test statistic 2196.102

Degrees of freedom 120

P-value 0.000

User Model versus Baseline Model:

Comparative Fit Index (CFI) 0.931

Tucker-Lewis Index (TLI) 0.918

Loglikelihood and Information Criteria:

Loglikelihood user model (H0) -4771.874

Loglikelihood unrestricted model (H1) -4649.853

Akaike (AIC) 9613.748

Bayesian (BIC) 9733.466

Sample-size adjusted Bayesian (BIC) 9622.543

Root Mean Square Error of Approximation:

RMSEA 0.079

90 Percent confidence interval - lower 0.067

90 Percent confidence interval - upper 0.092

P-value RMSEA <= 0.05 0.000

Standardized Root Mean Square Residual:

SRMR 0.048
Parameter Estimates:

Standard errors Standard

Information Expected

Information saturated (h1) model Structured

Latent Variables:

Estimate Std.Err z-value P(>|z|)

Factor1 =~

E3 1.000

E5 1.271 0.120 10.607 0.000

E7 1.187 0.119 9.953 0.000

E8 0.907 0.094 9.678 0.000

E10 1.022 0.105 9.747 0.000

E11 1.257 0.116 10.872 0.000

Factor2 =~

E9 1.000

E12 1.235 0.122 10.082 0.000

E13 1.259 0.125 10.047 0.000

E14 1.334 0.126 10.558 0.000

E15 1.119 0.107 10.423 0.000

E16 1.025 0.125 8.217 0.000

Factor3 =~

E1 1.000

E2 0.951 0.100 9.514 0.000

E4 0.818 0.088 9.306 0.000

E6 0.988 0.087 11.357 0.000

Covariances:

Estimate Std.Err z-value P(>|z|)


Factor1 ~~

Factor2 0.523 0.080 6.513 0.000

Factor3 0.628 0.093 6.743 0.000

Factor2 ~~

Factor3 0.549 0.081 6.812 0.000

Variances:

Estimate Std.Err z-value P(>|z|)

.E3 0.941 0.095 9.912 0.000

.E5 0.571 0.066 8.699 0.000

.E7 0.755 0.081 9.362 0.000

.E8 0.513 0.054 9.541 0.000

.E10 0.627 0.066 9.500 0.000

.E11 0.456 0.055 8.256 0.000

.E9 0.665 0.068 9.805 0.000

.E12 0.581 0.063 9.179 0.000

.E13 0.616 0.067 9.208 0.000

.E14 0.508 0.058 8.683 0.000

.E15 0.390 0.044 8.848 0.000

.E16 0.969 0.097 10.037 0.000

.E1 0.632 0.073 8.685 0.000

.E2 0.906 0.096 9.424 0.000

.E4 0.722 0.076 9.514 0.000

.E6 0.464 0.058 8.004 0.000

Factor1 0.716 0.133 5.392 0.000

Factor2 0.528 0.097 5.453 0.000

Factor3 0.782 0.126 6.199 0.000

semPaths(modelo, what = "paths", layout = "circle", title = TRUE, style = "LISREL")

SALIDA:
semPaths(modelo, what = "est", layout = "circle", title = TRUE, style = "LISREL")

SALIDA:
Una guía amigable para el uso de
Lavaan: Potencia de R para el
Análisis Factorial Confirmatorio
(SEM)
Brian N. Peña Calero (1,2,*)

2018-11-22

Carátula
1. Sociedad Peruana de Psicometría (SPP)
2. Avances en Medición Psicológica (AMP)

* Correspondencia al Autor. Dirección de E-mail: brianmsm@gmail.com

Presentación
Esta breve guía presenta dos ejes principales: a) Los fundamentos y usos del
Análisis Factorial Confirmatorio (CFA) de acuerdo a los estándares actuales y
b) El uso del paquete R lavaan (Rosseel, 2018) para su ejecución en el
análisis psicométrico (construcción de pruebas, adaptación, validación y/o
estudio de propiedades). A pesar de que existen actualmente una cantidad
considerable de software (mayormente privativos) que permiten el desarrollo
de un AFC, pocos de ellos tienen implementados los procedimientos
necesarios a desarrollar (consideración de variables ordinales por ej.).

Esta guía-manual permitirá entender lo principal acerca del desarrollo de un


AFC tanto para las personas que se encuentren interesadas en
implementarlos con el paquete lavaan de R (R Core Team, 2018), como
aquellas que deseen hacerlo mediante otro software de análisis. Se parte
desde la simplicidad de los modelos factoriales hasta aspectos más
específicos y particulares. El objetivo es generar un aprendizaje guiado, de
fácil implementación (cuando el objetivo sea así) y de robusta
implementación (cuando así se requiera).

La guía se encuentra escrita en R mediante el paquete


Bookdown (Xie, 2018) que implementa el estilo GitBook
(https://www.gitbook.com) para la presentación de libros y/o documentos
(manuales) en formato HTML (tipo página web) y la posibilidad de exportarlo
a otros formatos como pdf y epub. Además, se encuentra alojado
en Gitlab y Github a fin de poder recibir aporte de todas las personas que se
encuentren interesadas en corregir, sugerir cambios y/o adicionar
información que se considere de importancia.

El presente manual y los insumos utilizados para su creación siguen los


lineamientos del software libre, código abierto, ciencia abierta  y acceso
abierto. Por consiguiente todos los materiales utilizados para su creación se
encuentran disponibles para todos los usuarios interesados.

La versión en línea del presente manual se encuentra bajo la


licencia Creative Commons Reconocimiento-CompartirIgual 4.0 Internacional .

1 Introducción
Este manual es una guía para el entendimiento de los fundamentos del
Análisis Factorial Confirmatorio (AFC) y su desarrollo mediante el software R
y el paquete lavaan mayormente. Para fines de presentación de resultados y
análisis adicionales se hará uso de otros paquetes de R
como psych (Revelle, 2018) para análisis descriptivo de los
ítems; MVN (Korkmaz, Goksuluk, & Zararsiz, 2018) para el análisis de
normalidad multivariada; semTools (Jorgensen, Pornprasertmanit,
Schoemann, & Rosseel, 2018) para el cálculo de fiabilidad a partir del modelo
evaluado; y semPlot (Epskamp & Simon Stuber, 2017) para la generación de
gráficos a partir del modelo evaluado.

No es el objetivo del presente manual ser un libro de consulta o brindar


información técnica específica y especializada sobre los fundamentos de los
análisis, por el contrario se busca brindar la información actualizada y
pertinente de forma entendible y directa, sin descuidar en el proceso los
fundamentos esenciales.

Esta guía tiene en pendiente abordar los principales usos de AFC desde los
procesos más básicos hasta los más completos para fines de investigación
instrumental. Aún está en proceso de desarrollo por lo que se anuncia la
planificación existente: - Fundamentos básicos del AFC: Diferencias con
AFE. - Revisión de los estimadores clásicos y robustos - AFC de primer
orden - AFC de segundo orden - Modelos Bifactor - Modelos
multidimensionales - Invarianza - Invarianza longitudinal - Procedimientos de
AFC en muestras complejas

1.1 Fundamentos de Análisis Factorial


Confirmatorio
El análisis factorial confirmatorio (CFA) es considerado como una forma
de modelo de ecuaciones estructurales (SEM) que tiene como propósito el
analizar los modelos de medición, es decir, la estructura y conformación de
ítems, indicadores y/o estimulos a una variable latente (constructo)
previamente hipotetizada (Brown, 2015).

La hipotetización acerca del modelo estructural es indispensable en el AFC y


debe estar considerada de forma sólida, al menos lo suficiente para poder
explicar un buen o mal ajuste, y/o modificaciones que se realicen sobre el
modelo de medición. Cuando no existe una estructura hipótetica o la
estructura del modelo de medición (instrumento o test) se encuentra
cuestionada, se prefiere un análisis factorial exploratorio (AFE) en el que se
encuentre de forma exploratoria las relaciones de los ítems y/o indicadores a
la variable latente (Beaujean, 2014).

De esta forma el AFC permite confirmar la estructura factorial de un


instrumento propuesto siempre y cuando el proceso de construcción del
mismo tenga los requerimientos mínimos necesarios para hipotetizar sobre el
mismo.

No se pretende hacer una descripción matemática acerca de los


procedimientos que subyacen el AFC, por lo que se brinda una idea y/o
noción general que permita entenderlo, cuestionar y/o discutir sobre ello.
El AFC al ser una forma
1.2 Procedimientos para realizar un AFC
Para realizar un AFC en un instrumento de medición se debe tener en cuenta
los siguientes procedimientos:

1. Especificación: Estructura factorial de la prueba.


2. Identificación: Información suficiente (gl).
3. Estimación: Matriz teórica vs matriz empírica
4. Evaluación: ¿La estimación es correcta?
5. Reespecificación: Modificación a la estructura factorial para mejorar el ajuste
al modelo.

1.3 Algunas sugerencias y materiales de


lectura
En preparación.

1.4 Preparándonos
Para realizar análisis específicos como lo es el AFC o SEM, R requiere de
paquetes especializados para su propósito (que traen consigo, funciones
especializadas). Existen diversos paquetes para realizar un AFC, entre los
más comunes está OpenMX, CFA, sem y lavaan.

En nuestro caso usaremos el último en mención por ser uno de los más
consolidados en la actualidad, ofrecer mayor facilidad de manejo y tener en
su desarrollo los últimos avances en AFC provenientes en gran parte de
Mplus y aportes propios.

En primer lugar requerimos tener instalado R (R Core Team, 2018) en


nuestra computadora y/o laptop, además de la IDE Rstudio que nos facilitará
el proceso de escritura en código. Sobre ello instalaremos algunas
paqueterías además de lavann que complementarán nuestro análisis.

1. Descargar el software R desde R-project . Elegir el método de descarga de


acuerdo al sistema operativo de su computadora y/o laptop. En el caso más
probable de sistema operativo Windows seguir las instrucciones de aquí; en el caso
de SO MacOs, aquí; mientras que en caso de usar alguna distribución GNU/Linux,
puede seguir las instrucciones de aquí.
2. Instalar la IDE RStudio que nos permitirá tener una espacio de escritura más
robusta. Para ello puedes descargar la última versión disponible  (a la fecha
1.1.463).
3. Instalar el paquete lavaan y los complementarios listados a
continuación:
4. # Instalando lavaan
5. install.packages("lavaan", dependencies = TRUE)
6. # Instalar los paquetes complementarios
7. install.packages(c("tidyverse", "semTools", "semPlot",
"psych", "MVN"), dependencies = TRUE)
8. Ya nos encontramos listos para poder utilizar Rstudio con los paquetes
configurados.

2 Primeros pasos en el Análisis


Empezaremos con un primer análisis utulizando una base de datos de
acceso libre y de las más difundidas para el AFC. Se trata de la BD
de Holzinger & Swineford (1939) que recolecta información de una prueba de
Habilidades Cognitivas conformado por 26 test en séptimo y octavo grado de
dos colegios diferentes (Pasteur y Grant-White). Para este procedimiento se
utilizará los datos recortados a 9 pruebas que se estructuran en 3 factores
latentes: Visual, Textual y Velocidad.

Table 2.1: Estructura de la prueba de Holzinger & Swineford (1939).

Factores Indicadores

Factor Visual X1, X2 y X3

Factor Textual X4, X5 y X6

Factor Velocidad X7, X8 y X9

Es importante conocer la estructura propuesta del instrumento a analizar


(Table 2.1) debido a que el ajuste de los modelos calculados requieren tener
un marco explicativo y referencial.

2.1 Importar datos y reconocer variables


Empezaremos con algunas funciones sencillas que nos ayuden a entender la
forma de trabajo de R previo al flujo de análisis de AFC propiamente. En
caso de no haber cargado aún el paquete, o solo necesitar una función única
del mismo, podrías solicitarlo mediante la indicación:
package::function(...)
Lo indicado arriba estará solicitando una función function del
paquete package de forma específica. ¡Probemos!
# Solicitamos ver la BD
head(lavaan::HolzingerSwineford1939)
## id sex ageyr agemo school grade x1 x2 x3 x4 x5
## 1 1 1 13 1 Pasteur 7 3.333333 7.75 0.375 2.333333 5.75
## 2 2 2 13 7 Pasteur 7 5.333333 5.25 2.125 1.666667 3.00
## 3 3 2 13 1 Pasteur 7 4.500000 5.25 1.875 1.000000 1.75
## 4 4 1 13 2 Pasteur 7 5.333333 7.75 3.000 2.666667 4.50
## 5 5 2 12 2 Pasteur 7 4.833333 4.75 0.875 2.666667 4.00
## 6 6 2 14 1 Pasteur 7 5.333333 5.00 2.250 1.000000 3.00
## x6 x7 x8 x9
## 1 1.2857143 3.391304 5.75 6.361111
## 2 1.2857143 3.782609 6.25 7.916667
## 3 0.4285714 3.260870 3.90 4.416667
## 4 2.4285714 3.000000 5.30 4.861111
## 5 2.5714286 3.695652 6.30 5.916667
## 6 0.8571429 4.347826 6.65 7.500000
# ¡Quiero orden!
tibble::as_tibble(lavaan::HolzingerSwineford1939)
## # A tibble: 301 x 15
## id sex ageyr agemo scho… grade x1 x2 x3 x4 x5
x6
## <int> <int> <int> <int> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
<dbl>
## 1 1 1 13 1 Past… 7 3.33 7.75 0.375 2.33 5.75
1.29
## 2 2 2 13 7 Past… 7 5.33 5.25 2.12 1.67 3
1.29
## 3 3 2 13 1 Past… 7 4.5 5.25 1.88 1 1.75
0.429
## 4 4 1 13 2 Past… 7 5.33 7.75 3 2.67 4.5
2.43
## 5 5 2 12 2 Past… 7 4.83 4.75 0.875 2.67 4
2.57
## 6 6 2 14 1 Past… 7 5.33 5 2.25 1 3
0.857
## 7 7 1 12 1 Past… 7 2.83 6 1 3.33 6
2.86
## 8 8 2 12 2 Past… 7 5.67 6.25 1.88 3.67 4.25
1.29
## 9 9 2 13 0 Past… 7 4.5 5.75 1.5 2.67 5.75
2.71
## 10 11 2 12 5 Past… 7 3.5 5.25 0.75 2.67 5
2.57
## # ... with 291 more rows, and 3 more variables: x7 <dbl>, x8 <dbl>,
## # x9 <dbl>
Hemos realizado dos formas de poder visualizar los datos. Definitivamente la
segunda manera nos permite visualizar los datos de forma ordenada. Antes
de ir al análisis, necesitamos que R guarde estos datos en un objeto, es
decir un nombre que permita identificarlo (lo veremos en
el ambiente [Environment]). Para ello necesitamos utilizar la designación “<-”
(alt + -) como lo veremos abajo.
# Guardaremos la BD
datos <- tibble::as_tibble( # Guardemos la BD en "data"
lavaan::HolzingerSwineford1939 # Esta es la BD
)
View(datos)
¡Muy bien! Lo hemos logrado. Si vemos al recuadro superior derecho,
podemos ver que en el entorno “ambiente” ahora aparece “data” indicando
que posee 301 observaciones y 15 variables. Podemos tener más
información si lo que queremos es focalizarnos en las variables. Podemos
usar la función names para tener un listado de las variables de un data.frame
(BD) y la función glimpse del paquete dplyr para ver las propiedades de las
variables (además del listado del mismo).
names(datos) # Listado de variables
## [1] "id" "sex" "ageyr" "agemo" "school" "grade" "x1"
## [8] "x2" "x3" "x4" "x5" "x6" "x7" "x8"
## [15] "x9"
dplyr::glimpse(datos) # Listado y propiedades de variables
## Observations: 301
## Variables: 15
## $ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16,
17, ...
## $ sex <int> 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 1,
2...
## $ ageyr <int> 13, 13, 13, 13, 12, 14, 12, 12, 13, 12, 12, 12, 12,
12,...
## $ agemo <int> 1, 7, 1, 2, 2, 1, 1, 2, 0, 5, 2, 11, 7, 8, 6, 1, 11,
5,...
## $ school <fct> Pasteur, Pasteur, Pasteur, Pasteur, Pasteur, Pasteur,
P...
## $ grade <int> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7...
## $ x1 <dbl> 3.333333, 5.333333, 4.500000, 5.333333, 4.833333,
5.333...
## $ x2 <dbl> 7.75, 5.25, 5.25, 7.75, 4.75, 5.00, 6.00, 6.25, 5.75,
5...
## $ x3 <dbl> 0.375, 2.125, 1.875, 3.000, 0.875, 2.250, 1.000,
1.875,...
## $ x4 <dbl> 2.333333, 1.666667, 1.000000, 2.666667, 2.666667,
1.000...
## $ x5 <dbl> 5.75, 3.00, 1.75, 4.50, 4.00, 3.00, 6.00, 4.25, 5.75,
5...
## $ x6 <dbl> 1.2857143, 1.2857143, 0.4285714, 2.4285714,
2.5714286, ...
## $ x7 <dbl> 3.391304, 3.782609, 3.260870, 3.000000, 3.695652,
4.347...
## $ x8 <dbl> 5.75, 6.25, 3.90, 5.30, 6.30, 6.65, 6.20, 5.15, 4.65,
4...
## $ x9 <dbl> 6.361111, 7.916667, 4.416667, 4.861111, 5.916667,
7.500...
¡Perfecto! Hemos cargado una base de datos y reconocido el contenido de
los datos que vamos a utilizar. ¡Estamos listos para empezar con la
acción!

2.2 Sintaxis de Lavaan (Especificación)


Lo primero que haremos es especificar el modelo (estructura factorial) de la
prueba tal y como se encuentra indicado en la Tabla 2.1. ¿Cómo
especificamos? ¡Simple! Solo debemos indicarle a R qué variables forman
los factores (variables latentes) y la relación que hay entre los mismos. Para
indicar las relaciones existentes se tiene las siguientes indicaciones de la
Tabla 2.2:

Table 2.2: Sintaxis para la Especificación en Lavaan.

Sintaxis Descripción

=~ Conformación de una variable latente

~ Regresión
Table 2.2: Sintaxis para la Especificación en Lavaan.

Sintaxis Descripción

~~ Co-varianza entre errores o varianza del indicador

~1 Interceptos

Para la especificación de un AFC nos interesa indicarle a R las variables


latentes y su conformación (=~) y la co-varianza entre los errores (~~)
principalmente (o al menos por el nivel básico explorado). ¡Vamos a ello!
# Se crea un objeto "model" donde se almacena la información
# acerca de la especificación del instrumento
model <- " visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 "
¡Así de simple! Se está creando un objeto llamado model que usaremos para
solicitarle a R que identifique el modelo y realice la estimación del mismo.
Esta especificación precisa que existen tres
factores visual, textual y speed que se encuentran conformados por 3
indicadores cada uno.

2.3 Identificación, Estimación y
Evaluación
¡Ahora vamos a identificar y estimar! ¡Si! Los dos pasos al mismo tiempo
utilizando la función cfa del paquete lavaan.
# Cargamos el paquete
library(lavaan)
## This is lavaan 0.6-3
## lavaan is BETA software! Please report any bugs.
# Almacenamos en el objeto "fit" la información de la estimación
fit <- cfa(model = model,
data = datos)
¡Ya está! Veamos el entorno ambiente. Hemos creado un objeto adicional de
clase lavaan llamado fit. La función cfa es un wrapper de la función
general lavaan, es decir que automatiza una gran cantidad de
especificaciones como las varianzas individuales de las variables,
correlaciones de errores establecidas a 0, y el hecho de tratar a los factores
especificados como oblicuos, es decir que se encuentra correlacionados
entre ellos. Dicho esta aclaración sobre lo que acabamos de hacer,
procederemos a verificar la evaluación de nuestro modelo factorial
almacenado en fit. Para esto usaremos a la conocida función summary que
nos devolverá de forma organizada parte de lo estimado. ¡Hagámoslo!
summary(datos) ## ¡Ups! Nos confundimos, parece ser que hace eso mismo:
¡Resumir!
## id sex ageyr agemo
## Min. : 1.0 Min. :1.000 Min. :11 Min. : 0.000
## 1st Qu.: 82.0 1st Qu.:1.000 1st Qu.:12 1st Qu.: 2.000
## Median :163.0 Median :2.000 Median :13 Median : 5.000
## Mean :176.6 Mean :1.515 Mean :13 Mean : 5.375
## 3rd Qu.:272.0 3rd Qu.:2.000 3rd Qu.:14 3rd Qu.: 8.000
## Max. :351.0 Max. :2.000 Max. :16 Max. :11.000
##
## school grade x1 x2
## Grant-White:145 Min. :7.000 Min. :0.6667 Min. :2.250
## Pasteur :156 1st Qu.:7.000 1st Qu.:4.1667 1st Qu.:5.250
## Median :7.000 Median :5.0000 Median :6.000
## Mean :7.477 Mean :4.9358 Mean :6.088
## 3rd Qu.:8.000 3rd Qu.:5.6667 3rd Qu.:6.750
## Max. :8.000 Max. :8.5000 Max. :9.250
## NA's :1
## x3 x4 x5 x6
## Min. :0.250 Min. :0.000 Min. :1.000 Min. :0.1429
## 1st Qu.:1.375 1st Qu.:2.333 1st Qu.:3.500 1st Qu.:1.4286
## Median :2.125 Median :3.000 Median :4.500 Median :2.0000
## Mean :2.250 Mean :3.061 Mean :4.341 Mean :2.1856
## 3rd Qu.:3.125 3rd Qu.:3.667 3rd Qu.:5.250 3rd Qu.:2.7143
## Max. :4.500 Max. :6.333 Max. :7.000 Max. :6.1429
##
## x7 x8 x9
## Min. :1.304 Min. : 3.050 Min. :2.778
## 1st Qu.:3.478 1st Qu.: 4.850 1st Qu.:4.750
## Median :4.087 Median : 5.500 Median :5.417
## Mean :4.186 Mean : 5.527 Mean :5.374
## 3rd Qu.:4.913 3rd Qu.: 6.100 3rd Qu.:6.083
## Max. :7.435 Max. :10.000 Max. :9.250
##
## Muestrame acerca de lo estimado entonces
summary(fit)
## lavaan 0.6-3 ended normally after 35 iterations
##
## Optimization method NLMINB
## Number of free parameters 21
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 85.306
## Degrees of freedom 24
## P-value (Chi-square) 0.000
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|)
## visual =~
## x1 1.000
## x2 0.554 0.100 5.554 0.000
## x3 0.729 0.109 6.685 0.000
## textual =~
## x4 1.000
## x5 1.113 0.065 17.014 0.000
## x6 0.926 0.055 16.703 0.000
## speed =~
## x7 1.000
## x8 1.180 0.165 7.152 0.000
## x9 1.082 0.151 7.155 0.000
##
## Covariances:
## Estimate Std.Err z-value P(>|z|)
## visual ~~
## textual 0.408 0.074 5.552 0.000
## speed 0.262 0.056 4.660 0.000
## textual ~~
## speed 0.173 0.049 3.518 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .x1 0.549 0.114 4.833 0.000
## .x2 1.134 0.102 11.146 0.000
## .x3 0.844 0.091 9.317 0.000
## .x4 0.371 0.048 7.779 0.000
## .x5 0.446 0.058 7.642 0.000
## .x6 0.356 0.043 8.277 0.000
## .x7 0.799 0.081 9.823 0.000
## .x8 0.488 0.074 6.573 0.000
## .x9 0.566 0.071 8.003 0.000
## visual 0.809 0.145 5.564 0.000
## textual 0.979 0.112 8.737 0.000
## speed 0.384 0.086 4.451 0.000
¡Que elegancia! No nos asustemos. Vamos a entenderlo paso a paso, de las
manitos. No nos soltemos. Respiremos y empecemos por la primera parte.
Vemos que el “output” (resultados en consola) nos indica la versión de
“lavaan”, el número de parámetros libres que tenemos en el modelo, número
de casos analizados, método de estimación utilizado (máxima verosimilitud),
valor de chi cuadrado (Model Fit Test Statistic), grados de libertad (sobre
identificado), valor p de la prueba de bondad de ajuste (chi cuadrado) e
información adicional que por ahora no será de nuestra preocupación.

En el apartado de “Latent Variables” (Variables Latentes) podemos ver la


estimación sin estandarizar de los indicadores frente a la variable latente,
erores estándares de la estimación, valor Z y valor p del mismo. Con
respecto al apartado “Covariances”, sigue la misma estructura que arriba
centrándose en las relaciones entre factores (variables latentes).
Recordemos que al usar la función “cfa” por defecto se configura en “oblicuo”
(factores correlacionados). Por último, en el apartado de las varianzas lo
único de lo que nos preocuparemos por ahora es el no encontrar valores
estimados (no se encuentran estadarizados) que sean positivos. En caso de
encontrar uno negativo, estaremos frente a un caso Heywood!

Es probable que esta explicación, a pesar de mantenerse de forma simple, te


haya parecido algo compleja. Es normal sentirlo de esa forma si recién estás
teniendo contacto con este tipo de análisis. Te alegrará saber que, aunque
hay mucha información para ver y revisar, a lo que debemos prestar atención
es a los índices de ajuste del modelo y a las estimaciones estandarizadas.
Será lo principal. ¡Espera! ¿Y donde se encuentra todo eso?

Calma, toda esta información se encuentra almacenada en el objeto “fit”, solo


que al momento de solicitar el “output” con la función “summary”, no hemos
sido más precisos en lo que queremos que nos muestre. Para las dos
menciones que deseamos poder ver y revisar usaremos dos argumentos
adicionales. Si deseamos que se adicione la información sobre índices de
ajuste, la función quedará así:
summary(..., fit.measures = TRUE)
Si deseamos que se adicione información estandarizada, la función quedará
así:
summary(..., standardized = TRUE)
Así, en caso de querer ambas cosas, solo hará falta poner esos dos
argumentos en la misma solicitud:
summary(..., fit.measures = TRUE, standardized = TRUE)
¡Probemos!
# Solicitar el resumen del análisis adicionando las medidas estandarizadas
# y los índices de ajuste
summary(fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-3 ended normally after 35 iterations
##
## Optimization method NLMINB
## Number of free parameters 21
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 85.306
## Degrees of freedom 24
## P-value (Chi-square) 0.000
##
## Model test baseline model:
##
## Minimum Function Test Statistic 918.852
## Degrees of freedom 36
## P-value 0.000
##
## User model versus baseline model:
##
## Comparative Fit Index (CFI) 0.931
## Tucker-Lewis Index (TLI) 0.896
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -3737.745
## Loglikelihood unrestricted model (H1) -3695.092
##
## Number of free parameters 21
## Akaike (AIC) 7517.490
## Bayesian (BIC) 7595.339
## Sample-size adjusted Bayesian (BIC) 7528.739
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.092
## 90 Percent Confidence Interval 0.071 0.114
## P-value RMSEA <= 0.05 0.001
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.065
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual =~
## x1 1.000 0.900 0.772
## x2 0.554 0.100 5.554 0.000 0.498 0.424
## x3 0.729 0.109 6.685 0.000 0.656 0.581
## textual =~
## x4 1.000 0.990 0.852
## x5 1.113 0.065 17.014 0.000 1.102 0.855
## x6 0.926 0.055 16.703 0.000 0.917 0.838
## speed =~
## x7 1.000 0.619 0.570
## x8 1.180 0.165 7.152 0.000 0.731 0.723
## x9 1.082 0.151 7.155 0.000 0.670 0.665
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual ~~
## textual 0.408 0.074 5.552 0.000 0.459 0.459
## speed 0.262 0.056 4.660 0.000 0.471 0.471
## textual ~~
## speed 0.173 0.049 3.518 0.000 0.283 0.283
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x1 0.549 0.114 4.833 0.000 0.549 0.404
## .x2 1.134 0.102 11.146 0.000 1.134 0.821
## .x3 0.844 0.091 9.317 0.000 0.844 0.662
## .x4 0.371 0.048 7.779 0.000 0.371 0.275
## .x5 0.446 0.058 7.642 0.000 0.446 0.269
## .x6 0.356 0.043 8.277 0.000 0.356 0.298
## .x7 0.799 0.081 9.823 0.000 0.799 0.676
## .x8 0.488 0.074 6.573 0.000 0.488 0.477
## .x9 0.566 0.071 8.003 0.000 0.566 0.558
## visual 0.809 0.145 5.564 0.000 1.000 1.000
## textual 0.979 0.112 8.737 0.000 1.000 1.000
## speed 0.384 0.086 4.451 0.000 1.000 1.000
Está bien, no hay problema. Solo se agregaron unas líneas más al “output”.
¡Podemos manejarlo! En la primera parte del “output” se adicionó cuatro de
los índices de ajuste más comunes: CFI (>= .95), TLI (>= .95), RMSEA (<= .
05) y SRMR (<= .06).
Estos índices de ajuste nos permitirán decidir si, el modelo tal y como se
encuentra especificado guarda coherencia estadística. En la parte de abajo
(Latent Variables, Covariances y Variances) se ha agregado dos
columnas Std.lv y Std.all. Nosotros nos concentraremos en “Std.all” debido a
que representa la estimación estandarizada a todo el modelo (varía entre -1 y
1). Mientras más alto mejor.

Antes de pasar a ver como podemos mejorar nuestro modelo ya que


presenta valores en sus ajustes que no llegan a ser del todo satisfactorios,
veremos otra forma de visualizar los resultados que puede ser un tanto más
amigable.

2.4 Re-Especificación
Vemaos como mejorar nuestro modelo ya que presenta valores en sus
ajustes que no llegan a ser del todo satisfactorios. En este punto, la reflexión
teórica debería darnos algunas pistas sobre el mal funcionamiento de
algunos ítems, pertenencia a otro factor o presencia de correlación de errores
por un mismo comienzo en el enunciado.

Los índices de modificación son valores que nos brindarán


una orientación acerca de la re-especificación de la estructura factorial
evaluada inicialmente. Para ello usaremos la siguiente función:
`modificationindices(fit)`
Veremos también cómo ver solo una parte de los IM (los más
representativos)
# Solicitar los 10 primeros IM con valores más altos
modindices(fit, sort = TRUE, maximum.number = 10)
## lhs op rhs mi epc sepc.lv sepc.all sepc.nox
## 30 visual =~ x9 36.411 0.577 0.519 0.515 0.515
## 76 x7 ~~ x8 34.145 0.536 0.536 0.859 0.859
## 28 visual =~ x7 18.631 -0.422 -0.380 -0.349 -0.349
## 78 x8 ~~ x9 14.946 -0.423 -0.423 -0.805 -0.805
## 33 textual =~ x3 9.151 -0.272 -0.269 -0.238 -0.238
## 55 x2 ~~ x7 8.918 -0.183 -0.183 -0.192 -0.192
## 31 textual =~ x1 8.903 0.350 0.347 0.297 0.297
## 51 x2 ~~ x3 8.532 0.218 0.218 0.223 0.223
## 59 x3 ~~ x5 7.858 -0.130 -0.130 -0.212 -0.212
## 26 visual =~ x5 7.441 -0.210 -0.189 -0.147 -0.147
Los índices de modificación representan la disminución en el valor de chi-
cuadrado que se produciría en caso se realizará lo sugerido. ¿Cómo saber
cuando es importante? Va a depender de cada análisis, es distinto un modelo
estructural con chi-cuadrado de 1500 de valor que presenta IM de 35 puntos;
que un modelo estructural de chi-cuadrado 65 con el mismo valor en IM.

Esta información se adiciona al “expected parameter change” (epc) y su valor


estandarizado (sepc.all) para tener mayor noción del cambio a nivel
estadístico que se realizaría.
Antes de hacer caso a la sugerencia propuesta, RECORDAR, siempre debe
primar el criterio metodológico. En caso de sugerir correlación de errores
entre ítems, seguir estas sugerencias:

a. Buscar similitud en el contenido de ambos ítems que pueda haber propiciado


una similar forma de producir error en la medición.
b. Verificar si los ítems comparten una misma forma de finalizar o iniciar el
enunciado.
c. Si los items pertenecen a diferentes factores, tener mucho cuidado. Existe la
posibilidad de que lo señalado como sugerencia solo se deba a aleatoridad en los
datos. Si es que pese a ello se encontrase relación o motivos para suponer errores
correlacionados entre dichos ítems, poner en alerta la integridad de la estructura
factorial de la prueba.

Con respecto a las sugerencias de que un ítem pertenezca a otro factor,


tener en cuenta los siguientes puntos:

a. Existe la posibilidad de que un ítem verdaderamente deba pertenecer a otro


factor. Generalmente sucede esto en pruebas nuevas o con pocos estudios
psicométricos.
b. De igual manera a la anterior condición, su señalamiento puede deberse a
pura aleatoridad estadística.
c. Si un mismo ítem aparece repetidamente en los IM y se sugiere que podría
suponer un cambio importante en chi-cuadrado si se realizase la sugerencia, se
debe tener en alerta a dicho ítem. Su exclusión del análisis puede mejorar la
estructura factorial.

Dicho lo anterior verificamos que los IM sugieren que habría un cambio de 36


puntos menos en el chi-cuadrado (valor actual de 85.3) si se modificase su
pertenencia al factor visual. Mientras que si se correlaciona los errores del
indicador 7 y 8, habría un cambio de 34.15, además de que la correlación
sería de 0.86 (sepc.all).

Recordemos que cada vez que se realiza una re-especificación en el modelo


los IM cambian debido a que el ajuste del modelo también cambia. Así que
no se recomienda hacer múltiples re-especificaciones a partir de un solo
procedimiento de análisis para re-especificar. De uno en uno o de dos en dos
si las incongruencias son más claras.

Para efectos de aprendizaje, incluiremos una correlación de errores entre el


indicador 7 y 8 para ver cómo se produce los cambios. Previo a ello
guardaremos los índices de ajuste en un objeto que servirá para ir
comparando los cambios realizados.
# Procederemos a re-especificar creando un objeto con nombre "model_02"
model_02 <- " # Modelo de medición
visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9
# Correlación de errores
x7 ~~ x8
"
Hemos agregado la re-especificación de la correlación entre
errores. ¡Estimemos nuevamente y veamos los resultados!
# Procederemos a re-especificar creando un objeto con nombre "model_02"
fit_02 <- cfa(model = model_02,
data = datos)
summary(fit_02, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-3 ended normally after 43 iterations
##
## Optimization method NLMINB
## Number of free parameters 22
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 53.272
## Degrees of freedom 23
## P-value (Chi-square) 0.000
##
## Model test baseline model:
##
## Minimum Function Test Statistic 918.852
## Degrees of freedom 36
## P-value 0.000
##
## User model versus baseline model:
##
## Comparative Fit Index (CFI) 0.966
## Tucker-Lewis Index (TLI) 0.946
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -3721.728
## Loglikelihood unrestricted model (H1) -3695.092
##
## Number of free parameters 22
## Akaike (AIC) 7487.457
## Bayesian (BIC) 7569.013
## Sample-size adjusted Bayesian (BIC) 7499.242
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.066
## 90 Percent Confidence Interval 0.043 0.090
## P-value RMSEA <= 0.05 0.118
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.047
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual =~
## x1 1.000 0.885 0.759
## x2 0.576 0.098 5.898 0.000 0.509 0.433
## x3 0.752 0.103 7.289 0.000 0.665 0.589
## textual =~
## x4 1.000 0.989 0.851
## x5 1.115 0.066 17.015 0.000 1.103 0.856
## x6 0.926 0.056 16.682 0.000 0.916 0.838
## speed =~
## x7 1.000 0.383 0.352
## x8 1.244 0.194 6.414 0.000 0.477 0.471
## x9 2.515 0.641 3.924 0.000 0.963 0.956
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x7 ~~
## .x8 0.353 0.067 5.239 0.000 0.353 0.389
## visual ~~
## textual 0.400 0.073 5.511 0.000 0.457 0.457
## speed 0.184 0.054 3.423 0.001 0.544 0.544
## textual ~~
## speed 0.102 0.036 2.854 0.004 0.270 0.270
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x1 0.576 0.101 5.678 0.000 0.576 0.424
## .x2 1.122 0.100 11.171 0.000 1.122 0.812
## .x3 0.832 0.087 9.552 0.000 0.832 0.653
## .x4 0.372 0.048 7.791 0.000 0.372 0.276
## .x5 0.444 0.058 7.600 0.000 0.444 0.267
## .x6 0.357 0.043 8.287 0.000 0.357 0.298
## .x7 1.036 0.090 11.501 0.000 1.036 0.876
## .x8 0.795 0.080 9.988 0.000 0.795 0.778
## .x9 0.088 0.188 0.466 0.641 0.088 0.086
## visual 0.783 0.135 5.810 0.000 1.000 1.000
## textual 0.978 0.112 8.729 0.000 1.000 1.000
## speed 0.147 0.056 2.615 0.009 1.000 1.000
A simple vista podemos ver una mejora importante en los índices de ajuste
del modelo estimado. Ordenemos los datos y veamoslo en paralelo para
entenderlo mejor.
# Guardando los índices en objetos
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
fit_index <- broom::glance(fit) %>%
select(chisq, npar, cfi, tli, rmsea, rmsea.conf.high, srmr, aic, bic,
estimator)
fit_index02 <- broom::glance(fit_02) %>%
select(chisq, npar, cfi, tli, rmsea, rmsea.conf.high, srmr, aic, bic,
estimator)
# Uniendo
bind_rows(fit_index, fit_index02, .id = "Modelo")
## # A tibble: 2 x 11
## Modelo chisq npar cfi tli rmsea rmsea.conf.high srmr aic
bic
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
<dbl>
## 1 1 85.3 21 0.931 0.896 0.0921 0.114 0.0652 7517.
7595.
## 2 2 53.3 22 0.966 0.946 0.0661 0.0895 0.0471 7487.
7569.
## # ... with 1 more variable: estimator <chr>
¡Listo! Estamos viendo que el modelo 2 muestra una mejora importante en la
estructura factorial de la prueba. Es decir, tener en consideración que los
errores de indicador 7 y 8 se encuentran correlacionados permite un mejor
ajuste en lo mostrado por la matriz de covarianza empírica y la teórica
(especificado).

Antes de cantar victoria, volvamos a verificar los IM para ver si hay más
cambios importantes sugeridos al modelo.
# Solicitar los 10 primeros IM con valores más altos
modindices(fit_02, sort = TRUE, maximum.number = 10)
## lhs op rhs mi epc sepc.lv sepc.all sepc.nox
## 34 textual =~ x3 9.057 -0.257 -0.254 -0.225 -0.225
## 32 textual =~ x1 8.734 0.313 0.309 0.265 0.265
## 60 x3 ~~ x5 8.712 -0.136 -0.136 -0.223 -0.223
## 67 x4 ~~ x7 8.117 0.112 0.112 0.181 0.181
## 56 x2 ~~ x7 7.266 -0.160 -0.160 -0.148 -0.148
## 52 x2 ~~ x3 6.536 0.181 0.181 0.187 0.187
## 27 visual =~ x5 6.076 -0.191 -0.169 -0.131 -0.131
## 29 visual =~ x7 5.438 -0.231 -0.204 -0.188 -0.188
## 66 x4 ~~ x6 5.367 -0.222 -0.222 -0.609 -0.609
## 30 visual =~ x8 5.049 0.276 0.244 0.242 0.242
Genial, parece ser que los IM mostrados no son tan altos ni
el sepc.all representa un cambio importante al modelo estimado. Tenemos
entonces un modelo estructural comprobado… ¡Espera! ¿Hemos revisado la
distribución de los datos? Ups… Verifiquemos si se tiene una distribución
normal multivariada. Para ello usaremos la función “mvn” del paquete “MVN”.

Referencias
Beaujean, A. A. (2014). Latent variable modeling using R: A step by step
guide. New York: Routledge/Taylor & Francis Group.

Brown, T. A. (2015). Confirmatory factor analysis for applied


research (Second edition). New York ; London: The Guilford Press.

Epskamp, S., & Simon Stuber. (2017). SemPlot: Path diagrams and visual
analysis of various sem packages’ output. https://CRAN.R-
project.org/package=semPlot

Holzinger, K., & Swineford, F. (1939). A study in factor analysis: The stability
of a bifactor solution. Supplementary Educational Monograph, 48.
Jorgensen, T. D., Pornprasertmanit, S., Schoemann, A., & Rosseel, Y.
(2018). SemTools: Useful tools for structural equation
modeling. https://CRAN.R-project.org/package=semTools

Korkmaz, S., Goksuluk, D., & Zararsiz, G. (2018). MVN: Multivariate


normality tests. https://CRAN.R-project.org/package=MVN

R Core Team. (2018). R: A language and environment for statistical


computing. Vienna, Austria: R Foundation for Statistical
Computing. https://www.R-project.org/

Revelle, W. (2018). Psych: Procedures for psychological, psychometric, and


personality research. https://CRAN.R-project.org/package=psych

Rosseel, Y. (2018). Lavaan: Latent variable analysis. https://CRAN.R-


project.org/package=lavaan

Xie, Y. (2018). Bookdown: Authoring books and technical documents with r


markdown. https://github.com/rstudio/bookdown
Structural Equation Modeling
with the sem Package in R:
A Demonstration
Will Vincent, PH 251D, Final
Project 2
In the simplest terms, structural equation modeling(SEM) is basically like regression, but you can analyze
multiple outcomes simultaneously. You can also analyze multiple mediators and moderators at once in the
same model. In psychology, this is popular among community-based researchers. However,
neuropsychologists and more clinically focused psychologists who focus on randomized controlled trials
tend not to use this. Public-health researchers who are analyzing complex models of causal factors or
doing survey-based research with large samples multiple outcome variables would find SEM useful.

In order to conduct SEM in R, I am using the sem package available in R. (Another good package is


lavaan.) This demonstration is based on John Fox's (2002) Appendix to his book An R and S-Plus
Compnaion to Applied Regression. It's a good idea to familiarize yourself with the priniples and best
practices of structural equation modeling before attempting to do SEM. A good primer is as follows:

Kline, R. B. (2005). Principles and practice of structural equation modeling. New York, NY: The Guilford
Press.

In this model, I am determining whether AIDS-related stigma, religiosity, and adherence to the traditional
male role norm of antifemininity lead to perceptions of two types of threat in response to gay men. I am
also testing whether these perceived threats, in turn, lead to intoxicated and non-intoxicated aggression
toward sexual minorities.

CAVEAT: This is a cross-sectional study. Of course, we cannot determine causation with this design.
Nonetheless, terms like “path” and “effect” are often used with SEM even in cross-sectional studies. The
understanding is that these are not really causal.

I am activitating the sem package that I have already installed. But I will not import data. As you will
subsequently see, I won't need to for sem package.

library("sem")
## Loading required package: MASS
## Loading required package: matrixcalc

Create a correlation matrix of the assocations between all of the observed variables, which are just your
study variables that you directly measured. Structural equation modeling analyzes the correlations
between the variables. If you want to be fancier, you can create latent variables that represent underlying
factors, and you might choose to analyze the covariance matrix plus the variable means and standard
deviations in a software program or R package that will let you do so.

You will want to run correlation analyses to find the correlations among your observed variables. You can
use R or another program, like Stata.

corr.diss <- matrix(c(1, 0, 0, 0, 0, 0, 0, 0.876, 1, 0, 0, 0, 0, 0,


0.318, 0.32,
1, 0, 0, 0, 0, 0.358, 0.333, 0.84, 1, 0, 0, 0, 0.245, 0.264,
0.566, 0.521,
1, 0, 0, 0.267, 0.254, 0.549, 0.506, 0.365, 1, 0, 0.058, 0.074,
0.074, 0.301,
0.52, 0.149, 1), ncol = 7, byrow = T)

rownames(corr.diss) <- colnames(corr.diss) <- c("IntAgg", "NonIntAgg",


"RealThr",
"SymbThr", "ARStigma", "MRNaf", "Relig")

corr.diss
## IntAgg NonIntAgg RealThr SymbThr ARStigma MRNaf Relig
## IntAgg 1.000 0.000 0.000 0.000 0.000 0.000 0
## NonIntAgg 0.876 1.000 0.000 0.000 0.000 0.000 0
## RealThr 0.318 0.320 1.000 0.000 0.000 0.000 0
## SymbThr 0.358 0.333 0.840 1.000 0.000 0.000 0
## ARStigma 0.245 0.264 0.566 0.521 1.000 0.000 0
## MRNaf 0.267 0.254 0.549 0.506 0.365 1.000 0
## Relig 0.058 0.074 0.074 0.301 0.520 0.149 1

So, now is the fun part: MODELING!

ram.diss <- matrix(c(


# path parameter start-value
"RealThr -> IntAgg", "b11", NA,
"SymbThr -> IntAgg", "b12", NA,
"RealThr -> NonIntAgg", "b21", NA,
"SymbThr -> NonIntAgg", "b22", NA,
"ARStigma -> RealThr", "a11", NA,
"Relig -> RealThr", "a12", NA,
"MRNaf -> RealThr", "a13", NA,
"ARStigma -> SymbThr", "a21", NA,
"Relig -> SymbThr", "a22", NA,
"MRNaf -> SymbThr", "a23", NA,
"RealThr <-> SymbThr", "c11", NA,
"IntAgg <-> NonIntAgg", "c21", NA,
"RealThr <-> RealThr", "d11", NA,
"SymbThr <-> SymbThr", "d21", NA,
"IntAgg <-> IntAgg", "d31", NA,
"NonIntAgg <-> NonIntAgg", "d41", NA),
ncol=3, byrow=T)

In the path column, I am estimating assocations between variables that will be estimated using regression
coefficents. (Think coefficients, or slops, from regression.) Single-headed arrows represent “causal” paths,
where as double headed arrows represent “covariances” between variables. These covariances are like
correlations that are in their original units of measurement. These covariances in the model are actually
associations between the variables' error terms. The parameter column names the parameters that you
want to estimate (e.g., regression coefficients), and you don't really need to worry about what the starting
values are. If you put a number in this column instead of NA, you will fix the parameter to be that value.

I chose parameter names that are intuitive to me. You can name them what you want, and you can even
name them after standard statitical notation, like “beta”. The numbering is up to you.

Now, we want the results of our SEM analyses.

sem.diss <- sem(ram.diss, corr.diss, N = 212, fixed.x = c("ARStigma",


"Relig",
"MRNaf"))
I am reading into the object, sem.diss, the sem function that includs the modeling we did in ram.diss, the
correlation matrix we created in corr.diss, and the sample size (N).

The fixed.x argument tells R what predictor variables are in the model. These predictor variables, which
are called exogenous variables, are variables that have no single-headed arrows pointing to them.
Variables that do have single-headed arrows pointing toward them are called, endogenous variables.

Prepare yourself for the results!

sem.diss
##
## Model Chisquare = 7.293 Df = 6
##
## b11 b12 b21 b22 a11 a12 a13
a21
## 0.05870 0.30870 0.13682 0.21807 0.57256 -0.28062 0.38183
0.35482
## a22 a23 c11 c21 d11 d21 d31
d41
## 0.06177 0.36729 0.43296 0.75442 0.48708 0.61070 0.87082
0.88360
##
## Iterations = 0

Here are the results of the analyses. As you can see, the (unstandardized) regression coefficients are
shown. Unfortunately, standard errors are not included. But, fear not.

summary(sem.diss)
##
## Model Chisquare = 7.293 Df = 6 Pr(>Chisq) = 0.2946
## AIC = 39.29
## BIC = -24.85
##
## Normalized Residuals
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -0.568 0.000 0.000 0.134 0.000 1.120
##
## R-square for Endogenous Variables
## RealThr IntAgg SymbThr NonIntAgg
## 0.5129 0.1292 0.3893 0.1164
##
## Parameter Estimates
## Estimate Std Error z value Pr(>|z|)
## b11 0.05870 0.11840 0.4957 6.201e-01 IntAgg <--- RealThr
## b12 0.30870 0.11840 2.6072 9.128e-03 IntAgg <--- SymbThr
## b21 0.13682 0.11927 1.1472 2.513e-01 NonIntAgg <--- RealThr
## b22 0.21807 0.11927 1.8284 6.748e-02 NonIntAgg <--- SymbThr
## a11 0.57256 0.05982 9.5710 1.058e-21 RealThr <--- ARStigma
## a12 -0.28062 0.05632 -4.9823 6.282e-07 RealThr <--- Relig
## a13 0.38183 0.05167 7.3891 1.478e-13 RealThr <--- MRNaf
## a21 0.35482 0.06698 5.2971 1.177e-07 SymbThr <--- ARStigma
## a22 0.06177 0.06307 0.9794 3.274e-01 SymbThr <--- Relig
## a23 0.36729 0.05786 6.3477 2.186e-10 SymbThr <--- MRNaf
## c11 0.43296 0.04794 9.0315 1.694e-19 SymbThr <--> RealThr
## c21 0.75442 0.07965 9.4717 2.753e-21 NonIntAgg <--> IntAgg
## d11 0.48708 0.04742 10.2713 9.490e-25 RealThr <--> RealThr
## d21 0.61070 0.05946 10.2713 9.490e-25 SymbThr <--> SymbThr
## d31 0.87082 0.08478 10.2713 9.490e-25 IntAgg <--> IntAgg
## d41 0.88360 0.08603 10.2713 9.490e-25 NonIntAgg <--> NonIntAgg
##
## Iterations = 0

Here are your path coefficients and standard errors, along with p-values if you are interested in hypothesis
testing.

It is worth noting that the results also include R-squared values for all variables that have arrows pointing
toward them. You also get fit stiatistics, chi-square test of model fit, the Aikike Information Criterion (AIC),
and the Bayesian Information Criterion (BIC). Many people use chi-square default, and you should almost
always report some version of the chi-square model fit test with your results. A good, commonly used test
of model fit is the root mean-squared error (RMSEA), which you can calculate. See Fox's (2002) work,
reference above.

Unfortunately, these results do not include indirect effects, which are the effects of the predictor (e.g.,
ARStigma) on the outcome (e.g., IntAgg) through the mediator (e.g., RealThr). However, you can get
these by multiplying a by multiplying the regression coefficent of ARStigma -> RealThr by the regression
coefficient. You can do what's called a Sobel test to find out if this particuarly indirect path is statistically
significantly differnet from zero, or you can use bootstrapping. These deserve their own demonstrations
and are beyond the scope of this project.

In this example of SEM, we used continuous variables. If you have endogenous variables that are not
continuous, you would approach this all a bit differently.
Estadística y Machine Learning con
R
Francisco Parra
15 de Junio de 2017

Agrupación de la información
Análisis de componentes principales
El Análisis de Componentes Principales (ACP) es una técnica estadística de síntesis de la
información, o reducción de la dimensión (número de variables.

Dadas nn observaciones de pp variables, se buscan m<pm<p variables que sean


combinaciones lineales de las pp originales y que estén incorreladas, recogiendo la mayor
parte de la información o variabilidad de los datos. Hay que tener presente que, si las
variables originales están incorreladas de partida, entonces no tiene sentido realizar un
análisis de componentes principales.
Se considera una serie de variables (x1,x2,...xp)(x1,x2,...xp) sobre un grupo de objetos o
individuos y se trata de calcular, a partir de ellas, un nuevo conjunto de
variables (y1,y2,...yp)(y1,y2,...yp),incorreladas entre sí, cuyas varianzas vayan
decreciendo progresivamente. Cada yjyj (donde j=1,...,pj=1,...,p) es una combinación
lineal de las x1,x2,...xpx1,x2,...xp originales, es decir:
yj=aj1x1+aj2x2+...+ajPxp=a′jxyj=aj1x1+aj2x2+...+ajPxp=aj′x
donde a′j=(aj1,aj2,...,ajP)aj′=(aj1,aj2,...,ajP) y
x=⎡⎣⎢x1x2...xp⎤⎦⎥x=[x1x2...xp]
El objeto del análisis es maximizar la varianza del componente obtenido, pero
manteniendo la ortogonalidad de la transformación, esto es a′jaj=∑pj=1a2kj=1aj
′aj=∑j=1pakj2=1.
El primer componente por tanto se obtendrá:

Var(y1)=Var(a′1x)=a′1σa1Var(y1)=Var(a1′x)=a1′σa1
El problema consiste en maximizar la función a′1σa1a1′σa1 donde σσ es la matriz de
covarianzas de las pp variables,sujeta a la restricción a′1a1=1a1′a1=1, utilizandose para
ello los multiplicadores de Lagrange:
L(a1)=a′1σa1−λ(a′1a1−1)L(a1)=a1′σa1−λ(a1′a1−1)
siendo ahora a1a1 la incognita, se busca el maximo:
L(∂a1)∂a1=0⟶(σ−λI)a1=0L(∂a1)∂a1=0⟶(σ−λI)a1=0
La solución del sistema de ecuaciones requiere que el determinante ∣σ−λI∣∣σ−λI∣ sea no
nulo, de manera que λλ es un autovalor de σσ, que al ser definida positiva,
tendrá pp autovalores distintos.
Entonces, para maximizar la varianza de y1y1 se tiene que tomar el mayor
autovalor, λ1λ1 y el correspondiente autovector de a1a1.
El segundo componente principal,y2=a′2xy2=a2′x ha de estar incorrelacionado con y1y1,
es decir:
cov(y1,y2)=cov(a′1x,a′2x)=a′1σa2=0cov(y1,y2)=cov(a1′x,a2′x)=a1′σa2=0.
Equivale a:

a′1λa2=0a1′λa2=0
Y a maximizar las Var(y2)=a′2σa2Var(y2)=a2′σa2 imponinedo ahora dos restricciones:
a′2a2=1a2′a2=1
a′2a1=0a2′a1=0
Se forma el lagrangiano L(a2)=a′12σa2−λ(a′2a2−1)−δ(a
′2a1)L(a2)=a1′2σa2−λ(a2′a2−1)−δ(a′2a1), se deriva respecto a a2a2 y se iguala a cero:
L(∂a2)∂a2=0⟶(σ−λI)a2=0L(∂a2)∂a2=0⟶(σ−λI)a2=0.
Elegimos λ2λ2 como segundo autovalor de la matriz σσ asociado al autovector
asociado a2a2.
Entonces todos los p componentes de yy se pueden expresar como el producto de una
matriz formada por los autovectores, multiplicada por el vector xx que contiene las
variables originales:
y=Axy=Ax
donde la Var(yj)=λjVar(yj)=λj, y la Cov(yj,ys)=0Cov(yj,ys)=0.
Si sumamos todos los autovalores,tendremos entonces la varianza total de los
componentes, que por las propiedades del operador traza, acaba siendo igual que la
varianza de los variables originales:

∑Var(yj)=∑(λj)=∑Var(xj)∑Var(yj)=∑(λj)=∑Var(xj)
El porcentaje de varianza total que recoge cada componentes principales, es el critierio
utilizado para reducir las pp variables de nuestro conjunto de datos,
por mm combinaciones lineales de dichas variables.
El ACP se emplea sobre todo en análisis exploratorio de datos (Analisis factorial) y para
construir modelos predictivos cuando las variables explicativas tienen problemas de
colinealidad.
El ACP comporta el cálculo de la descomposición en autovalores de la matriz de
covarianza, normalmente tras centrar los datos en la media de cada atributo.
El análisis de componentes principales (PCA) puede realizarse con una función de la
librería básica de «R»: prcomp o princomp.

require(graphics)
str(USArrests)
## 'data.frame': 50 obs. of 4 variables:
## $ Murder : num 13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
## $ Assault : int 236 263 294 190 276 204 110 238 335 211 ...
## $ UrbanPop: int 58 48 80 50 91 78 77 72 80 60 ...
## $ Rape : num 21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9
25.8 ...
prcomp(USArrests, scale = TRUE)
## Standard deviations (1, .., p=4):
## [1] 1.5748783 0.9948694 0.5971291 0.4164494
##
## Rotation (n x k) = (4 x 4):
## PC1 PC2 PC3 PC4
## Murder -0.5358995 0.4181809 -0.3412327 0.64922780
## Assault -0.5831836 0.1879856 -0.2681484 -0.74340748
## UrbanPop -0.2781909 -0.8728062 -0.3780158 0.13387773
## Rape -0.5434321 -0.1673186 0.8177779 0.08902432
prcomp(~ Murder + Assault + Rape, data = USArrests, scale = TRUE)
## Standard deviations (1, .., p=3):
## [1] 1.5357670 0.6767949 0.4282154
##
## Rotation (n x k) = (3 x 3):
## PC1 PC2 PC3
## Murder -0.5826006 0.5339532 -0.6127565
## Assault -0.6079818 0.2140236 0.7645600
## Rape -0.5393836 -0.8179779 -0.1999436
plot(prcomp(USArrests))

summary(prcomp(USArrests, scale = TRUE))


## Importance of components%s:
## PC1 PC2 PC3 PC4
## Standard deviation 1.5749 0.9949 0.59713 0.41645
## Proportion of Variance 0.6201 0.2474 0.08914 0.04336
## Cumulative Proportion 0.6201 0.8675 0.95664 1.00000
biplot(prcomp(USArrests, scale = TRUE))

Análisis factorial
El análisis factorial (AF) es tambien una técnica estadística de reducción de datos usada
para explicar las correlaciones entre las variables observadas en términos de un número
menor de variables no observadas llamadas factores.
El análisis factorial exploratorio, se utiliza para tratar de descubrir la estructura interna de
un número relativamente grande de variables. La hipótesis a priori del investigador es que
pueden existir una serie de factores asociados a grupos de variables. Las cargas de los
distintos factores se utilizan para intuir la relación de éstos con las distintas variables. Es el
tipo de análisis factorial más común.
El análisis factorial confirmatorio, AFC, trata de determinar si el número de factores
obtenidos y sus cargas se corresponden con los que cabría esperar a la luz de una teoría
previa acerca de los datos. La hipótesis a priori es que existen unos determinados factores
preestablecidos y que cada uno de ellos está asociado con un determinado subconjunto de
las variables. El análisis factorial confirmatorio entonces arroja un nivel de confianza para
poder aceptar o rechazar dicha hipótesis.
El análisis de componentes principales es el método apropiado de extracción de factores,
cuando el interés primordial se centra en la predicción o el número mínimo de factores
necesarios para justificar la porción máxima de varianza representada en la serie de
variables original, y cuando el conocimiento previo sugiere que la varianza específica y de
error representan una porción relativamente pequeña de la varianza total. Por el contrario
cuando se pretende identificar las dimensiones latentes o las construcciones
representadas en las variables originales y se tiene poco conocimiento de la varianza
específica y el error, lo más apropiado es utilizar el método factorial común. Si bien las
complicaciones del análisis factorial común han contribuido al análisis generalizado de la
técnica de componentes principales.
Para interpretar bien los factores se utiliza una rotación de ejes, ya que las soluciones
factoriales no rotadas extraen factores según su orden de importancia. El primer factor
tiende a ser un factor general por el que casi toda variable se ve afectada
significativamente dando cuenta del mayor porcentaje de varianza. Los métodos de
rotación ortogonales mas utilizados son VARIMAX, QUARTIMAX y EQUIMAX.
En la practica no se utiliza un criterio único de los factores a extraer, si bien se utiliza como
primera aproximación el gráfico de autovalor para el criterio de contraste de caida,
despues de interpretar los factores extraidos hay que valorar su caracter práctico.
Se leen la base de datos Seatbelts, que contiene datos mensuales de conductores de
Gran Bretaña, muestos o heridos entre Enero de 1969 y Diciembre de 1983:

library(rela)
Belts <- Seatbelts[,1:7]
summary(Belts)
## DriversKilled drivers front rear
## Min. : 60.0 Min. :1057 Min. : 426.0 Min. :224.0
## 1st Qu.:104.8 1st Qu.:1462 1st Qu.: 715.5 1st Qu.:344.8
## Median :118.5 Median :1631 Median : 828.5 Median :401.5
## Mean :122.8 Mean :1670 Mean : 837.2 Mean :401.2
## 3rd Qu.:138.0 3rd Qu.:1851 3rd Qu.: 950.8 3rd Qu.:456.2
## Max. :198.0 Max. :2654 Max. :1299.0 Max. :646.0
## kms PetrolPrice VanKilled
## Min. : 7685 Min. :0.08118 Min. : 2.000
## 1st Qu.:12685 1st Qu.:0.09258 1st Qu.: 6.000
## Median :14987 Median :0.10448 Median : 8.000
## Mean :14994 Mean :0.10362 Mean : 9.057
## 3rd Qu.:17203 3rd Qu.:0.11406 3rd Qu.:12.000
## Max. :21626 Max. :0.13303 Max. :17.000

Calculo la matriz de correlaciones:


correl=cor(Belts,use="pairwise.complete.obs")
correl
## DriversKilled drivers front rear
kms
## DriversKilled 1.0000000 0.8888264 0.7067596 0.3533510
-0.3211016
## drivers 0.8888264 1.0000000 0.8084114 0.3436685
-0.4447631
## front 0.7067596 0.8084114 1.0000000 0.6202248
-0.3573823
## rear 0.3533510 0.3436685 0.6202248 1.0000000
0.3330069
## kms -0.3211016 -0.4447631 -0.3573823 0.3330069
1.0000000
## PetrolPrice -0.3866061 -0.4576675 -0.5392394 -0.1326272
0.3839004
## VanKilled 0.4070412 0.4853995 0.4724207 0.1217581
-0.4980356
## PetrolPrice VanKilled
## DriversKilled -0.3866061 0.4070412
## drivers -0.4576675 0.4853995
## front -0.5392394 0.4724207
## rear -0.1326272 0.1217581
## kms 0.3839004 -0.4980356
## PetrolPrice 1.0000000 -0.2885584
## VanKilled -0.2885584 1.0000000

La prueba de esfericidad de Bartlett contrasta la hipótesis nula de que la matriz de


correlaciones es una matriz identidad, en cuyo caso no existirían correlaciones
significativas entre las variables y el modelo factorial no sería pertinente.

library(psych)
cortest.bartlett(Belts)
## R was not square, finding R from data
## $chisq
## [1] 968.7579
##
## $p.value
## [1] 1.260101e-191
##
## $df
## [1] 21

Para calcular los componentes principales basados en la matriz de correlaciones:

## Importance of components:
## Comp.1 Comp.2 Comp.3 Comp.4
Comp.5
## Standard deviation 1.9203515 1.2141729 0.8489513 0.78140438
0.5754445
## Proportion of Variance 0.5268214 0.2106022 0.1029598 0.08722754
0.0473052
## Cumulative Proportion 0.5268214 0.7374236 0.8403834 0.92761093
0.9749161
## Comp.6 Comp.7
## Standard deviation 0.3298839 0.258386585
## Proportion of Variance 0.0155462 0.009537661
## Cumulative Proportion 0.9904623 1.000000000
##
## Loadings:
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7
## DriversKilled -0.444 0.136 0.521 -0.360 -0.519 0.323
## drivers -0.480 0.100 0.377 0.505 -0.596
## front -0.475 -0.198 -0.103 0.417 0.414 0.612
## rear -0.226 -0.686 -0.322 0.277 -0.406 -0.361
## kms 0.276 -0.627 -0.606 0.365 0.168
## PetrolPrice 0.327 -0.141 0.829 0.277 0.311
## VanKilled -0.334 0.259 0.526 -0.627 -0.387

A continuación se realiza un Analisis factorial con la libreria : psych, representando el


gráfico de autovalor para el criterio de contraste de caida.

library(psych)
fa.parallel(Belts)
## The estimated weights for the factor scores are probably incorrect.
Try a different factor extraction method.
## Warning in fac(r = r, nfactors = nfactors, n.obs = n.obs, rotate =
## rotate, : A loading greater than abs(1) was detected. Examine the
loadings
## carefully.
## The estimated weights for the factor scores are probably incorrect.
Try a different factor extraction method.
## Warning in fac(r = r, nfactors = nfactors, n.obs = n.obs, rotate =
## rotate, : An ultra-Heywood case was detected. Examine the results
carefully

## Warning in fac(r = r, nfactors = nfactors, n.obs = n.obs, rotate =


## rotate, : A loading greater than abs(1) was detected. Examine the
loadings
## carefully.
## The estimated weights for the factor scores are probably incorrect.
Try a different factor extraction method.
## Warning in fac(r = r, nfactors = nfactors, n.obs = n.obs, rotate =
## rotate, : An ultra-Heywood case was detected. Examine the results
carefully

## Parallel analysis suggests that the number of factors = 3 and the


number of components = 2
Belts.ps <- fa(Belts, fm="minres", nfactors=3, rotate="varimax")
## The estimated weights for the factor scores are probably incorrect.
Try a different factor extraction method.
## Warning in fac(r = r, nfactors = nfactors, n.obs = n.obs, rotate =
## rotate, : An ultra-Heywood case was detected. Examine the results
carefully
print(Belts.ps) # Factor loadings as $loadings
## Factor Analysis using method = minres
## Call: fa(r = Belts, nfactors = 3, rotate = "varimax", fm =
"minres")
## Standardized loadings (pattern matrix) based upon correlation
matrix
## MR1 MR3 MR2 h2 u2 com
## DriversKilled 0.81 0.27 0.26 0.80 0.19785 1.4
## drivers 0.88 0.39 0.25 1.00 0.00454 1.6
## front 0.47 0.54 0.71 1.01 -0.01177 2.7
## rear 0.21 -0.12 0.82 0.72 0.27655 1.2
## kms -0.19 -0.93 0.32 1.00 0.00012 1.3
## PetrolPrice -0.27 -0.44 -0.20 0.30 0.69660 2.1
## VanKilled 0.30 0.49 0.11 0.34 0.65652 1.8
##
## MR1 MR3 MR2
## SS loadings 1.89 1.83 1.45
## Proportion Var 0.27 0.26 0.21
## Cumulative Var 0.27 0.53 0.74
## Proportion Explained 0.37 0.35 0.28
## Cumulative Proportion 0.37 0.72 1.00
##
## Mean item complexity = 1.7
## Test of the hypothesis that 3 factors are sufficient.
##
## The degrees of freedom for the null model are 21 and the
objective function was 5.16 with Chi Square of 968.76
## The degrees of freedom for the model are 3 and the objective
function was 0.07
##
## The root mean square of the residuals (RMSR) is 0.02
## The df corrected root mean square of the residuals is 0.04
##
## The harmonic number of observations is 192 with the empirical chi
square 1.85 with prob < 0.6
## The total number of observations was 192 with Likelihood Chi
Square = 13.41 with prob < 0.0038
##
## Tucker Lewis Index of factoring reliability = 0.922
## RMSEA index = 0.137 and the 90 % confidence intervals are 0.067
0.212
## BIC = -2.36
## Fit based upon off diagonal values = 1

Analsis factorial con factanal

Belts.fa<-factanal(Belts,factors=3, rotation="varimax",scores =
"Bartlett")
Belts.fa
##
## Call:
## factanal(x = Belts, factors = 3, scores = "Bartlett", rotation =
"varimax")
##
## Uniquenesses:
## DriversKilled drivers front rear
kms
## 0.197 0.005 0.005 0.227
0.051
## PetrolPrice VanKilled
## 0.660 0.645
##
## Loadings:
## Factor1 Factor2 Factor3
## DriversKilled 0.820 0.264 0.244
## drivers 0.883 0.391 0.249
## front 0.485 0.531 0.691
## rear 0.204 -0.121 0.846
## kms -0.191 -0.903 0.311
## PetrolPrice -0.241 -0.469 -0.249
## VanKilled 0.301 0.507
##
## Factor1 Factor2 Factor3
## SS loadings 1.915 1.813 1.482
## Proportion Var 0.274 0.259 0.212
## Cumulative Var 0.274 0.533 0.744
##
## Test of the hypothesis that 3 factors are sufficient.
## The chi square statistic is 11.54 on 3 degrees of freedom.
## The p-value is 0.00914

Análisis factorial con libreria : rela

library(rela)
res <- paf(as.matrix(Belts))
summary(res) # Automatically calculate KMO with MSA, determine the
number of factors,
## $KMO
## [1] 0.66899
##
## $MSA
## MSA
## DriversKilled 0.75338
## drivers 0.72295
## front 0.65795
## rear 0.40214
## kms 0.53517
## PetrolPrice 0.83413
## VanKilled 0.88197
##
## $Bartlett
## [1] 968.76
##
## $Communalities
## Initial Communalities Final Extraction
## DriversKilled 0.79824 0.66181
## drivers 0.87486 0.85141
## front 0.87225 0.91049
## rear 0.76216 0.69016
## kms 0.67184 0.89761
## PetrolPrice 0.36120 0.29405
## VanKilled 0.36294 0.34590
##
## $Factor.Loadings
## [,1] [,2]
## DriversKilled 0.80934 -0.082307
## drivers 0.92263 -0.012744
## front 0.92638 -0.228709
## rear 0.41852 -0.717642
## kms -0.53335 -0.783039
## PetrolPrice -0.53096 -0.110142
## VanKilled 0.55008 0.208105
##
## $RMS
## [1] 0.050492
# calculate chi-square of Bartlett's sphericity test, communalities
and
# factor loadings. Communalities are 1 minus uniquenesses.
barplot(res$Eigenvalues[,1]) # First column of eigenvalues.

resv <- varimax(res$Factor.Loadings) # Varimax rotation is possible


later.
print(resv)
## $loadings
##
## Loadings:
## [,1] [,2]
## DriversKilled 0.773 -0.254
## drivers 0.898 -0.211
## front 0.856 -0.422
## rear 0.255 -0.791
## kms -0.689 -0.650
## PetrolPrice -0.542
## VanKilled 0.582
##
## [,1] [,2]
## SS loadings 3.309 1.343
## Proportion Var 0.473 0.192
## Cumulative Var 0.473 0.664
##
## $rotmat
## [,1] [,2]
## [1,] 0.97667 -0.21474
## [2,] 0.21474 0.97667
barplot(sort(colSums(loadings(resv)^2),decreasing=TRUE)) # screeplot
using rotated SS loadings.

scores <- as.matrix(Belts) %*% as.matrix(resv$loadings) # Get factor


scores in a simple manner.

El índice KMO compara los valores de las correlaciones entre las variables y sus
correlaciones parciales. Si el índice KMO está próximo a 1, el ACP se puede hacer. Si el
índice es bajo (próximo a 0), el ACP no será relevante.

Análisis cluster
Introducción
El análisis cluster (AC) es un conjunto de técnicas multivariantes cuyo principal propósito
es agrupar objetos basándose en las características que poseen. El AC clasifica los
objetos en clases ó conglomerados de tal forma que cada objeto sea parecido a los que
hay en el conjunto de su conglomerado. Los conglomerados resultantes tendrán que tener
un alto grado de homogeneidad interna (dentro del conglomerado) y de heterogeneidad
externa (entre conglomerados).
Para realizar un AC se necesita una medida de similitud, de correspondencia, o parecido
entre objetos que van a ser analizados. Esta puede ser medida de varias formas, pero en
el AC, tres son los métodos de simulitud que se utilizan: medidas de correlación (la matriz
de correlación entre variables), medidas de distancia (la más utilizada es la distancia
euclidea) y las medidas de asociación, cuando se tienen datos no métricos.
Una vez se tiene una matriz de simulitud calculada, hay que realizar el proceso de
partición de los datos, para ello hay que decidir el algoritmo de aglomeración utilizado en la
formación de conglomerados, para despues tomar una decisión acerca del número de
conglomerados que se van a formar. Los algoritmos de obtención de conglomerados se
subdividen en métodos jerárquicos (encadenamiento simple, encadenamiento completo,
encadenamiento médio, método de Ward, método del centroide), de los no jerarquicos
(umbral secuencial, umbral paralelo, optimización), o una combinación de los dos.
El dendrograma ó gráfico en forma de arbol, es una herramienta visual que ayudar a
decidir el número de conglomerados que podrían representar mejor la estructura de los
datos.
Para determinar el número final de conglomerados a formar o regla de parada, no hay un
procedimiento determinado, ha de decidirlo el investigador en la fase de interpretación de
los datos.

Cluster Jerarquico
R incluye la función hclust para la realización de clasificaciones jerárquicas.
Una clasificación precisa que el investigador le pase dos opciones básicas a R:
●Medida de similitud/disimilitud para calcular la matriz de distancias
●Estrategia de fusión
Posteriormente, en la interpretación de los datos el investigador deberá decidir el punto de
corte y, con ello, el número de grupos.
Se puede usar la función nativa de R dist para calcular la matriz de distancias; por defecto
el programa usa la distancia euclídea (euclidean), siendo posible elegir varias más con la
opción method=“”: maximum, manhattan, canberra, binary, minkowski.
Las estrategias de fusión disponibles en hclust son las siguientes:
●“ward”: la distancia entre dos conglomerados es la suma de los cuadrados entre dos
conglomerados sumados para todas las variables. En cada paso del procedimiento de
aglomeración se minimiza la suma de cuadrados dentro del conglomerado para todas las
particiones. Tiende a combinar los conglomerados con un número reducido de
dimensiones.
●“single”: distancia mínima o vecino más próximo, encuentra dos objetos separados por la
distancia más corta y los coloca en un primer conglomerado. A continuación se encuetra la
distancia más corta, y se une a el un tercer objeto o se forma un nuevo conglomerado de
dos miembros. El proceso continua hasta que todos los objetos están en un conglomerado.
●“complete”: Parecido al “single”(simple) pero utilizando como criterio de agregación la
distancia máxima (aproximación al vecino más lejano).
●“average”: comienza igual que los métodos “single” y “complete”, pero el método de
aproximación es la distancia media entre todos los individuos de un conglomerado y los de
otro.
●“mcquitty”
●“median”
●“centroid”: la distancia entre dos conglomerados es la distancia (euclidia) entre
centroides.
Realizamos un Cluster Jerarquico con las tasas de crimen en USA (USArrests), utilizando
una medida de similaridad de distancias euclideas y el método de agrupación de
encadenamiento medio:

require(graphics)
str(USArrests)
## 'data.frame': 50 obs. of 4 variables:
## $ Murder : num 13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
## $ Assault : int 236 263 294 190 276 204 110 238 335 211 ...
## $ UrbanPop: int 58 48 80 50 91 78 77 72 80 60 ...
## $ Rape : num 21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9
25.8 ...
hc <- hclust(dist(USArrests), "ave")
plot(hc)

plot(hc, hang = -1)

Se realiza el mismo cluster Jerarquico, se establece una parada de 10 cluster (cutree), y


se realiza un nuevo cluster con los 10 conglomerados.

hc <- hclust(dist(USArrests)^2, "cen")


memb <- cutree(hc, k = 10)
cent <- NULL
for(k in 1:10){
cent <- rbind(cent, colMeans(USArrests[memb == k, , drop = FALSE]))
}
str(cent)
## num [1:10, 1:4] 11.47 13.5 9.95 11.5 5.59 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:4] "Murder" "Assault" "UrbanPop" "Rape"
hc1 <- hclust(dist(cent)^2, method = "cen", members = table(memb))
opar <- par(mfrow = c(1, 2))
plot(hc, labels = FALSE, hang = -1, main = "Original Tree")
plot(hc1, labels = FALSE, hang = -1, main = "Re-start from 10
clusters")
par(opar)

Determinar el número de cluster con k-means


Determinar el número de cluster o la regla de parada es una de las tareas más sensibles
en el AC, una forma de incluir un test para decidir el numero de conglomerados en utilizar
la función k-meas de R, y representar gráficamente el vector la suma de cuadrados entre
conglomerados (withniss), para diferentes agrupamientos.

d=dist(USArrests)^2

# Determinar el numero de cluster

# Fija semilla inicial de numeros pseudoaleatorios


# para obtener misma serie aleatoria en ejecuciones.
set.seed(123)

# Crea vector "Errores", sin datos


# Crea variable "K_Max" con la cant. maxima de k a analizar
Errores <-NULL
K_Max <-10

# Ejecuta kmeans con diferentes cluster, desde 1 hasta 10


# Luego guarda el error de cada ejecucion en el vector "Errores"
for (i in 1:K_Max)
{
Errores[i] <- sum(kmeans(d[-1], centers=i)$withinss)
}
# Grafica el vector "Errores"
plot(1:K_Max, Errores, type="b",
xlab="Cantidad de Cluster",
ylab="Suma de error")

Cluster Jerárquico de series temporales con DTW


La agrupación en series temporales consiste, como se apreció en el apartardo anterior, en
dividir el data-set de series temporales en grupos basados en similitudes o distancias, de
modo que las series temporales de un mismo grupo sean similares.
Para la agrupación de series de tiempo, el primer paso es elaborar una métrica de
distancia ó similitud apropiada, y luego, en el segundo paso, utilizar técnicas de agrupación
existentes, como k-means, clustering jerárquico, clustering basado en densidad o
clustering subespacial.
Para encontrar estructuras de agrupamiento, de series temporales una metrica adecuada
es la distancia Dynamic Time Warping (DTW), que encuentra la alineación óptima entre
dos series temporales.
El Alineamiento Temporal Dinámico (Dynamic Time Warping, DTW), es una técnica
desarrollada en el ambito de reconocimiento de la voz, cuyo objetivo es comparar dos
emisiones vocales aisladas a fin de determinar si corresponden o no a la misma palabra.
De manera resumida, el DTW se diseño para comprobar si existe una sincronización
temporal (alineamiento temporal) entre dos grupos fónicos. La falta de alineamiento, por lo
general, no obedece a una ley fija (p. e., un retardo constante), sino que se da de forma
heterogénea, produciéndose así variaciones localizadas que aumentan o disminuyen la
duración del tramo de análisis.
El problema de calcular una función de alineamiento se resuelve en el DTW mediante
técnicas de programación dinámica, motivo por el que se conoce a esta técnica como
alineamiento temporal dinámico.
En el ejemplo, se utiliza un conjunto de datos de la serie temporal de gráficos de control
sintético, que contiene 600 ejemplos de gráficos de control. Cada gráfico de control es una
serie de tiempo con 60 valores. Hay seis clases:

1. 1-100 Normal,
2. 101-200 Cíclico,
3. 201-300 Tendencia creciente,
4. 301-400 Tendencia decreciente,
5. 401-500 Cambio hacia arriba y
6. 501-600 Descenso cambio.

Los datos y el script se ha obtenido de :http://www.rdatamining.com/examples/time-series-


clustering-classification.

sc <-
read.table("http://kdd.ics.uci.edu/databases/synthetic_control/synthet
ic_control.data", header=F, sep="")
# randomly sampled n cases from each class, to make it easy for
plotting
n <- 10
s <- sample(1:100, n)
idx <- c(s, 100+s, 200+s, 300+s, 400+s, 500+s)
sample2 <- sc[idx,]
observedLabels <- c(rep(1,n), rep(2,n), rep(3,n), rep(4,n), rep(5,n),
rep(6,n))
# compute DTW distances
library(dtw)
## Loading required package: proxy
##
## Attaching package: 'proxy'
## The following objects are masked from 'package:stats':
##
## as.dist, dist
## The following object is masked from 'package:base':
##
## as.matrix
## Loaded dtw v1.18-1. See ?dtw for help, citation("dtw") for use in
publication.
distMatrix <- dist(sample2, method="DTW")
# hierarchical clustering
hc <- hclust(distMatrix, method="average")
plot(hc, labels=observedLabels, main="")

Cluster Jerárquico con span-tree


Si al clasificar un conjunto de datos no encontramos una decisión adecuada para
establecer una regla de parada, y obtenemos como resultado un conjunto inclasificable, es
util combinar la metodología de jerarquía y topología de los árboles de expansión mínima
(MST, Minimal Spanning Tree).
ado un grafo, su árbol mínimo generador (o árbol de peso mínimo o árbol mínimo de
expansión) es un árbol que pasa por todos los vértices y que la suma de sus aristas es la
de menor peso.
La gráfica siguiente ilustra el proceso, se trata de un arbol de expansión de 7 nodos
(acciones), con las medidas de distancia que hay entre ellos. Partiendo de la distancia
menor, 29, entre el nodo 8 y 4, se inicia el arbol, que en el nodo 4, encuentra la segunda
minima distancia en su enlace con el nodo 2, 31, y en el nodo 2, la menor distancia la
encuentra con el nodo 5, operando de esta manera hasta tener enlazados todos los nodos.
Como se puede observar en la figura, un nodo puede tener, más de un enlace con otros
nodos, tal y como ocurre en el gráfico, nodo 3.

Curva ROC
Basandonos en el trabajo pionero de Mantegna (1999) sobre tasas de retornos en los
mercados financieros, realizamos un ejercicio clasificatorio con la función span-tree, de la
librería vegan, que ordena y establece dependencias entre diversos activos financieros
utilizando datos de rendimientos mensuales de activos procedentes de Berndt’s The
Practice of Econometrics: http://web.stanford.edu/~clint/berndt/

# read prices from csv file


bolsa.df = load("berndt.RData")
colnames(berndt.df)
## [1] "Año" "MOBIL" "TEXACO" "IBM" "DEC" "DATGEN" "CONED"
## [8] "PSNH" "WEYER" "BOISE" "MOTOR" "TANDY" "PANAN" "DELTA"
## [15] "CONTIL" "CITGRP" "GERBER" "GENMIL" "MARKET" "RKFREE"
#[1] "Año" "MOBIL" "TEXACO" "IBM" "DEC" "DATGEN" "CONED"
"PSNH" "WEYER" "BOISE"
#[11] "MOTOR" "TANDY" "PANAN" "DELTA" "CONTIL" "CITGRP" "GERBER"
"GENMIL" "MARKET" "RKFREE

# create zooreg object - regularly spaced zoo object

library(zoo)
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
berndt.z = zooreg(berndt.df[,-1], start=c(1978, 1),
end=c(1987,12),frequency=12)
index(berndt.z) = as.yearmon(index(berndt.z))

start(berndt.z)
## [1] "ene. 1978"
end(berndt.z)
## [1] "dic. 1987"
nrow(berndt.z)
## [1] 120
# note: coredata() function extracts data from zoo object
returns.mat = as.matrix(coredata(berndt.z))

# create the correlation coefficients

coef.corr <- cor(returns.mat)


coef.d <- (1-coef.corr^2) # compute distance (Mantegna, 1998)

# hierarchical cluster whir hclust

d <- as.dist(as.matrix(coef.d)) # find distance matrix


#Function spantree finds a minimum spanning tree (MTA) connecting all
points, but disregarding dissimilarities that are at or above the
threshold or NA.

library(vegan)
## Loading required package: permute
## Loading required package: lattice
## This is vegan 2.4-3
tr <- spantree(d)
## Add tree to a metric scaling
plot(tr, cmdscale(d), type = "t")

## Find a configuration to display the tree neatly


plot(tr, type = "t")
## Initial stress : 0.10907
## stress after 2 iters: 0.06448

## Depths of nodes
depths <- spandepth(tr)
plot(tr, type = "t", label = depths)
## Initial stress : 0.10907
## stress after 2 iters: 0.06448

## Plot as a dendrogram
cl <- as.hclust(tr)
plot(cl)
 Potencia de R para el Análisis Factorial Confirmatorio (SEM)

 Carátula
 Presentación
 1 Introducción
 2 Primeros pasos en el Análisis
o 2.1 Importar datos y reconocer variables
o 2.2 Sintaxis de Lavaan (Especificación)
o 2.3 Identificación, Estimación y Evaluación
o 2.4 Re-Especificación
 Referencias

 Publicado en Github

Una guía amigable para el uso de Lavaan: Potencia de R para

el Análisis Factorial Confirmatorio (SEM)

2 Primeros pasos en el Análisis


Empezaremos con un primer análisis utulizando una base de datos de acceso libre y de
las más difundidas para el AFC. Se trata de la BD de Holzinger & Swineford (1939) que
recolecta información de una prueba de Habilidades Cognitivas conformado por 26 test
en séptimo y octavo grado de dos colegios diferentes (Pasteur y Grant-White). Para
este procedimiento se utilizará los datos recortados a 9 pruebas que se estructuran en 3
factores latentes: Visual, Textual y Velocidad.

Table 2.1: Estructura de la prueba de Holzinger & Swineford (1939).

Factores Indicadores

Factor Visual X1, X2 y X3

Factor Textual X4, X5 y X6

Factor Velocidad X7, X8 y X9

Es importante conocer la estructura propuesta del instrumento a analizar (Table  2.1)


debido a que el ajuste de los modelos calculados requieren tener un marco explicativo y
referencial.

2.1 Importar datos y reconocer variables


Empezaremos con algunas funciones sencillas que nos ayuden a entender la forma de
trabajo de R previo al flujo de análisis de AFC propiamente. En caso de no haber
cargado aún el paquete, o solo necesitar una función única del mismo, podrías
solicitarlo mediante la indicación:
package::function(...)
Lo indicado arriba estará solicitando una función function del paquete package de
forma específica. ¡Probemos!
# Solicitamos ver la BD
head(lavaan::HolzingerSwineford1939)
## id sex ageyr agemo school grade x1 x2 x3 x4 x5
## 1 1 1 13 1 Pasteur 7 3.333333 7.75 0.375 2.333333 5.75
## 2 2 2 13 7 Pasteur 7 5.333333 5.25 2.125 1.666667 3.00
## 3 3 2 13 1 Pasteur 7 4.500000 5.25 1.875 1.000000 1.75
## 4 4 1 13 2 Pasteur 7 5.333333 7.75 3.000 2.666667 4.50
## 5 5 2 12 2 Pasteur 7 4.833333 4.75 0.875 2.666667 4.00
## 6 6 2 14 1 Pasteur 7 5.333333 5.00 2.250 1.000000 3.00
## x6 x7 x8 x9
## 1 1.2857143 3.391304 5.75 6.361111
## 2 1.2857143 3.782609 6.25 7.916667
## 3 0.4285714 3.260870 3.90 4.416667
## 4 2.4285714 3.000000 5.30 4.861111
## 5 2.5714286 3.695652 6.30 5.916667
## 6 0.8571429 4.347826 6.65 7.500000
# ¡Quiero orden!
tibble::as_tibble(lavaan::HolzingerSwineford1939)
## # A tibble: 301 x 15
## id sex ageyr agemo scho… grade x1 x2 x3 x4 x5 x6
## <int> <int> <int> <int> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 1 13 1 Past… 7 3.33 7.75 0.375 2.33 5.75 1.29
## 2 2 2 13 7 Past… 7 5.33 5.25 2.12 1.67 3 1.29
## 3 3 2 13 1 Past… 7 4.5 5.25 1.88 1 1.75 0.429
## 4 4 1 13 2 Past… 7 5.33 7.75 3 2.67 4.5 2.43
## 5 5 2 12 2 Past… 7 4.83 4.75 0.875 2.67 4 2.57
## 6 6 2 14 1 Past… 7 5.33 5 2.25 1 3 0.857
## 7 7 1 12 1 Past… 7 2.83 6 1 3.33 6 2.86
## 8 8 2 12 2 Past… 7 5.67 6.25 1.88 3.67 4.25 1.29
## 9 9 2 13 0 Past… 7 4.5 5.75 1.5 2.67 5.75 2.71
## 10 11 2 12 5 Past… 7 3.5 5.25 0.75 2.67 5 2.57
## # ... with 291 more rows, and 3 more variables: x7 <dbl>, x8 <dbl>,
## # x9 <dbl>
Hemos realizado dos formas de poder visualizar los datos. Definitivamente la segunda
manera nos permite visualizar los datos de forma ordenada. Antes de ir al análisis,
necesitamos que R guarde estos datos en un objeto, es decir un nombre que permita
identificarlo (lo veremos en el ambiente [Environment]). Para ello necesitamos utilizar la
designación “<-” (alt + -) como lo veremos abajo.
# Guardaremos la BD
datos <- tibble::as_tibble( # Guardemos la BD en "data"
lavaan::HolzingerSwineford1939 # Esta es la BD
)
View(datos)
¡Muy bien! Lo hemos logrado. Si vemos al recuadro superior derecho, podemos ver que
en el entorno “ambiente” ahora aparece “data” indicando que posee 301 observaciones
y 15 variables. Podemos tener más información si lo que queremos es focalizarnos en
las variables. Podemos usar la función names para tener un listado de las variables de
un data.frame (BD) y la función glimpse del paquete dplyr para ver las propiedades de
las variables (además del listado del mismo).
names(datos) # Listado de variables
## [1] "id" "sex" "ageyr" "agemo" "school" "grade" "x1"
## [8] "x2" "x3" "x4" "x5" "x6" "x7" "x8"
## [15] "x9"
dplyr::glimpse(datos) # Listado y propiedades de variables
## Observations: 301
## Variables: 15
## $ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, ...
## $ sex <int> 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 1, 2...
## $ ageyr <int> 13, 13, 13, 13, 12, 14, 12, 12, 13, 12, 12, 12, 12, 12,...
## $ agemo <int> 1, 7, 1, 2, 2, 1, 1, 2, 0, 5, 2, 11, 7, 8, 6, 1, 11, 5,...
## $ school <fct> Pasteur, Pasteur, Pasteur, Pasteur, Pasteur, Pasteur, P...
## $ grade <int> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7...
## $ x1 <dbl> 3.333333, 5.333333, 4.500000, 5.333333, 4.833333, 5.333...
## $ x2 <dbl> 7.75, 5.25, 5.25, 7.75, 4.75, 5.00, 6.00, 6.25, 5.75, 5...
## $ x3 <dbl> 0.375, 2.125, 1.875, 3.000, 0.875, 2.250, 1.000, 1.875,...
## $ x4 <dbl> 2.333333, 1.666667, 1.000000, 2.666667, 2.666667, 1.000...
## $ x5 <dbl> 5.75, 3.00, 1.75, 4.50, 4.00, 3.00, 6.00, 4.25, 5.75, 5...
## $ x6 <dbl> 1.2857143, 1.2857143, 0.4285714, 2.4285714, 2.5714286, ...
## $ x7 <dbl> 3.391304, 3.782609, 3.260870, 3.000000, 3.695652, 4.347...
## $ x8 <dbl> 5.75, 6.25, 3.90, 5.30, 6.30, 6.65, 6.20, 5.15, 4.65, 4...
## $ x9 <dbl> 6.361111, 7.916667, 4.416667, 4.861111, 5.916667, 7.500...
¡Perfecto! Hemos cargado una base de datos y reconocido el contenido de los datos
que vamos a utilizar. ¡Estamos listos para empezar con la acción!

2.2 Sintaxis de Lavaan (Especificación)


Lo primero que haremos es especificar el modelo (estructura factorial) de la prueba tal y
como se encuentra indicado en la Tabla 2.1. ¿Cómo especificamos? ¡Simple! Solo
debemos indicarle a R qué variables forman los factores (variables latentes) y la
relación que hay entre los mismos. Para indicar las relaciones existentes se tiene las
siguientes indicaciones de la Tabla 2.2:

Table 2.2: Sintaxis para la Especificación en Lavaan.

Sintaxis Descripción

=~ Conformación de una variable latente

~ Regresión

~~ Co-varianza entre errores o varianza del indicador

~1 Interceptos

Para la especificación de un AFC nos interesa indicarle a R las variables latentes y su


conformación (=~) y la co-varianza entre los errores (~~) principalmente (o al menos por
el nivel básico explorado). ¡Vamos a ello!
# Se crea un objeto "model" donde se almacena la información
# acerca de la especificación del instrumento
model <- " visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 "
¡Así de simple! Se está creando un objeto llamado model que usaremos para solicitarle
a R que identifique el modelo y realice la estimación del mismo. Esta especificación
precisa que existen tres factores visual, textual y speed que se encuentran
conformados por 3 indicadores cada uno.
2.3 Identificación, Estimación y Evaluación
¡Ahora vamos a identificar y estimar! ¡Si! Los dos pasos al mismo tiempo utilizando la
función cfa del paquete lavaan.
# Cargamos el paquete
library(lavaan)
## This is lavaan 0.6-3
## lavaan is BETA software! Please report any bugs.
# Almacenamos en el objeto "fit" la información de la estimación
fit <- cfa(model = model,
data = datos)
¡Ya está! Veamos el entorno ambiente. Hemos creado un objeto adicional de
clase lavaan llamado fit. La función cfa es un wrapper de la función general lavaan, es
decir que automatiza una gran cantidad de especificaciones como las varianzas
individuales de las variables, correlaciones de errores establecidas a 0, y el hecho de
tratar a los factores especificados como oblicuos, es decir que se encuentra
correlacionados entre ellos. Dicho esta aclaración sobre lo que acabamos de hacer,
procederemos a verificar la evaluación de nuestro modelo factorial almacenado en  fit.
Para esto usaremos a la conocida función summary que nos devolverá de
forma organizada parte de lo estimado. ¡Hagámoslo!
summary(datos) ## ¡Ups! Nos confundimos, parece ser que hace eso mismo: ¡Resumir!
## id sex ageyr agemo
## Min. : 1.0 Min. :1.000 Min. :11 Min. : 0.000
## 1st Qu.: 82.0 1st Qu.:1.000 1st Qu.:12 1st Qu.: 2.000
## Median :163.0 Median :2.000 Median :13 Median : 5.000
## Mean :176.6 Mean :1.515 Mean :13 Mean : 5.375
## 3rd Qu.:272.0 3rd Qu.:2.000 3rd Qu.:14 3rd Qu.: 8.000
## Max. :351.0 Max. :2.000 Max. :16 Max. :11.000
##
## school grade x1 x2
## Grant-White:145 Min. :7.000 Min. :0.6667 Min. :2.250
## Pasteur :156 1st Qu.:7.000 1st Qu.:4.1667 1st Qu.:5.250
## Median :7.000 Median :5.0000 Median :6.000
## Mean :7.477 Mean :4.9358 Mean :6.088
## 3rd Qu.:8.000 3rd Qu.:5.6667 3rd Qu.:6.750
## Max. :8.000 Max. :8.5000 Max. :9.250
## NA's :1
## x3 x4 x5 x6
## Min. :0.250 Min. :0.000 Min. :1.000 Min. :0.1429
## 1st Qu.:1.375 1st Qu.:2.333 1st Qu.:3.500 1st Qu.:1.4286
## Median :2.125 Median :3.000 Median :4.500 Median :2.0000
## Mean :2.250 Mean :3.061 Mean :4.341 Mean :2.1856
## 3rd Qu.:3.125 3rd Qu.:3.667 3rd Qu.:5.250 3rd Qu.:2.7143
## Max. :4.500 Max. :6.333 Max. :7.000 Max. :6.1429
##
## x7 x8 x9
## Min. :1.304 Min. : 3.050 Min. :2.778
## 1st Qu.:3.478 1st Qu.: 4.850 1st Qu.:4.750
## Median :4.087 Median : 5.500 Median :5.417
## Mean :4.186 Mean : 5.527 Mean :5.374
## 3rd Qu.:4.913 3rd Qu.: 6.100 3rd Qu.:6.083
## Max. :7.435 Max. :10.000 Max. :9.250
##
## Muestrame acerca de lo estimado entonces
summary(fit)
## lavaan 0.6-3 ended normally after 35 iterations
##
## Optimization method NLMINB
## Number of free parameters 21
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 85.306
## Degrees of freedom 24
## P-value (Chi-square) 0.000
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|)
## visual =~
## x1 1.000
## x2 0.554 0.100 5.554 0.000
## x3 0.729 0.109 6.685 0.000
## textual =~
## x4 1.000
## x5 1.113 0.065 17.014 0.000
## x6 0.926 0.055 16.703 0.000
## speed =~
## x7 1.000
## x8 1.180 0.165 7.152 0.000
## x9 1.082 0.151 7.155 0.000
##
## Covariances:
## Estimate Std.Err z-value P(>|z|)
## visual ~~
## textual 0.408 0.074 5.552 0.000
## speed 0.262 0.056 4.660 0.000
## textual ~~
## speed 0.173 0.049 3.518 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## .x1 0.549 0.114 4.833 0.000
## .x2 1.134 0.102 11.146 0.000
## .x3 0.844 0.091 9.317 0.000
## .x4 0.371 0.048 7.779 0.000
## .x5 0.446 0.058 7.642 0.000
## .x6 0.356 0.043 8.277 0.000
## .x7 0.799 0.081 9.823 0.000
## .x8 0.488 0.074 6.573 0.000
## .x9 0.566 0.071 8.003 0.000
## visual 0.809 0.145 5.564 0.000
## textual 0.979 0.112 8.737 0.000
## speed 0.384 0.086 4.451 0.000
¡Que elegancia! No nos asustemos. Vamos a entenderlo paso a paso, de las manitos.
No nos soltemos. Respiremos y empecemos por la primera parte. Vemos que el “output”
(resultados en consola) nos indica la versión de “lavaan”, el número de parámetros
libres que tenemos en el modelo, número de casos analizados, método de estimación
utilizado (máxima verosimilitud), valor de chi cuadrado (Model Fit Test Statistic), grados
de libertad (sobre identificado), valor p de la prueba de bondad de ajuste (chi cuadrado)
e información adicional que por ahora no será de nuestra preocupación.

En el apartado de “Latent Variables” (Variables Latentes) podemos ver la estimación sin


estandarizar de los indicadores frente a la variable latente, erores estándares de la
estimación, valor Z y valor p del mismo. Con respecto al apartado “Covariances”, sigue
la misma estructura que arriba centrándose en las relaciones entre factores (variables
latentes). Recordemos que al usar la función “cfa” por defecto se configura en “oblicuo”
(factores correlacionados). Por último, en el apartado de las varianzas lo único de lo que
nos preocuparemos por ahora es el no encontrar valores estimados (no se encuentran
estadarizados) que sean positivos. En caso de encontrar uno negativo, estaremos frente
a un caso Heywood!

Es probable que esta explicación, a pesar de mantenerse de forma simple, te haya


parecido algo compleja. Es normal sentirlo de esa forma si recién estás teniendo
contacto con este tipo de análisis. Te alegrará saber que, aunque hay mucha
información para ver y revisar, a lo que debemos prestar atención es a los índices de
ajuste del modelo y a las estimaciones estandarizadas. Será lo principal. ¡Espera! ¿Y
donde se encuentra todo eso?

Calma, toda esta información se encuentra almacenada en el objeto “fit”, solo que al
momento de solicitar el “output” con la función “summary”, no hemos sido más precisos
en lo que queremos que nos muestre. Para las dos menciones que deseamos poder ver
y revisar usaremos dos argumentos adicionales. Si deseamos que se adicione la
información sobre índices de ajuste, la función quedará así:
summary(..., fit.measures = TRUE)
Si deseamos que se adicione información estandarizada, la función quedará así:
summary(..., standardized = TRUE)
Así, en caso de querer ambas cosas, solo hará falta poner esos dos argumentos en la
misma solicitud:
summary(..., fit.measures = TRUE, standardized = TRUE)
¡Probemos!
# Solicitar el resumen del análisis adicionando las medidas estandarizadas
# y los índices de ajuste
summary(fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-3 ended normally after 35 iterations
##
## Optimization method NLMINB
## Number of free parameters 21
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 85.306
## Degrees of freedom 24
## P-value (Chi-square) 0.000
##
## Model test baseline model:
##
## Minimum Function Test Statistic 918.852
## Degrees of freedom 36
## P-value 0.000
##
## User model versus baseline model:
##
## Comparative Fit Index (CFI) 0.931
## Tucker-Lewis Index (TLI) 0.896
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -3737.745
## Loglikelihood unrestricted model (H1) -3695.092
##
## Number of free parameters 21
## Akaike (AIC) 7517.490
## Bayesian (BIC) 7595.339
## Sample-size adjusted Bayesian (BIC) 7528.739
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.092
## 90 Percent Confidence Interval 0.071 0.114
## P-value RMSEA <= 0.05 0.001
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.065
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual =~
## x1 1.000 0.900 0.772
## x2 0.554 0.100 5.554 0.000 0.498 0.424
## x3 0.729 0.109 6.685 0.000 0.656 0.581
## textual =~
## x4 1.000 0.990 0.852
## x5 1.113 0.065 17.014 0.000 1.102 0.855
## x6 0.926 0.055 16.703 0.000 0.917 0.838
## speed =~
## x7 1.000 0.619 0.570
## x8 1.180 0.165 7.152 0.000 0.731 0.723
## x9 1.082 0.151 7.155 0.000 0.670 0.665
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual ~~
## textual 0.408 0.074 5.552 0.000 0.459 0.459
## speed 0.262 0.056 4.660 0.000 0.471 0.471
## textual ~~
## speed 0.173 0.049 3.518 0.000 0.283 0.283
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x1 0.549 0.114 4.833 0.000 0.549 0.404
## .x2 1.134 0.102 11.146 0.000 1.134 0.821
## .x3 0.844 0.091 9.317 0.000 0.844 0.662
## .x4 0.371 0.048 7.779 0.000 0.371 0.275
## .x5 0.446 0.058 7.642 0.000 0.446 0.269
## .x6 0.356 0.043 8.277 0.000 0.356 0.298
## .x7 0.799 0.081 9.823 0.000 0.799 0.676
## .x8 0.488 0.074 6.573 0.000 0.488 0.477
## .x9 0.566 0.071 8.003 0.000 0.566 0.558
## visual 0.809 0.145 5.564 0.000 1.000 1.000
## textual 0.979 0.112 8.737 0.000 1.000 1.000
## speed 0.384 0.086 4.451 0.000 1.000 1.000
Está bien, no hay problema. Solo se agregaron unas líneas más al “output”. ¡Podemos
manejarlo! En la primera parte del “output” se adicionó cuatro de los índices de ajuste
más comunes: CFI (>= .95), TLI (>= .95), RMSEA (<= .05) y SRMR (<= .06).

Estos índices de ajuste nos permitirán decidir si, el modelo tal y como se encuentra
especificado guarda coherencia estadística. En la parte de abajo (Latent Variables,
Covariances y Variances) se ha agregado dos columnas  Std.lv y Std.all. Nosotros nos
concentraremos en “Std.all” debido a que representa la estimación estandarizada a todo
el modelo (varía entre -1 y 1). Mientras más alto mejor.

Antes de pasar a ver como podemos mejorar nuestro modelo ya que presenta valores
en sus ajustes que no llegan a ser del todo satisfactorios, veremos otra forma de
visualizar los resultados que puede ser un tanto más amigable.
2.4 Re-Especificación
Vemaos como mejorar nuestro modelo ya que presenta valores en sus ajustes que no
llegan a ser del todo satisfactorios. En este punto, la reflexión teórica debería darnos
algunas pistas sobre el mal funcionamiento de algunos ítems, pertenencia a otro factor
o presencia de correlación de errores por un mismo comienzo en el enunciado.

Los índices de modificación son valores que nos brindarán una orientación acerca de


la re-especificación de la estructura factorial evaluada inicialmente. Para ello usaremos
la siguiente función:
`modificationindices(fit)`
Veremos también cómo ver solo una parte de los IM (los más representativos)
# Solicitar los 10 primeros IM con valores más altos
modindices(fit, sort = TRUE, maximum.number = 10)
## lhs op rhs mi epc sepc.lv sepc.all sepc.nox
## 30 visual =~ x9 36.411 0.577 0.519 0.515 0.515
## 76 x7 ~~ x8 34.145 0.536 0.536 0.859 0.859
## 28 visual =~ x7 18.631 -0.422 -0.380 -0.349 -0.349
## 78 x8 ~~ x9 14.946 -0.423 -0.423 -0.805 -0.805
## 33 textual =~ x3 9.151 -0.272 -0.269 -0.238 -0.238
## 55 x2 ~~ x7 8.918 -0.183 -0.183 -0.192 -0.192
## 31 textual =~ x1 8.903 0.350 0.347 0.297 0.297
## 51 x2 ~~ x3 8.532 0.218 0.218 0.223 0.223
## 59 x3 ~~ x5 7.858 -0.130 -0.130 -0.212 -0.212
## 26 visual =~ x5 7.441 -0.210 -0.189 -0.147 -0.147
Los índices de modificación representan la disminución en el valor de chi-cuadrado que
se produciría en caso se realizará lo sugerido. ¿Cómo saber cuando es importante? Va
a depender de cada análisis, es distinto un modelo estructural con chi-cuadrado de
1500 de valor que presenta IM de 35 puntos; que un modelo estructural de chi-cuadrado
65 con el mismo valor en IM.

Esta información se adiciona al “expected parameter change” (epc) y su valor


estandarizado (sepc.all) para tener mayor noción del cambio a nivel estadístico que se
realizaría.

Antes de hacer caso a la sugerencia propuesta, RECORDAR, siempre debe primar el


criterio metodológico. En caso de sugerir correlación de errores entre ítems, seguir
estas sugerencias:

a. Buscar similitud en el contenido de ambos ítems que pueda haber propiciado


una similar forma de producir error en la medición.
b. Verificar si los ítems comparten una misma forma de finalizar o iniciar el
enunciado.
c. Si los items pertenecen a diferentes factores, tener mucho cuidado. Existe la
posibilidad de que lo señalado como sugerencia solo se deba a aleatoridad en los
datos. Si es que pese a ello se encontrase relación o motivos para suponer errores
correlacionados entre dichos ítems, poner en alerta la integridad de la estructura
factorial de la prueba.

Con respecto a las sugerencias de que un ítem pertenezca a otro factor, tener en
cuenta los siguientes puntos:

a. Existe la posibilidad de que un ítem verdaderamente deba pertenecer a otro


factor. Generalmente sucede esto en pruebas nuevas o con pocos estudios
psicométricos.
b. De igual manera a la anterior condición, su señalamiento puede deberse a pura
aleatoridad estadística.
c. Si un mismo ítem aparece repetidamente en los IM y se sugiere que podría
suponer un cambio importante en chi-cuadrado si se realizase la sugerencia, se debe
tener en alerta a dicho ítem. Su exclusión del análisis puede mejorar la estructura
factorial.

Dicho lo anterior verificamos que los IM sugieren que habría un cambio de 36 puntos
menos en el chi-cuadrado (valor actual de 85.3) si se modificase su pertenencia al
factor visual. Mientras que si se correlaciona los errores del indicador 7 y 8, habría un
cambio de 34.15, además de que la correlación sería de 0.86 (sepc.all).

Recordemos que cada vez que se realiza una re-especificación en el modelo los IM
cambian debido a que el ajuste del modelo también cambia. Así que no se recomienda
hacer múltiples re-especificaciones a partir de un solo procedimiento de análisis para re-
especificar. De uno en uno o de dos en dos si las incongruencias son más claras.

Para efectos de aprendizaje, incluiremos una correlación de errores entre el indicador 7


y 8 para ver cómo se produce los cambios. Previo a ello guardaremos los índices de
ajuste en un objeto que servirá para ir comparando los cambios realizados.
# Procederemos a re-especificar creando un objeto con nombre "model_02"
model_02 <- " # Modelo de medición
visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9
# Correlación de errores
x7 ~~ x8
"
Hemos agregado la re-especificación de la correlación entre errores.  ¡Estimemos
nuevamente y veamos los resultados!
# Procederemos a re-especificar creando un objeto con nombre "model_02"
fit_02 <- cfa(model = model_02,
data = datos)
summary(fit_02, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-3 ended normally after 43 iterations
##
## Optimization method NLMINB
## Number of free parameters 22
##
## Number of observations 301
##
## Estimator ML
## Model Fit Test Statistic 53.272
## Degrees of freedom 23
## P-value (Chi-square) 0.000
##
## Model test baseline model:
##
## Minimum Function Test Statistic 918.852
## Degrees of freedom 36
## P-value 0.000
##
## User model versus baseline model:
##
## Comparative Fit Index (CFI) 0.966
## Tucker-Lewis Index (TLI) 0.946
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -3721.728
## Loglikelihood unrestricted model (H1) -3695.092
##
## Number of free parameters 22
## Akaike (AIC) 7487.457
## Bayesian (BIC) 7569.013
## Sample-size adjusted Bayesian (BIC) 7499.242
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.066
## 90 Percent Confidence Interval 0.043 0.090
## P-value RMSEA <= 0.05 0.118
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.047
##
## Parameter Estimates:
##
## Information Expected
## Information saturated (h1) model Structured
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## visual =~
## x1 1.000 0.885 0.759
## x2 0.576 0.098 5.898 0.000 0.509 0.433
## x3 0.752 0.103 7.289 0.000 0.665 0.589
## textual =~
## x4 1.000 0.989 0.851
## x5 1.115 0.066 17.015 0.000 1.103 0.856
## x6 0.926 0.056 16.682 0.000 0.916 0.838
## speed =~
## x7 1.000 0.383 0.352
## x8 1.244 0.194 6.414 0.000 0.477 0.471
## x9 2.515 0.641 3.924 0.000 0.963 0.956
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x7 ~~
## .x8 0.353 0.067 5.239 0.000 0.353 0.389
## visual ~~
## textual 0.400 0.073 5.511 0.000 0.457 0.457
## speed 0.184 0.054 3.423 0.001 0.544 0.544
## textual ~~
## speed 0.102 0.036 2.854 0.004 0.270 0.270
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .x1 0.576 0.101 5.678 0.000 0.576 0.424
## .x2 1.122 0.100 11.171 0.000 1.122 0.812
## .x3 0.832 0.087 9.552 0.000 0.832 0.653
## .x4 0.372 0.048 7.791 0.000 0.372 0.276
## .x5 0.444 0.058 7.600 0.000 0.444 0.267
## .x6 0.357 0.043 8.287 0.000 0.357 0.298
## .x7 1.036 0.090 11.501 0.000 1.036 0.876
## .x8 0.795 0.080 9.988 0.000 0.795 0.778
## .x9 0.088 0.188 0.466 0.641 0.088 0.086
## visual 0.783 0.135 5.810 0.000 1.000 1.000
## textual 0.978 0.112 8.729 0.000 1.000 1.000
## speed 0.147 0.056 2.615 0.009 1.000 1.000
A simple vista podemos ver una mejora importante en los índices de ajuste del modelo
estimado. Ordenemos los datos y veamoslo en paralelo para entenderlo mejor.
# Guardando los índices en objetos
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
fit_index <- broom::glance(fit) %>%
select(chisq, npar, cfi, tli, rmsea, rmsea.conf.high, srmr, aic, bic,
estimator)
fit_index02 <- broom::glance(fit_02) %>%
select(chisq, npar, cfi, tli, rmsea, rmsea.conf.high, srmr, aic, bic,
estimator)
# Uniendo
bind_rows(fit_index, fit_index02, .id = "Modelo")
## # A tibble: 2 x 11
## Modelo chisq npar cfi tli rmsea rmsea.conf.high srmr aic bic
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 85.3 21 0.931 0.896 0.0921 0.114 0.0652 7517. 7595.
## 2 2 53.3 22 0.966 0.946 0.0661 0.0895 0.0471 7487. 7569.
## # ... with 1 more variable: estimator <chr>
¡Listo! Estamos viendo que el modelo 2 muestra una mejora importante en la estructura
factorial de la prueba. Es decir, tener en consideración que los errores de
indicador 7 y 8 se encuentran correlacionados permite un mejor ajuste en lo mostrado
por la matriz de covarianza empírica y la teórica (especificado).

Antes de cantar victoria, volvamos a verificar los IM para ver si hay más cambios
importantes sugeridos al modelo.
# Solicitar los 10 primeros IM con valores más altos
modindices(fit_02, sort = TRUE, maximum.number = 10)
## lhs op rhs mi epc sepc.lv sepc.all sepc.nox
## 34 textual =~ x3 9.057 -0.257 -0.254 -0.225 -0.225
## 32 textual =~ x1 8.734 0.313 0.309 0.265 0.265
## 60 x3 ~~ x5 8.712 -0.136 -0.136 -0.223 -0.223
## 67 x4 ~~ x7 8.117 0.112 0.112 0.181 0.181
## 56 x2 ~~ x7 7.266 -0.160 -0.160 -0.148 -0.148
## 52 x2 ~~ x3 6.536 0.181 0.181 0.187 0.187
## 27 visual =~ x5 6.076 -0.191 -0.169 -0.131 -0.131
## 29 visual =~ x7 5.438 -0.231 -0.204 -0.188 -0.188
## 66 x4 ~~ x6 5.367 -0.222 -0.222 -0.609 -0.609
## 30 visual =~ x8 5.049 0.276 0.244 0.242 0.242
Genial, parece ser que los IM mostrados no son tan altos ni el  sepc.all representa un
cambio importante al modelo estimado. Tenemos entonces un modelo estructural
comprobado… ¡Espera! ¿Hemos revisado la distribución de los datos? Ups…
Verifiquemos si se tiene una distribución normal multivariada. Para ello usaremos la
función “mvn” del paquete “MVN”.

También podría gustarte