Modelo de medida

Pasos que se van a dar.

Lectura de datos

Los datos están en un fichero dta de Stata, los podemos leer en R utilizando la librería foreign. De paso obtenemos un breve summary de las variables que nos interesan para el modelo de medida

library(foreign)
datos <- read.dta("data/paper3_seleccionvars.dta")
names(datos) <- tolower(names(datos))  # pasamos a minúsculas los nombres de las variables

Creamos vectores con los nombres de las variables que nos interesan

var.str <- c(paste("c3_", 1:3, sep = ""), "csc")
var.trust <- c(paste("d4_", 2:3, sep = ""), "d1", "d2", paste("r1_", 1:3, sep = ""))
var.confgov <- paste("d6_", 1:4, sep = "")

Resumen de las variables para structural

summary(datos[, var.str])
##       c3_1           c3_2           c3_3           csc      
##  Min.   :1.00   Min.   :1.00   Min.   :1.00   Min.   :0.00  
##  1st Qu.:1.00   1st Qu.:1.00   1st Qu.:1.00   1st Qu.:1.00  
##  Median :2.00   Median :1.00   Median :1.00   Median :1.00  
##  Mean   :2.47   Mean   :1.46   Mean   :1.59   Mean   :1.46  
##  3rd Qu.:4.00   3rd Qu.:1.00   3rd Qu.:2.00   3rd Qu.:2.00  
##  Max.   :5.00   Max.   :5.00   Max.   :5.00   Max.   :4.00

for (i in 1:length(var.str)) hist(datos[, var.str[i]], main = var.str[i], xlab = "")

plot of chunk unnamed-chunk-3 plot of chunk unnamed-chunk-3 plot of chunk unnamed-chunk-3 plot of chunk unnamed-chunk-3

Resumen de las variables trust

summary(datos[, var.trust])
##       d4_2           d4_3            d1             d2      
##  Min.   :1.00   Min.   :1.00   Min.   :1.00   Min.   :1.00  
##  1st Qu.:4.00   1st Qu.:3.00   1st Qu.:3.00   1st Qu.:3.00  
##  Median :4.00   Median :4.00   Median :4.00   Median :4.00  
##  Mean   :4.41   Mean   :3.91   Mean   :3.49   Mean   :3.67  
##  3rd Qu.:5.00   3rd Qu.:4.00   3rd Qu.:4.00   3rd Qu.:4.00  
##  Max.   :5.00   Max.   :5.00   Max.   :5.00   Max.   :5.00  
##       r1_1           r1_2           r1_3     
##  Min.   :1.00   Min.   :1.00   Min.   :1.00  
##  1st Qu.:3.00   1st Qu.:3.00   1st Qu.:2.00  
##  Median :4.00   Median :4.00   Median :3.00  
##  Mean   :3.69   Mean   :3.68   Mean   :2.88  
##  3rd Qu.:4.00   3rd Qu.:4.00   3rd Qu.:4.00  
##  Max.   :5.00   Max.   :5.00   Max.   :5.00

for (i in 1:length(var.trust)) hist(datos[, var.trust[i]], main = var.trust[i], 
    xlab = "")

plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4 plot of chunk unnamed-chunk-4

Resumen de las variables confgov

summary(datos[, var.confgov])
##       d6_1          d6_2           d6_3          d6_4     
##  Min.   :1.0   Min.   :1.00   Min.   :1.0   Min.   :1.00  
##  1st Qu.:2.0   1st Qu.:2.00   1st Qu.:2.0   1st Qu.:2.00  
##  Median :3.0   Median :3.00   Median :3.0   Median :3.00  
##  Mean   :3.1   Mean   :2.86   Mean   :3.1   Mean   :2.56  
##  3rd Qu.:4.0   3rd Qu.:4.00   3rd Qu.:4.0   3rd Qu.:3.00  
##  Max.   :5.0   Max.   :5.00   Max.   :5.0   Max.   :5.00  
##                NA's   :287                  NA's   :154

for (i in 1:length(var.confgov)) hist(datos[, var.confgov[i]], main = var.confgov[i], 
    xlab = "")

plot of chunk unnamed-chunk-5 plot of chunk unnamed-chunk-5 plot of chunk unnamed-chunk-5 plot of chunk unnamed-chunk-5

Análisis factorial exploratorio

Efectuamos un análisis factorial exploratorio sobre todas las variables, para ver si emergen los constructos de forma natural. En R hay multitud de paquetes que realizan el análisis factorial. Voy a utilizar el paquete psych.

Lo primero que hacemos es calcular la matriz de correlaciones y dibujarla ordenando sus valores

library(psych)
correlaciones <- cor(datos[, c(var.str, var.trust, var.confgov)], use = "pairwise")
cor.plot(mat.sort(correlaciones))
## Loading required package: MASS

plot of chunk AFE

En el gráfico se aprecia claramente el factor structural, cuyas variables presentan nula o muy poca correlación con las variables de otros factores

El factor confgov (esquina superior derecha) también se aprecia claramente y se intuyen correlaciones con el factor trust ( en el medio ), posibles regresiones a tener en cuenta.

Por último el factor trust es más difuso. Quizá sobre alguna variable o sean dos factores en vez de uno. El análisis factorial confirmatorio podría darnos más pistas

La función fa del paquete psych ofrece múltiples opciones para realizar el análisis factorial exploratorio. Veamos la más común, consistente en un análisis sin rotación mediante el método de principal axis. Elegimos 5 factores y veamos el screeplot de los valores propios para elegir un número de factores.

fit.pa5 <- fa(datos[, c(var.str, var.trust, var.confgov)], nfactors = 5, rotate = "none", 
    fm = "pa")
# veamos las cargas factoriales
fit.pa5$loadings
## 
## Loadings:
##      PA1    PA2    PA3    PA4    PA5   
## c3_1  0.168  0.540  0.183              
## c3_2         0.555  0.210  0.131       
## c3_3         0.483  0.285              
## csc          0.666  0.318              
## d4_2  0.455  0.220 -0.279 -0.183  0.428
## d4_3  0.674  0.207 -0.421 -0.273       
## d1    0.495  0.118 -0.157        -0.123
## d2    0.584  0.119 -0.342 -0.209 -0.368
## r1_1  0.403        -0.186  0.363       
## r1_2  0.437  0.125 -0.117  0.381       
## r1_3  0.400        -0.185  0.428       
## d6_1  0.587 -0.246  0.319              
## d6_2  0.648 -0.234  0.398 -0.107       
## d6_3  0.575 -0.332  0.321              
## d6_4  0.527 -0.239  0.316              
## 
##                  PA1   PA2   PA3   PA4   PA5
## SS loadings    3.180 1.698 1.202 0.650 0.364
## Proportion Var 0.212 0.113 0.080 0.043 0.024
## Cumulative Var 0.212 0.325 0.405 0.449 0.473
plot(fit.pa5$e.values, type = "b", col = "darkred", lwd = 2, lty = 2, main = "Scree plot")
abline(h = 1)

plot of chunk unnamed-chunk-6

En primer lugar vemos las cargas factoriales que nos dan una idea de en qué factor carga cada variable. También obtenemos la varianza explicada por cada factor y vemos que con 3 factores se explica el 40,5% de las variabilidad y con 4 el 44,9%.

El gráfico del análisis sería

diagram(fit.pa5, e.size = 0.1)

plot of chunk unnamed-chunk-7

Se observa claramente el factor structural , pero las variables que componen los otros dos factores o constructos cargan en el mismo factor. Lo que confirma el análisis de las correlaciones.

Ahora bien, podemos utilizar rotación varimax y seleccionar 3 componentes

fit.pa4 <- fa(datos[, c(var.str, var.trust, var.confgov)], nfactors = 3, rotate = "varimax", 
    fm = "pa")  # necesita paquete GPArotation
## Loading required package: GPArotation

diagram(fit.pa4, e.size = 0.1)

plot of chunk unnamed-chunk-8

Si seleccionamos 4 factores como indicaba el scree plot y rotamos la solución tenemos

fit.pa3 <- fa(datos[, c(var.str, var.trust, var.confgov)], nfactors = 4, rotate = "varimax", 
    fm = "pa")  # necesita paquete GPArotation

diagram(fit.pa3, e.size = 0.1)

plot of chunk unnamed-chunk-9

El análisis factorial exploratorio nos indica que nuestros constructos son correctos,pero quizá haya otro más con las variables r1_1, r1_2, r1_3 ¿Tiene sentido teórico?

Modelo de medida

\( \alpha \) de Cronbach

la función alpha del paquete psych

alpha(datos[, var.str])
## 
## Reliability analysis   
## Call: alpha(x = datos[, var.str])
## 
##   raw_alpha std.alpha G6(smc) average_r mean   sd
##        0.7      0.71    0.66      0.38  1.7 0.81
## 
##  Reliability if an item is dropped:
##      raw_alpha std.alpha G6(smc) average_r
## c3_1      0.65      0.66    0.58      0.39
## c3_2      0.63      0.66    0.57      0.39
## c3_3      0.65      0.68    0.58      0.41
## csc       0.60      0.60    0.51      0.34
## 
##  Item statistics 
##         n    r r.cor r.drop mean   sd
## c3_1  998 0.72  0.57   0.48  2.5 1.38
## c3_2  998 0.73  0.58   0.49  1.5 1.00
## c3_3  998 0.70  0.55   0.44  1.6 1.13
## csc   998 0.78  0.68   0.56  1.5 0.89
## 
## Non missing response frequency for each item
##         0    1    2    3    4    5 miss
## c3_1 0.00 0.34 0.24 0.14 0.19 0.10    0
## c3_2 0.00 0.78 0.09 0.04 0.06 0.03    0
## c3_3 0.00 0.73 0.10 0.05 0.07 0.04    0
## csc  0.12 0.44 0.33 0.10 0.02 0.00    0
alpha(datos[, var.trust])
## 
## Reliability analysis   
## Call: alpha(x = datos[, var.trust])
## 
##   raw_alpha std.alpha G6(smc) average_r mean   sd
##       0.73      0.74    0.75      0.29  3.7 0.51
## 
##  Reliability if an item is dropped:
##      raw_alpha std.alpha G6(smc) average_r
## d4_2      0.72      0.72    0.71      0.30
## d4_3      0.67      0.67    0.65      0.25
## d1        0.70      0.71    0.72      0.29
## d2        0.69      0.70    0.69      0.28
## r1_1      0.71      0.72    0.72      0.30
## r1_2      0.71      0.72    0.72      0.30
## r1_3      0.72      0.73    0.73      0.31
## 
##  Item statistics 
##         n    r r.cor r.drop mean   sd
## d4_2  998 0.59  0.50   0.40  4.4 0.63
## d4_3  998 0.75  0.75   0.59  3.9 0.82
## d1    998 0.63  0.53   0.45  3.5 0.86
## d2    998 0.66  0.61   0.50  3.7 0.73
## r1_1  998 0.59  0.48   0.42  3.7 0.80
## r1_2  998 0.59  0.48   0.42  3.7 0.92
## r1_3  998 0.56  0.44   0.38  2.9 0.97
## 
## Non missing response frequency for each item
##         1    2    3    4    5 miss
## d4_2 0.00 0.00 0.06 0.46 0.48    0
## d4_3 0.00 0.04 0.25 0.46 0.25    0
## d1   0.02 0.12 0.29 0.50 0.07    0
## d2   0.00 0.07 0.25 0.60 0.08    0
## r1_1 0.01 0.11 0.15 0.65 0.08    0
## r1_2 0.01 0.14 0.13 0.58 0.13    0
## r1_3 0.03 0.41 0.24 0.29 0.03    0
alpha(datos[, var.confgov])
## 
## Reliability analysis   
## Call: alpha(x = datos[, var.confgov])
## 
##   raw_alpha std.alpha G6(smc) average_r mean   sd
##       0.82      0.82    0.79      0.54  2.6 0.87
## 
##  Reliability if an item is dropped:
##      raw_alpha std.alpha G6(smc) average_r
## d6_1      0.78      0.78    0.71      0.55
## d6_2      0.75      0.75    0.67      0.50
## d6_3      0.77      0.77    0.71      0.53
## d6_4      0.80      0.80    0.74      0.57
## 
##  Item statistics 
##         n    r r.cor r.drop mean  sd
## d6_1  998 0.80  0.71   0.63  3.1 1.1
## d6_2  711 0.84  0.78   0.70  2.9 1.1
## d6_3  998 0.81  0.72   0.65  3.1 1.0
## d6_4  844 0.78  0.66   0.60  2.6 1.1
## 
## Non missing response frequency for each item
##         1    2    3    4    5 miss
## d6_1 0.10 0.19 0.28 0.38 0.06 0.00
## d6_2 0.14 0.23 0.30 0.31 0.03 0.29
## d6_3 0.09 0.17 0.30 0.41 0.02 0.00
## d6_4 0.19 0.29 0.29 0.21 0.01 0.15

Los \( \alpha \) son mayores que 0.7 en todas las escalas

Análisis factorial confirmatorio

Para el análisis factorial confirmatorio vamos a utilizar el paquete lavaan (latent variable analysis)

Primero especificamos el modelo inicial

library(lavaan)
## Loading required package: boot
## Attaching package: 'boot'
## The following object(s) are masked from 'package:psych':
## 
## logit
## Loading required package: mnormt
## Loading required package: quadprog
## This is lavaan 0.5-10
## lavaan is BETA software! Please report any bugs.
# cargo algunas funciones mias útiles, que añaden por ejemplo más medidas
# de bondad de ajuste
source("../codigos_utiles/funciones_utiles.R")

modelo <- "\nstructural =~ c3_1 + c3_2 +c3_3 + csc\ntrust =~  d4_2 + d4_3 +d1 + d2  + r1_1 + r1_2 + r1_3\nconf.gov =~ d6_1 + d6_2 + d6_3 + d6_4\n"
fit.cfa1 <- cfa(modelo, data = datos, std.lv = T, std.ov = T)
# Con std.lv=T le digo que estandarice la métrica de la latente.  con
# std.ov=T le digo que estandarice las variables antes del análisis es
# decir que trabaje con la matriz de correlaciones en vez de covarianzas

La especificación del modelo no se ve bien, \n indica salto de línea lo pongo tal como se ha escrito en el código

modelo <- "
structural =~ c3_1 + c3_2 +c3_3 + csc
trust =~  d4_2 + d4_3 +d1 + d2  + r1_1 + r1_2 + r1_3
conf.gov =~ d6_1 + d6_2 + d6_3 + d6_4
"

Un resumen numérico del modelo sería

summary(fit.cfa1, fit.measures = TRUE)
## lavaan (0.5-10) converged normally after  21 iterations
## 
##                                                   Used       Total
##   Number of observations                           641         998
## 
##   Estimator                                         ML
##   Minimum Function Chi-square                  379.280
##   Degrees of freedom                                87
##   P-value                                        0.000
## 
## Chi-square test baseline model:
## 
##   Minimum Function Chi-square                 2696.727
##   Degrees of freedom                               105
##   P-value                                        0.000
## 
## Full model versus baseline model:
## 
##   Comparative Fit Index (CFI)                    0.887
##   Tucker-Lewis Index (TLI)                       0.864
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)             -12476.865
##   Loglikelihood unrestricted model (H1)     -12287.225
## 
##   Number of free parameters                         33
##   Akaike (AIC)                               25019.729
##   Bayesian (BIC)                             25167.009
##   Sample-size adjusted Bayesian (BIC)        25062.236
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.072
##   90 Percent Confidence Interval          0.065  0.080
##   P-value RMSEA <= 0.05                          0.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.056
## 
## Parameter estimates:
## 
##   Information                                 Expected
##   Standard Errors                             Standard
## 
##                    Estimate  Std.err  Z-value  P(>|z|)
## Latent variables:
##   structural =~
##     c3_1              0.558    0.043   13.087    0.000
##     c3_2              0.621    0.042   14.661    0.000
##     c3_3              0.566    0.043   13.285    0.000
##     csc               0.766    0.042   18.100    0.000
##   trust =~
##     d4_2              0.532    0.040   13.274    0.000
##     d4_3              0.830    0.036   22.951    0.000
##     d1                0.562    0.040   14.148    0.000
##     d2                0.717    0.038   19.040    0.000
##     r1_1              0.395    0.042    9.505    0.000
##     r1_2              0.443    0.041   10.783    0.000
##     r1_3              0.326    0.042    7.744    0.000
##   conf.gov =~
##     d6_1              0.748    0.037   20.311    0.000
##     d6_2              0.788    0.036   21.731    0.000
##     d6_3              0.725    0.037   19.502    0.000
##     d6_4              0.660    0.038   17.297    0.000
## 
## Covariances:
##   structural ~~
##     trust             0.117    0.050    2.350    0.019
##     conf.gov          0.040    0.050    0.789    0.430
##   trust ~~
##     conf.gov          0.420    0.041   10.222    0.000
## 
## Variances:
##     c3_1              0.687    0.046
##     c3_2              0.613    0.045
##     c3_3              0.678    0.046
##     csc               0.411    0.046
##     d4_2              0.715    0.044
##     d4_3              0.310    0.033
##     d1                0.683    0.042
##     d2                0.485    0.036
##     r1_1              0.842    0.049
##     r1_2              0.802    0.047
##     r1_3              0.892    0.051
##     d6_1              0.439    0.034
##     d6_2              0.377    0.032
##     d6_3              0.473    0.034
##     d6_4              0.563    0.037
##     structural        1.000
##     trust             1.000
##     conf.gov          1.000

Vemos qeu los coeficientes sensiblemente menores de 0.6 son los asociados a las variables r1_1 r1_2 r1_3 Las medidas de ajuste serían

medidasAjuste(fit.cfa1)
##             chisq                df            pvalue    baseline.chisq 
##           379.280            87.000             0.000          2696.727 
##       baseline.df   baseline.pvalue               cfi               tli 
##           105.000             0.000             0.887             0.864 
##              logl unrestricted.logl              npar               aic 
##        -12476.865        -12287.225            33.000         25019.729 
##               bic            ntotal              bic2             rmsea 
##         25167.009           641.000         25062.236             0.072 
##    rmsea.ci.lower    rmsea.ci.upper      rmsea.pvalue              srmr 
##             0.065             0.080             0.000             0.056 
##       srmr_nomean               nfi              sncp              ecvi 
##             0.056             0.859             0.456             0.649 
##               gfi              agfi              pgfi              pnfi 
##             0.925             0.896             0.766             0.712

Gráficamente

# diagrama es una función mía que envuelve a diagram y a lavaan.diagram
diagrama(fit.cfa1, e.size = 0.06)

plot of chunk unnamed-chunk-14

No es un modelo malo y se podría mejorar mirando los índices de modificación , que nos indican que posible relación se podría modelar para incrementar el ajuste. No obstante, vamos a probar primero sacando las variables r en otro constructo, tal como parecía indicar el factorial exploratorio y los bajos coeficientes.

modelo <- "\nstructural =~ c3_1 + c3_2 +c3_3 + csc\ntrust =~  d4_2 + d4_3 +d1 + d2\nnueva =~ r1_1 + r1_2 + r1_3\nconf.gov =~ d6_1 + d6_2 + d6_3 + d6_4\n"
fit.cfa2 <- cfa(modelo, data = datos, std.lv = T, std.ov = T)

Pongo la especificación de fit.cfa2, para que se vea mejor

modelo <- "
structural =~ c3_1 + c3_2 +c3_3 + csc
trust =~  d4_2 + d4_3 +d1 + d2
nueva =~ r1_1 + r1_2 + r1_3
conf.gov =~ d6_1 + d6_2 + d6_3 + d6_4
"

Resumen del modelo

summary(fit.cfa2, fit.measures = TRUE)
## lavaan (0.5-10) converged normally after  20 iterations
## 
##                                                   Used       Total
##   Number of observations                           641         998
## 
##   Estimator                                         ML
##   Minimum Function Chi-square                  252.872
##   Degrees of freedom                                84
##   P-value                                        0.000
## 
## Chi-square test baseline model:
## 
##   Minimum Function Chi-square                 2696.727
##   Degrees of freedom                               105
##   P-value                                        0.000
## 
## Full model versus baseline model:
## 
##   Comparative Fit Index (CFI)                    0.935
##   Tucker-Lewis Index (TLI)                       0.919
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)             -12413.660
##   Loglikelihood unrestricted model (H1)     -12287.225
## 
##   Number of free parameters                         36
##   Akaike (AIC)                               24899.321
##   Bayesian (BIC)                             25059.990
##   Sample-size adjusted Bayesian (BIC)        24945.692
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.056
##   90 Percent Confidence Interval          0.048  0.064
##   P-value RMSEA <= 0.05                          0.102
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.044
## 
## Parameter estimates:
## 
##   Information                                 Expected
##   Standard Errors                             Standard
## 
##                    Estimate  Std.err  Z-value  P(>|z|)
## Latent variables:
##   structural =~
##     c3_1              0.558    0.043   13.079    0.000
##     c3_2              0.620    0.042   14.643    0.000
##     c3_3              0.566    0.043   13.289    0.000
##     csc               0.767    0.042   18.111    0.000
##   trust =~
##     d4_2              0.546    0.040   13.775    0.000
##     d4_3              0.881    0.036   24.434    0.000
##     d1                0.534    0.040   13.430    0.000
##     d2                0.711    0.038   18.816    0.000
##   nueva =~
##     r1_1              0.600    0.046   13.017    0.000
##     r1_2              0.668    0.047   14.303    0.000
##     r1_3              0.506    0.046   11.004    0.000
##   conf.gov =~
##     d6_1              0.747    0.037   20.287    0.000
##     d6_2              0.786    0.036   21.646    0.000
##     d6_3              0.727    0.037   19.580    0.000
##     d6_4              0.661    0.038   17.347    0.000
## 
## Covariances:
##   structural ~~
##     trust             0.109    0.049    2.208    0.027
##     nueva             0.069    0.057    1.197    0.231
##     conf.gov          0.039    0.050    0.784    0.433
##   trust ~~
##     nueva             0.549    0.044   12.462    0.000
##     conf.gov          0.379    0.042    9.047    0.000
##   nueva ~~
##     conf.gov          0.372    0.050    7.464    0.000
## 
## Variances:
##     c3_1              0.687    0.046
##     c3_2              0.614    0.045
##     c3_3              0.678    0.046
##     csc               0.410    0.046
##     d4_2              0.701    0.043
##     d4_3              0.221    0.035
##     d1                0.714    0.043
##     d2                0.493    0.036
##     r1_1              0.638    0.050
##     r1_2              0.553    0.052
##     r1_3              0.742    0.050
##     d6_1              0.440    0.034
##     d6_2              0.381    0.032
##     d6_3              0.470    0.034
##     d6_4              0.561    0.037
##     structural        1.000
##     trust             1.000
##     nueva             1.000
##     conf.gov          1.000

El modelo mejora bastante, obteniendo un RMSEA con un I.C (0.048, 0.064) y valores altos de CFI y TLI Nótese que se han usado 641 observaciones (valores perdidos en d6_2) tendríamos que imputar o considerar la matriz de correlación directamente en vez de todos los datos. Queda pendiente el procedimiento de imputación, así como el modelo con las correlaciones policóricas.

Las medidas de bondad de ajuste del modelo son

medidasAjuste(fit.cfa2)
##             chisq                df            pvalue    baseline.chisq 
##           252.872            84.000             0.000          2696.727 
##       baseline.df   baseline.pvalue               cfi               tli 
##           105.000             0.000             0.935             0.919 
##              logl unrestricted.logl              npar               aic 
##        -12413.660        -12287.225            36.000         24899.321 
##               bic            ntotal              bic2             rmsea 
##         25059.990           641.000         24945.692             0.056 
##    rmsea.ci.lower    rmsea.ci.upper      rmsea.pvalue              srmr 
##             0.048             0.064             0.102             0.044 
##       srmr_nomean               nfi              sncp              ecvi 
##             0.044             0.906             0.263             0.461 
##               gfi              agfi              pgfi              pnfi 
##             0.950             0.928             0.760             0.725

Gráficamente

diagrama(fit.cfa2, e.size = 0.06)

plot of chunk unnamed-chunk-18

Siguientes pasos

Opciones que deberíamos pensar.