Last chance! 50% off unlimited learning
Sale ends in
This function does alignment under approximate
invariance for
invariance.alignment(lambda, nu, wgt=NULL, align.scale=c(1, 1),
align.pow=c(1, 1), eps=.01, h=0.001, max.increment=0.2,
increment.factor=c(1.001,1.02,1.04,1.08), maxiter=300, conv=1e-04,
fac.oldpar=c(.01,.2,.5,.85), psi0.init=NULL, alpha0.init=NULL, progress=TRUE)# S3 method for invariance.alignment
summary(object,...)
A
A
A
A vector of length two containing scale parameter
A vector of length two containing power
A parameter in the optimization function
Numerical differentiation parameter
Maximum increment in each iteration
A numerical larger than one indicating the extent
of the decrease of max.increment
in every
iteration.
Maximum number of iterations
Maximum parameter change of the optimization function
Convergence acceleration parameter between 0 and 1. This parameter defines the relative weight the previous parameter value for the calculation of the parameter update. The default is .85. But experiment with this value and study the obtained results.
An optional vector of initial
An optional vector of initial
An optional logical indicating whether computational should be printed.
Object of class invariance.alignment
Further optional arguments to be passed
A list with following entries
Aligned distribution parameters
Aligned item parameters for all groups
Effect sizes of approximate invariance
Aligned
Residuals of
Aligned
Residuals of
Number of iterations for
Iteration index with minimum optimization value
Minimum optimization value
Used alignment scale parameters
Used alignment power parameters
For
The alignment procedure searches means
For identification reasons, the product
Note that the standard deviations
Note that Asparouhov and Muthen (2014) use align.scale
)
and align.pow
).
In case of
Effect sizes of approximate invariance based on es.invariance
. In addition,
the average correlation of aligned item parameters among groups (rbar
)
is reported.
Metric invariance means that all aligned item loadings
Asparouhov, T., & Muthen, B. (2014). Multiple-group factor analysis alignment. Structural Equation Modeling, 21, 1-14.
Muthen, B., & Asparouhov, T. (2014). IRT studies of many groups: The alignment method. Frontiers in Psychology | Quantitative Psychology and Measurement, 5:978. doi: 10.3389/fpsyg.2014.00978,
Vandenberg, R. J., & Lance, C. E. (2000). A review and synthesis of the measurement invariance literature: Suggestions, practices, and recommendations for organizational research. Organizational Research Methods, 3, 4-70.
For IRT linking see also linking.haberman
.
For modeling random item effects for loadings and intercepts
see mcmc.2pno.ml
.
# NOT RUN {
#############################################################################
# EXAMPLE 1: Item parameters cultural activities
#############################################################################
data( data.activity.itempars )
lambda <- data.activity.itempars$lambda
nu <- data.activity.itempars$nu
Ng <- data.activity.itempars$N
wgt <- matrix( sqrt(Ng), length(Ng), ncol(nu) )
#***
# Model 1: Alignment using a quadratic loss function
# -> use the default of align.pow=c(1,1) and align.scale=c(1,1)
mod1 <- sirt::invariance.alignment( lambda, nu, wgt )
summary(mod1)
## Effect Sizes of Approximate Invariance
## loadings intercepts
## R2 0.9944 0.9988
## sqrtU2 0.0748 0.0346
## rbar 0.9265 0.9735
#****
# Model 2: Different powers for alignment
mod2 <- sirt::invariance.alignment( lambda, nu, wgt, align.pow=c(.25,1/2),
align.scale=c(.95,.95), max.increment=.1)
summary(mod2)
# compare means from Models 1 and 2
plot( mod1$pars$alpha0, mod2$pars$alpha0, pch=16,
xlab="M (Model 1)", ylab="M (Model 2)", xlim=c(-.3,.3), ylim=c(-.3,.3) )
lines( c(-1,1), c(-1,1), col="gray")
round( cbind( mod1$pars$alpha0, mod2$pars$alpha0 ), 3 )
round( mod1$nu.resid, 3)
round( mod2$nu.resid,3 )
#****
# Model 3: Low powers for alignment of scale and power
# Note that setting increment.factor larger than 1 seems necessary
mod3 <- sirt::invariance.alignment( lambda, nu, wgt, align.pow=c(.25,.35),
align.scale=c(.55,.55), psi0.init=mod1$psi0, alpha0.init=mod1$alpha0 )
summary(mod3)
# compare mean and SD estimates of Models 1 and 3
plot( mod1$pars$alpha0, mod3$pars$alpha0, pch=16)
plot( mod1$pars$psi0, mod3$pars$psi0, pch=16)
# compare residuals for Models 1 and 3
# plot lambda
plot( abs(as.vector(mod1$lambda.resid)), abs(as.vector(mod3$lambda.resid)),
pch=16, xlab="Residuals lambda (Model 1)",
ylab="Residuals lambda (Model 3)", xlim=c(0,.1), ylim=c(0,.1))
lines( c(-3,3),c(-3,3), col="gray")
# plot nu
plot( abs(as.vector(mod1$nu.resid)), abs(as.vector(mod3$nu.resid)),
pch=16, xlab="Residuals nu (Model 1)", ylab="Residuals nu (Model 3)",
xlim=c(0,.4),ylim=c(0,.4))
lines( c(-3,3),c(-3,3), col="gray")
# }
# NOT RUN {
#############################################################################
# EXAMPLE 2: Comparison 4 groups | data.inv4gr
#############################################################################
data(data.inv4gr)
dat <- data.inv4gr
miceadds::library_install("semTools")
model1 <- "
F=~ I01 + I02 + I03 + I04 + I05 + I06 + I07 + I08 + I09 + I10 + I11
F ~~ 1*F
"
res <- semTools::measurementInvariance(model1, std.lv=TRUE, data=dat, group="group")
## Measurement invariance tests:
##
## Model 1: configural invariance:
## chisq df pvalue cfi rmsea bic
## 162.084 176.000 0.766 1.000 0.000 95428.025
##
## Model 2: weak invariance (equal loadings):
## chisq df pvalue cfi rmsea bic
## 519.598 209.000 0.000 0.973 0.039 95511.835
##
## [Model 1 versus model 2]
## delta.chisq delta.df delta.p.value delta.cfi
## 357.514 33.000 0.000 0.027
##
## Model 3: strong invariance (equal loadings + intercepts):
## chisq df pvalue cfi rmsea bic
## 2197.260 239.000 0.000 0.828 0.091 96940.676
##
## [Model 1 versus model 3]
## delta.chisq delta.df delta.p.value delta.cfi
## 2035.176 63.000 0.000 0.172
##
## [Model 2 versus model 3]
## delta.chisq delta.df delta.p.value delta.cfi
## 1677.662 30.000 0.000 0.144
##
# extract item parameters separate group analyses
ipars <- lavaan::parameterEstimates(res$fit.configural)
# extract lambda's: groups are in rows, items in columns
lambda <- matrix( ipars[ ipars$op=="=~", "est"], nrow=4, byrow=TRUE)
colnames(lambda) <- colnames(dat)[-1]
# extract nu's
nu <- matrix( ipars[ ipars$op=="~1" & ipars$se !=0, "est" ], nrow=4, byrow=TRUE)
colnames(nu) <- colnames(dat)[-1]
# Model 1: least squares optimization
mod1 <- sirt::invariance.alignment( lambda=lambda, nu=nu )
summary(mod1)
## Effect Sizes of Approximate Invariance
## loadings intercepts
## R2 0.9826 0.9972
## sqrtU2 0.1319 0.0526
## rbar 0.6237 0.7821
## -----------------------------------------------------------------
## Group Means and Standard Deviations
## alpha0 psi0
## 1 0.000 0.965
## 2 -0.105 1.098
## 3 -0.081 1.011
## 4 0.171 0.935
# Model 2: sparse target function
mod2 <- sirt::invariance.alignment( lambda=lambda, nu=nu, align.pow=c(1/4,1/4) )
summary(mod2)
## Effect Sizes of Approximate Invariance
## loadings intercepts
## R2 0.9824 0.9972
## sqrtU2 0.1327 0.0529
## rbar 0.6237 0.7856
## -----------------------------------------------------------------
## Group Means and Standard Deviations
## alpha0 psi0
## 1 -0.002 0.965
## 2 -0.107 1.098
## 3 -0.083 1.011
## 4 0.170 0.935
#############################################################################
# EXAMPLE 3: European Social Survey data.ess2005
#############################################################################
data(data.ess2005)
lambda <- data.ess2005$lambda
nu <- data.ess2005$nu
# Model 1: least squares optimization
mod1 <- sirt::invariance.alignment( lambda=lambda, nu=nu )
summary(mod1)
# Model 2: sparse target function and definition of scales
mod2 <- sirt::invariance.alignment( lambda=lambda, nu=nu, align.pow=c(1/4,1/4),
align.scale=c( .2, .3) )
summary(mod2)
# compare results of Model 1 and Model 2
round( cbind( mod1$pars, mod2$pars ), 2 )
## alpha0 psi0 alpha0 psi0
## 1 0.06 0.87 0.05 0.91
## 2 -0.51 1.03 -0.37 0.99
## 3 0.18 0.97 0.25 1.04
## 4 -0.67 0.90 -0.53 0.90
## 5 0.09 0.98 0.10 0.99
## 6 0.23 1.03 0.28 1.00
## 7 0.27 0.97 0.14 1.10
## 8 0.18 0.90 0.07 0.89
## [...]
# look at nu residuals to explain differences in means
round( mod1$nu.resid, 2)
## ipfrule ipmodst ipbhprp imptrad
## [1,] 0.15 -0.25 -0.01 0.01
## [2,] -0.18 0.23 0.10 -0.24
## [3,] 0.22 -0.34 0.05 -0.02
## [4,] 0.29 -0.04 0.12 -0.53
## [5,] -0.32 0.19 0.00 0.13
## [6,] 0.05 -0.21 0.05 0.04
## [7,] -0.26 0.54 -0.15 -0.02
## [8,] 0.07 -0.05 -0.10 0.12
round( mod2$nu.resid, 2)
## ipfrule ipmodst ipbhprp imptrad
## [1,] 0.16 -0.25 0.00 0.02
## [2,] -0.27 0.14 0.00 -0.30
## [3,] 0.18 -0.37 0.00 -0.05
## [4,] 0.19 -0.13 0.00 -0.60
## [5,] -0.33 0.19 -0.01 0.12
## [6,] 0.00 -0.23 0.00 0.01
## [7,] -0.16 0.64 -0.01 0.04
## [8,] 0.15 0.02 -0.02 0.19
round( rowMeans( mod1$nu.resid )[1:8], 2 )
## [1] -0.02 -0.02 -0.02 -0.04 0.00 -0.02 0.03 0.01
round( rowMeans( mod2$nu.resid )[1:8], 2 )
## [1] -0.02 -0.11 -0.06 -0.14 -0.01 -0.06 0.13 0.09
#############################################################################
# EXAMPLE 4: Linking with item parameters containing outliers
#############################################################################
# see Help file in linking.robust
# simulate some item difficulties in the Rasch model
I <- 38
set.seed(18785)
itempars <- data.frame("item"=paste0("I",1:I) )
itempars$study1 <- stats::rnorm( I, mean=.3, sd=1.4 )
# simulate DIF effects plus some outliers
bdif <- stats::rnorm(I,mean=.4,sd=.09)+( stats::runif(I)>.9 )* rep( 1*c(-1,1)+.4, each=I/2 )
itempars$study2 <- itempars$study1 + bdif
# create input for function invariance.alignment
nu <- t( itempars[,2:3] )
colnames(nu) <- itempars$item
lambda <- 1+0*nu
# linking using least squares optimization
mod1 <- sirt::invariance.alignment( lambda=lambda, nu=nu )
summary(mod1)
## Group Means and Standard Deviations
## alpha0 psi0
## study1 -0.286 1
## study2 0.286 1
# linking using powers of .5
mod2 <- sirt::invariance.alignment( lambda=lambda, nu=nu, align.pow=c(.5,.5) )
summary(mod2)
## Group Means and Standard Deviations
## alpha0 psi0
## study1 -0.213 1
## study2 0.213 1
# linking using powers of .25
mod3 <- sirt::invariance.alignment( lambda=lambda, nu=nu, align.pow=c(.25,.25) )
summary(mod3)
## Group Means and Standard Deviations
## alpha0 psi0
## study1 -0.207 1
## study2 0.207 1
#############################################################################
# EXAMPLE 5: Linking gender groups with data.math
#############################################################################
data(data.math)
dat <- data.math$data
dat.male <- dat[ dat$female==0, substring( colnames(dat),1,1)=="M" ]
dat.female <- dat[ dat$female==1, substring( colnames(dat),1,1)=="M" ]
#*************************
# Model 1: Linking using the Rasch model
mod1m <- sirt::rasch.mml2( dat.male )
mod1f <- sirt::rasch.mml2( dat.female )
# create objects for invariance.alignment
nu <- rbind( mod1m$item$thresh, mod1f$item$thresh )
colnames(nu) <- mod1m$item$item
rownames(nu) <- c("male", "female")
lambda <- 1+0*nu
# mean of item difficulties
round( rowMeans(nu), 3 )
## male female
## -0.081 -0.049
# Linking using least squares optimization
res1a <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ) )
summary(res1a)
## Effect Sizes of Approximate Invariance
## loadings intercepts
## R2 1 0.9801
## sqrtU2 0 0.1412
## rbar 1 0.9626
## -----------------------------------------------------------------
## Group Means and Standard Deviations
## alpha0 psi0
## male -0.016 1
## female 0.016 1
# Linking using optimization with absolute values
res1b <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ),
align.pow=c( .5, .5 ) )
summary(res1b)
## Group Means and Standard Deviations
## alpha0 psi0
## male -0.045 1
## female 0.045 1
#-- compare results with Haberman linking
I <- ncol(dat.male)
itempartable <- data.frame( "study"=rep( c("male", "female"), each=I ) )
itempartable$item <- c( paste0(mod1m$item$item), paste0(mod1f$item$item) )
itempartable$a <- 1
itempartable$b <- c( mod1m$item$b, mod1f$item$b )
# estimate linking parameters
res1c <- sirt::linking.haberman( itempars=itempartable )
## Transformation parameters (Haberman linking)
## study At Bt
## 1 female 1 0.000
## 2 male 1 -0.032
## Linear transformation for person parameters theta
## study A_theta B_theta
## 1 female 1 0.000
## 2 male 1 0.032
## R-Squared Measures of Invariance
## slopes intercepts
## R2 1 0.9801
## sqrtU2 0 0.1412
#-- results of equating.rasch
x <- itempartable[ 1:I, c("item", "b") ]
y <- itempartable[ I + 1:I, c("item", "b") ]
res1d <- sirt::equating.rasch( x, y )
round( res1d$B.est, 3 )
## Mean.Mean Haebara Stocking.Lord
## 1 0.032 0.032 0.029
#*************************
# Model 2: Linking using the 2PL model
I <- ncol(dat.male)
mod2m <- sirt::rasch.mml2( dat.male, est.a=1:I)
mod2f <- sirt::rasch.mml2( dat.female, est.a=1:I)
# create objects for invariance.alignment
nu <- rbind( mod2m$item$thresh, mod2f$item$thresh )
colnames(nu) <- mod2m$item$item
rownames(nu) <- c("male", "female")
lambda <- rbind( mod2m$item$a, mod2f$item$a )
colnames(lambda) <- mod2m$item$item
rownames(lambda) <- c("male", "female")
res2a <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ) )
summary(res2a)
## Effect Sizes of Approximate Invariance
## loadings intercepts
## R2 0.9589 0.9682
## sqrtU2 0.2027 0.1782
## rbar 0.5177 0.9394
## -----------------------------------------------------------------
## Group Means and Standard Deviations
## alpha0 psi0
## male -0.044 0.968
## female 0.047 1.034
res2b <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ),
align.pow=c( .5, .5 ) )
summary(res2b)
## Group Means and Standard Deviations
## alpha0 psi0
## male -0.046 1.053
## female 0.041 0.951
# compare results with Haberman linking
I <- ncol(dat.male)
itempartable <- data.frame( "study"=rep( c("male", "female"), each=I ) )
itempartable$item <- c( paste0(mod2m$item$item), paste0(mod2f$item$item ) )
itempartable$a <- c( mod2m$item$a, mod2f$item$a )
itempartable$b <- c( mod2m$item$b, mod2f$item$b )
# estimate linking parameters
res2c <- sirt::linking.haberman( itempars=itempartable )
## Transformation parameters (Haberman linking)
## study At Bt
## 1 female 1.000 0.00
## 2 male 1.041 0.09
## Linear transformation for person parameters theta
## study A_theta B_theta
## 1 female 1.000 0.00
## 2 male 1.041 -0.09
## R-Squared Measures of Invariance
## slopes intercepts
## R2 0.9554 0.9484
## sqrtU2 0.2111 0.2273
# }
Run the code above in your browser using DataLab