invariance.alignment.RdThe function invariance.alignment performs alignment under approximate
invariance for \(G\) groups and \(I\) items
(Asparouhov & Muthen, 2014; Byrne & van de Vijver, 2017; DeMars, 2020; Finch, 2016;
Fischer & Karl, 2019; Flake & McCoach, 2018; Kim et al., 2017; Marsh et al., 2018;
Muthen & Asparouhov, 2014, 2018; Pokropek, Davidov & Schmidt, 2019).
It is assumed that item loadings and intercepts are
previously estimated as a unidimensional factor model under the assumption of a factor
with zero mean and a variance of one.
The function invariance_alignment_constraints postprocesses the output of the
invariance.alignment function and estimates item parameters under equality
constraints for prespecified absolute values of parameter tolerance.
The function invariance_alignment_simulate simulates a one-factor model
for multiple groups for given matrices of \(\nu\) and \(\lambda\) parameters of
item intercepts and item slopes (see Example 6).
The function invariance_alignment_cfa_config estimates one-factor
models separately for each group as a preliminary step for invariance
alignment (see Example 6). Sampling weights are accommodated by the
argument weights.
invariance.alignment(lambda, nu, wgt=NULL, align.scale=c(1, 1), align.pow=c(.5, .5), eps=1e-3, psi0.init=NULL, alpha0.init=NULL, center=FALSE, optimizer="optim", fixed=NULL, meth=1, ...) # S3 method for invariance.alignment summary(object, digits=3, file=NULL, ...) invariance_alignment_constraints(model, lambda_parm_tol, nu_parm_tol ) # S3 method for invariance_alignment_constraints summary(object, digits=3, file=NULL, ...) invariance_alignment_simulate(nu, lambda, err_var, mu, sigma, N, output="data", groupwise=FALSE, exact=FALSE) invariance_alignment_cfa_config(dat, group, weights=NULL, model="2PM", verbose=FALSE, ...)
| lambda | A \(G \times I\) matrix with item loadings |
|---|---|
| nu | A \(G \times I\) matrix with item intercepts |
| wgt | A \(G \times I\) matrix for weighing groups for each item |
| align.scale | A vector of length two containing scale parameter \(a_\lambda\) and \(a_\nu\) (see Details) |
| align.pow | A vector of length two containing power \(p_\lambda\) and \(p_\nu\) (see Details) |
| eps | A parameter in the optimization function |
| psi0.init | An optional vector of initial \(\psi_0\) parameters |
| alpha0.init | An optional vector of initial \(\alpha_0\) parameters |
| center | Logical indicating whether estimated means and standard deviations should be centered. |
| optimizer | Name of the optimizer chosen for alignment. Options are
|
| fixed | Logical indicating whether SD of first group should
be fixed to one. If |
| meth | Type of method used for optimization function. |
| object | Object of class |
| digits | Number of digits used for rounding |
| file | Optional file name in which summary should be sunk |
| ... | Further optional arguments to be passed |
| model | Model of class |
| lambda_parm_tol | Parameter tolerance for \(\lambda\) parameters |
| nu_parm_tol | Parameter tolerance for \(\nu\) parameters |
| err_var | Error variance |
| mu | Vector of means |
| sigma | Vector of standard deviations |
| N | Vector of sample sizes per group |
| output | Specifies output type: |
| groupwise | Logical indicating whether group-wise output is requested |
| exact | Logical indicating whether distributions should be exactly preserved in simulated data |
| dat | Dataset with items or a list containing sufficient statistics |
| group | Vector containing group indicators |
| weights | Optional vector of sampling weights |
| verbose | Logical indicating whether progress should be printed |
For \(G\) groups and \(I\) items, item loadings \(\lambda_{ig0}\) and intercepts \(\nu_{ig0}\) are available and have been estimated in a 1-dimensional factor analysis assuming a standardized factor.
The alignment procedure searches means \(\alpha_{g0}\) and standard deviations \(\psi_{g0}\) using an alignment optimization function \(F\). This function is defined as $$F=\sum_i \sum_{ g_1 < g_2} w_{i,g1} w_{i,g2} f_\lambda( \lambda_{i g_1,1} - \lambda_{i g_2,1} ) + \sum_i \sum_{ g_1 < g_2} w_{i,g1} w_{i,g2} f_\nu( \nu_{i g_1,1} - \nu_{i g_2,1} ) $$ where the aligned item parameters \(\lambda_{i g,1}\) and \(\nu_{i g,1}\) are defined such that
$$ \lambda_{i g,1}=\lambda_{i g 0} / \psi_{g0} \qquad \mbox{and} \qquad \nu_{i g,1}=\nu_{i g 0} - \alpha_{g0} \lambda_{ig0} / \psi_{g0} $$ and the optimization functions are defined as $$ f_\lambda (x)=| x/ a_\lambda | ^{p_\lambda} \approx [ ( x/ a_\lambda )^2 + \varepsilon ]^{p_\lambda / 2} \qquad \mbox{and} \qquad f_\nu (x)=| x/ a_\nu ]^{p_\nu} \approx [ ( x/ a_\nu )^2 + \varepsilon ]^{p_\nu / 2} $$ using a small \( \varepsilon > 0\) (e.g. .001) to obtain a differentiable optimization function. For \(p_\nu=0\) or \(p_\lambda=0\), the optimization function essentially counts the number of different parameter and mimicks a \(L_0\) penalty which is zero iff the argument is zero and one otherwise. It is approximated by $$f(x)=2 / ( 1 + \exp( - \gamma \sqrt{x^2 + \varepsilon} ) - 1$$ (Oelker & Tutz, 2017).
For identification reasons, the product \(\Pi_g \psi_{g0}\) of all group standard deviations is set to one. The mean \(\alpha_{g0}\) of the first group is set to zero.
Note that Asparouhov and Muthen (2014) use \(a_\lambda=a_\nu=1\)
(which can be modified in align.scale)
and \(p_\lambda=p_\nu=0.5\) (which can be modified in align.pow).
In case of \(p_\lambda=2\), the penalty is approximately
\(f_\lambda(x)=x^2 \), in case of \(p_\lambda=0.5\)
it is approximately \(f_\lambda(x)=\sqrt{|x|} \). Note that sirt used a
different parametrization in versions up to 3.5. The \(p\) parameters have to be halved
for consistency with previous versions (e.g., the Asparouhov & Muthen parametrization
corresponds to \(p=.25\); see also Fischer & Karl, 2019, for an application of
the previous parametrization).
Effect sizes of approximate invariance based on \(R^2\) have
been proposed by Asparouhov and Muthen (2014). These are
calculated separately for item loading and intercepts, resulting
in \(R^2_\lambda\) and \(R^2_\nu\) measures which are
included in the output es.invariance. In addition,
the average correlation of aligned item parameters among groups (rbar)
is reported.
Metric invariance means that all aligned item loadings \(\lambda_{ig,1}\) are equal across groups and therefore \(R^2_\lambda=1\). Scalar invariance means that all aligned item loadings \(\lambda_{ig,1}\) and aligned item intercepts \(\nu_{ig,1}\) are equal across groups and therefore \(R^2_\lambda=1\) and \(R^2_\nu=1\) (see Vandenberg & Lance, 2000).
A list with following entries
Aligned distribution parameters
Aligned item parameters for all groups
Effect sizes of approximate invariance
Aligned \( \lambda_{i g,1}\) parameters
Residuals of \( \lambda_{i g,1}\) parameters
Aligned \( \nu_{i g,1}\) parameters
Residuals of \( \nu_{i g,1}\) parameters
Number of iterations for \(f_\lambda\) and \(f_\nu\) optimization functions
Minimum optimization value
Used alignment scale parameters
Used alignment power parameters
Asparouhov, T., & Muthen, B. (2014). Multiple-group factor analysis alignment. Structural Equation Modeling, 21(4), 1-14. doi: 10.1080/10705511.2014.919210
Byrne, B. M., & van de Vijver, F. J. R. (2017). The maximum likelihood alignment approach to testing for approximate measurement invariance: A paradigmatic cross-cultural application. Psicothema, 29(4), 539-551. doi: 10.7334/psicothema2017.178
DeMars, C. E. (2020). Alignment as an alternative to anchor purification in DIF analyses. Structural Equation Modeling, 27(1), 56-72. doi: 10.1080/10705511.2019.1617151
Finch, W. H. (2016). Detection of differential item functioning for more than two groups: A Monte Carlo comparison of methods. Applied Measurement in Education, 29,(1), 30-45, doi: 10.1080/08957347.2015.1102916
Fischer, R., & Karl, J. A. (2019). A primer to (cross-cultural) multi-group invariance testing possibilities in R. Frontiers in Psychology | Cultural Psychology, 10:1507. doi: 10.3389/fpsyg.2019.01507
Flake, J. K., & McCoach, D. B. (2018). An investigation of the alignment method with polytomous indicators under conditions of partial measurement invariance. Structural Equation Modeling, 25(1), 56-70. doi: 10.1080/10705511.2017.1374187
Kim, E. S., Cao, C., Wang, Y., & Nguyen, D. T. (2017). Measurement invariance testing with many groups: A comparison of five approaches. Structural Equation Modeling, 24(4), 524-544. doi: 10.1080/10705511.2017.1304822
Marsh, H. W., Guo, J., Parker, P. D., Nagengast, B., Asparouhov, T., Muthen, B., & Dicke, T. (2018). What to do when scalar invariance fails: The extended alignment method for multi-group factor analysis comparison of latent means across many groups. Psychological Methods, 23(3), 524-545. doi: 10.1037/met0000113
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
Muthen, B., & Asparouhov, T. (2018). Recent methods for the study of measurement invariance with many groups: Alignment and random effects. Sociological Methods & Research, 47(4), 637-664. doi: 10.1177/0049124117701488
Oelker, M. R., & Tutz, G. (2017). A uniform framework for the combination of penalties in generalized structured models. Advances in Data Analysis and Classification, 11(1), 97-120. doi: 10.1007/s11634-015-0205-y
Pokropek, A., Davidov, E., & Schmidt, P. (2019). A Monte Carlo simulation study to assess the appropriateness of traditional and newer approaches to test for measurement invariance. Structural Equation Modeling, 26(5), 724-744. doi: 10.1080/10705511.2018.1561293
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. doi: 10.1177/109442810031002 s
For IRT linking see also linking.haberman or
TAM::tam.linking.
For modeling random item effects for loadings and intercepts
see mcmc.2pno.ml.
############################################################################# # EXAMPLE 1: Item parameters cultural activities ############################################################################# data(data.activity.itempars, package="sirt") 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 mod1 <- sirt::invariance.alignment( lambda, nu, wgt, align.pow=c(2,2) ) summary(mod1) #**** # Model 2: Different powers for alignment mod2 <- sirt::invariance.alignment( lambda, nu, wgt, align.pow=c(.5,1), align.scale=c(.95,.95)) 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 ) # L0 penalty mod2b <- sirt::invariance.alignment( lambda, nu, wgt, align.pow=c(0,0), align.scale=c(.3,.3)) summary(mod2b) #**** # 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(.5,.75), 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") if (FALSE) { ############################################################################# # 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(.5,.5) ) 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, align.pow=c(2,2) ) summary(mod1) # Model 2: sparse target function and definition of scales mod2 <- sirt::invariance.alignment( lambda=lambda, nu=nu, control=list(trace=2) ) summary(mod2) ############################################################################# # 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(1,1) ) 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(.5,.5) ) 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 ) # Linking using least squares optimization res1a <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ) ) summary(res1a) # Linking using optimization with absolute value function (pow=.5) res1b <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ), align.pow=c(1,1) ) summary(res1b) #-- 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 ) #-- results of sirt::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) res2b <- sirt::invariance.alignment( lambda, nu, align.scale=c( .3, .5 ), align.pow=c(1,1) ) summary(res2b) # 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 ) ############################################################################# # EXAMPLE 6: Data from Asparouhov & Muthen (2014) simulation study ############################################################################# G <- 3 # number of groups I <- 5 # number of items # define lambda and nu parameters lambda <- matrix(1, nrow=G, ncol=I) nu <- matrix(0, nrow=G, ncol=I) # define size of noninvariance dif <- 1 #- 1st group: N(0,1) lambda[1,3] <- 1+dif*.4; nu[1,5] <- dif*.5 #- 2nd group: N(0.3,1.5) gg <- 2 ; mu <- .3; sigma <- sqrt(1.5) lambda[gg,5] <- 1-.5*dif; nu[gg,1] <- -.5*dif nu[gg,] <- nu[gg,] + mu*lambda[gg,] lambda[gg,] <- lambda[gg,] * sigma #- 3nd group: N(.8,1.2) gg <- 3 ; mu <- .8; sigma <- sqrt(1.2) lambda[gg,4] <- 1-.7*dif; nu[gg,2] <- -.5*dif nu[gg,] <- nu[gg,] + mu*lambda[gg,] lambda[gg,] <- lambda[gg,] * sigma # define alignment scale align.scale <- c(.2,.4) # Asparouhov and Muthen use c(1,1) # define alignment powers align.pow <- c(.5,.5) # as in Asparouhov and Muthen #*** estimate alignment parameters mod1 <- sirt::invariance.alignment( lambda, nu, eps=.01, optimizer="optim", align.scale=align.scale, align.pow=align.pow, center=FALSE ) summary(mod1) #--- find parameter constraints for prespecified tolerance cmod1 <- sirt::invariance_alignment_constraints(model=mod1, nu_parm_tol=.4, lambda_parm_tol=.2 ) summary(cmod1) ############################################################################# # EXAMPLE 7: Similar to Example 6, but with data simulation and CFA estimation ############################################################################# #--- data simulation set.seed(65) G <- 3 # number of groups I <- 5 # number of items # define lambda and nu parameters lambda <- matrix(1, nrow=G, ncol=I) nu <- matrix(0, nrow=G, ncol=I) err_var <- matrix(1, nrow=G, ncol=I) # define size of noninvariance dif <- 1 #- 1st group: N(0,1) lambda[1,3] <- 1+dif*.4; nu[1,5] <- dif*.5 #- 2nd group: N(0.3,1.5) gg <- 2 ; lambda[gg,5] <- 1-.5*dif; nu[gg,1] <- -.5*dif #- 3nd group: N(.8,1.2) gg <- 3 lambda[gg,4] <- 1-.7*dif; nu[gg,2] <- -.5*dif #- define distributions of groups mu <- c(0,.3,.8) sigma <- sqrt(c(1,1.5,1.2)) N <- rep(1000,3) # sample sizes per group #* simulate data dat <- sirt::invariance_alignment_simulate(nu, lambda, err_var, mu, sigma, N) head(dat) #--- estimate CFA models pars <- sirt::invariance_alignment_cfa_config(dat[,-1], group=dat$group) print(pars) #--- invariance alignment # define alignment scale align.scale <- c(.2,.4) # define alignment powers align.pow <- c(.5,.5) mod1 <- sirt::invariance.alignment( lambda=pars$lambda, nu=pars$nu, eps=.01, optimizer="optim", align.scale=align.scale, align.pow=align.pow, center=FALSE) #* find parameter constraints for prespecified tolerance cmod1 <- sirt::invariance_alignment_constraints(model=mod1, nu_parm_tol=.4, lambda_parm_tol=.2 ) summary(cmod1) #--- estimate CFA models with sampling weights #* simulate weights weights <- stats::runif(sum(N), 0, 2) #* estimate models pars2 <- sirt::invariance_alignment_cfa_config(dat[,-1], group=dat$group, weights=weights) print(pars2$nu) print(pars$nu) #--- estimate one-parameter model pars <- sirt::invariance_alignment_cfa_config(dat[,-1], group=dat$group, model="1PM") print(pars) }