library(pacman)
p_load(lavaan, semPlot, ggplot2, psych, efast)
#Correlation matrices
lowerEUR = '
1
0.624 1
0.641 0.687 1
0.198 0.333 0.252 1
0.119 0.229 0.19 0.368 1
0.307 0.427 0.452 0.494 0.403 1
0.29 0.22 0.219 0.021 0.11 0.145 1
0.238 0.279 0.188 0.05 0.097 0.114 0.578 1
0.217 0.157 0.217 0.037 0.093 0.199 0.625 0.635 1
0.051 0.189 0.125 0.206 0.357 0.35 0.139 0.108 0.187 1
0.073 0.143 0.131 0.126 0.326 0.331 0.266 0.191 0.296 0.521 1
0.139 0.167 0.132 0.073 0.217 0.32 0.186 0.214 0.236 0.497 0.662 1'
lowerAFR = '
1
0.614 1
0.668 0.665 1
0.161 0.317 0.227 1
0.137 0.243 0.224 0.33 1
0.373 0.537 0.525 0.478 0.402 1
0.361 0.32 0.297 0.067 0.097 0.131 1
0.218 0.253 0.268 -0.026 -0.004 0.093 0.523 1
0.196 0.25 0.242 0.069 0.017 0.121 0.582 0.698 1
0.02 0.167 0.154 0.2 0.266 0.235 0.108 0.072 0.151 1
0.06 0.093 0.17 -0.044 0.228 0.194 0.179 0.221 0.25 0.411 1
0.114 0.131 0.198 -0.054 0.22 0.257 0.121 0.125 0.166 0.356 0.686 1'
#Variable names
Names = list("I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9", "I10", "I11", "I12")
#Convert to variance-covariance matrices
EUR.cor = getCov(lowerEUR, names = Names)
AFR.cor = getCov(lowerAFR, names = Names)
EURSDs <- c(1.5, 1.48, 1.51, 1.88, 1.74, 1.66, 1.29, 1.26, 1.34, 1.64, 1.59, 1.59)
AFRSDs <- c(1.63, 1.63, 1.54, 1.88, 1.79, 1.68, 1.33, 1.19, 1.35, 1.71, 1.59, 1.61)
EUR.cov = lavaan::cor2cov(R = EUR.cor, sds = EURSDs)
AFR.cov = lavaan::cor2cov(R = AFR.cor, sds = AFRSDs)
#Means
EURmeans = c(5.25, 5.21, 4.93, 4.45, 4.48, 3.91, 5.27, 5.77, 5.29, 4.36, 3.96, 3.65)
AFRmeans = c(5.2, 5.09, 4.85, 4.62, 4.65, 3.98, 5.25, 5.81, 5.31, 4.09, 3.71, 3.44)
#Group inputs
GCovs <- list(EUR.cov, AFR.cov)
GMeans <- list(EURmeans, AFRmeans)
GNs <- list(350, 317)
#Fit measures
FITM <- c("chisq", "df", "nPar", "cfi", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "aic", "bic")
#For plotting
LATS <- list(
PAP = c("I1", "I2", "I3"),
PAV = c("I4", "I5","I6"),
MAP = c("I7", "I8", "I9"),
MAV = c("I10", "I11", "I12"))
The Modified Achievement Goal Questionnaire (AGQ-M) is intended to measure achievement goal orientation. It theoretically features four dimensions described by Campbell et al. (2008) as follows:
Under this new framework, mastery-approach (MAP) orientation refers to the goal of developing competence, which is evaluated using absolute or intrapersonal standards of competence. Mastery-avoidance (MAV) orientation refers to the goal of avoiding misunderstanding, which is evaluated using absolute or intrapersonal standards of competence. Performance-approach (PAP) orientation refers to the goal of striving to be superior to or better than others on a task, which is evaluated using normative or interpersonal standards of competence. Finally, performance-avoidance (PAV) refers to the goal of avoiding inferiority or not being the worst on a task, which is evaluated using normative or interpersonal standards of competence.
Campbell et al. (2008) aimed to test if the AGQ-M was invariant, and thus suitable for use, by race, in African- and European-American university students. To note, the sample may be selected on achievement orientation. Nonetheless, they ended up with 317 African- and almost 8,000 European-American students’ results. To avoid issues with relatively group sizes, they randomly selected 350 European-American students to form their sample. This probably should not have been done because if strict factorial invariance holds, relatively group sizes do not matter. But they did not test strict factorial invariance. In fact, they only tested to scalar invariance. This is a bit worrying because it still leaves open the possibility that the influences on achievement goal orientation could differ by ethnic group. With that in mind, I went ahead and tested everything below.
#Correlated group factor model from the paper
MAQM.model <- '
PAP =~ I1 + I2 + I3
PAV =~ I4 + I5 + I6
MAP =~ I7 + I8 + I9
MAV =~ I10 + I11 + I12'
# Plot
MAQE.fit <- cfa(MAQM.model, sample.cov = EUR.cov, sample.nobs = 350, std.lv = T, orthogonal = F)
semPaths(MAQE.fit, "model", "std", title = F, residuals = F, groups = "LATS", pastel = T, mar = c(2, 1, 3, 1))
# Multiple-group
MAQMC.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = T, orthogonal = F)
MAQMM.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = F, orthogonal = F, group.equal = "loadings")
MAQMS.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = F, orthogonal = F, group.equal = c("loadings", "intercepts"))
MAQMF.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = F, orthogonal = F, group.equal = c("loadings", "intercepts", "residuals"))
MAQMLV.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = T, orthogonal = F, group.equal = c("loadings", "intercepts", "residuals"))
MAQMLA.fit <- cfa(MAQM.model, sample.cov = GCovs, sample.mean = GMeans, sample.nobs = GNs, std.lv = T, orthogonal = F, group.equal = c("loadings", "intercepts", "residuals", "means"))
round(cbind(CONFIGURAL = fitMeasures(MAQMC.fit, FITM),
METRIC = fitMeasures(MAQMM.fit, FITM),
SCALAR = fitMeasures(MAQMS.fit, FITM),
STRICT = fitMeasures(MAQMF.fit, FITM),
LVARS = fitMeasures(MAQMLV.fit, FITM),
MEANS = fitMeasures(MAQMLA.fit, FITM)), 3)
## CONFIGURAL METRIC SCALAR STRICT LVARS MEANS
## chisq 262.760 271.008 274.434 294.406 294.406 305.088
## df 96.000 104.000 112.000 124.000 124.000 128.000
## npar 84.000 76.000 68.000 56.000 56.000 52.000
## cfi 0.945 0.945 0.946 0.944 0.944 0.941
## rmsea 0.072 0.069 0.066 0.064 0.064 0.064
## rmsea.ci.lower 0.062 0.059 0.056 0.055 0.055 0.055
## rmsea.ci.upper 0.083 0.080 0.076 0.074 0.074 0.074
## aic 26944.548 26936.797 26924.222 26920.195 26920.195 26922.877
## bic 27322.783 27279.009 27230.412 27172.351 27172.351 27157.022
df <- data.frame("FIT" = c(fitMeasures(MAQMC.fit, "bic") - fitMeasures(MAQMC.fit, "bic"), fitMeasures(MAQMM.fit, "bic") - fitMeasures(MAQMC.fit, "bic"), fitMeasures(MAQMS.fit, "bic") - fitMeasures(MAQMC.fit, "bic"), fitMeasures(MAQMF.fit, "bic") - fitMeasures(MAQMC.fit, "bic"), fitMeasures(MAQMLA.fit, "bic") - fitMeasures(MAQMC.fit, "bic"), fitMeasures(MAQMC.fit, "aic") - fitMeasures(MAQMC.fit, "aic"), fitMeasures(MAQMM.fit, "aic") - fitMeasures(MAQMC.fit, "aic"), fitMeasures(MAQMS.fit, "aic") - fitMeasures(MAQMC.fit, "aic"), fitMeasures(MAQMF.fit, "aic") - fitMeasures(MAQMC.fit, "aic"), fitMeasures(MAQMLA.fit, "aic") - fitMeasures(MAQMC.fit, "aic")), "Model" = c("Configural", "Metric", "Scalar", "Strict", "Mean Homogeneity"), "LM" = c("BIC", "BIC", "BIC", "BIC", "BIC", "AIC", "AIC", "AIC", "AIC", "AIC"))
df
df$Model <- factor(df$Model, levels = c("Configural", "Metric", "Scalar", "Strict", "Mean Homogeneity"))
ggplot(df, aes(x = Model, y = FIT, group = LM, shape = LM, color = LM)) + geom_line() + geom_point() + xlab("Level of Invariance") + ylab("Value") + scale_colour_discrete(name = "Information Criteria", breaks = c("AIC", "BIC"), labels = c("Akaike", "Schwarz"), c = 60) + scale_shape_discrete(name = "Factor Model", breaks = c("Akaike", "Schwarz"), labels = c("AIC", "BIC")) + theme_bw() + theme(text = element_text(size = 12, family = "serif"))
MAQHOF.model <- '
PAP =~ I1 + I2 + I3
PAV =~ I4 + I5 + I6
MAP =~ I7 + I8 + I9
MAV =~ I10 + I11 + I12
GAM =~ PAP + PAV + MAP + MAV'
MAQBF.model <- '
PAP =~ I1 + I2 + I3
PAV =~ I4 + I5 + I6
MAP =~ I7 + I8 + I9
MAV =~ I10 + I11 + I12
GAM =~ I1 + I2 + I3 + I4 + I5 + I6 + I7 + I8 + I9 + I10 + I11 + I12
I4 ~~ 1*I4' #negative residual variance constraint
MAQE2.fit <- cfa(MAQHOF.model, sample.cov = EUR.cov, sample.nobs = 350, std.lv = T, orthogonal = F)
MAQE3.fit <- cfa(MAQBF.model, sample.cov = EUR.cov, sample.nobs = 350, std.lv = T, orthogonal = T)
round(cbind(CGF = fitMeasures(MAQE.fit, FITM),
HOF = fitMeasures(MAQE2.fit, FITM),
BF = fitMeasures(MAQE3.fit, FITM)),3)
## CGF HOF BF
## chisq 126.370 161.673 136.819
## df 48.000 50.000 43.000
## npar 30.000 28.000 35.000
## cfi 0.951 0.930 0.941
## rmsea 0.068 0.080 0.079
## rmsea.ci.lower 0.054 0.066 0.064
## rmsea.ci.upper 0.083 0.094 0.094
## aic 13998.603 14029.906 14019.052
## bic 14114.341 14137.928 14154.080
The results are as follows:
The four-factor structure was fine. It actually performed better than a higher-order general factor structure, and if \(\omega_hs\) is calculated alongside \(\omega_h\), we can actually see good evidence for distinct dimensions! Given how rare that is, that’s a very exciting find and a sign that the makers of the AGQ-M did an excellent job that yielded structural fidelity for their theory. I do not often get to say that. A bifactor model was incoherent and led to errors without modification and showed evidence against unidimensionality. Perhaps one could be modeled as a method factor, but it’s not necessary.
Encouragingly and in a clear extension of Campbell et al.’s (2008) results, invariance was achieved, and not only at the level of SFI, but all the way to mean homogeneity. A substantive restatement of these results would be as follows: there are no black-white differences in whatever the AGQ-M measures in samples of university students.
Generalization to other populations should be tested. Most importantly, this adds more support for the attitude-achievement paradox, or something like it. At least among black and white university students in the US, it may be the case that culture is irrelevant, or at least that the cultural backgrounds of the people in this sample were so similar that it was irrelevant. Even if it affected the factor means and variances directly, there were neither mean nor latent variance differences.
Campbell, H. L., Barry, C. L., Joe, J. N., & Finney, S. J. (2008). Configural, metric, and scalar invariance of the modified achievement goal questionnaire across African American and white university students. Educational and Psychological Measurement, 68(6), 988–1007. https://doi.org/10.1177/0013164408315269
The new (and great) efast package actually makes this easier than ever before.
EFA <- '
efa("x4") * F1 +
efa("x4") * F2 +
efa("x4") * F3 +
efa("x4") * F4 =~ I1 + I2 + I3 + I4 + I5 + I6 + I7 + I8 + I9 + I10 + I11 + I12'
EFAAGMQ <- lavaan(model = EFA, sample.cov = EUR.cov, sample.nobs = 350, auto.var = TRUE, auto.efa = TRUE)
#summary(EFAAGMQ, stand = T, fit = T)
inspect(EFAAGMQ, what="std")$lambda
## F1 F2 F3 F4
## I1 0.804 -0.112 0.054 0.010
## I2 0.775 0.118 -0.013 -0.012
## I3 0.820 0.043 -0.016 -0.006
## I4 0.013 0.790 -0.003 -0.301
## I5 -0.038 0.577 0.023 0.038
## I6 0.221 0.622 0.008 0.023
## I7 0.058 -0.035 0.739 0.019
## I8 0.038 -0.012 0.761 -0.035
## I9 -0.060 0.046 0.841 0.012
## I10 -0.021 0.310 -0.011 0.475
## I11 0.002 0.125 0.064 0.744
## I12 0.127 -0.021 -0.023 0.804
PFA <- fa(EUR.cor, n.obs = 350, nfactors = 4, rotate = "geominQ")
## Loading required namespace: GPArotation
print(PFA$loadings)
##
## Loadings:
## MR2 MR3 MR1 MR4
## I1 0.792
## I2 0.761 0.136
## I3 0.823
## I4 -0.255 0.772
## I5 0.559
## I6 0.229 0.597
## I7 0.740
## I8 0.764
## I9 0.834
## I10 0.505 0.290
## I11 0.759 0.103
## I12 0.114 0.813
##
## MR2 MR3 MR1 MR4
## SS loadings 1.961 1.838 1.571 1.392
## Proportion Var 0.163 0.153 0.131 0.116
## Cumulative Var 0.163 0.317 0.448 0.564
FFA <- efast_efa(data = EUR.cor, sample.nobs = 350, M = 4)
## Warning in lavData(data = data, group = group, cluster = cluster, ov.names =
## OV.NAMES, : lavaan WARNING: std.ov argument is ignored if only sample statistics
## are provided.
efast_loadings(FFA)
##
## Loadings:
## F1 F2 F3 F4
## I1 0.796
## I2 0.771 0.124
## I3 0.815
## I4 0.769 -0.244
## I5 0.551
## I6 0.225 0.598
## I7 0.737
## I8 0.760
## I9 0.839
## I10 0.278 0.508
## I11 0.766
## I12 0.104 0.816
##
## F1 F2 F3 F4
## SS loadings 1.964 1.371 1.834 1.584
## Proportion Var 0.164 0.114 0.153 0.132
## Cumulative Var 0.164 0.278 0.431 0.563