R: Partial Measurement Invariance Testing Across Groups

partialInvariance {semTools} | R Documentation

## Partial Measurement Invariance Testing Across Groups

### Description

This test will provide partial invariance testing by (a) freeing a parameter one-by-one from nested model and compare with the original nested model or (b) fixing (or constraining) a parameter one-by-one from the parent model and compare with the original parent model. This function only works with congeneric models. The `partialInvariance` is used for continuous variable. The `partialInvarianceCat` is used for categorical variables.

### Usage

    partialInvariance(fit, type, free = NULL, fix = NULL, refgroup = 1,
      poolvar = TRUE, p.adjust = "none", fbound = 2,
      return.fit = FALSE, method = "satorra.bentler.2001")

    partialInvarianceCat(fit, type, free = NULL, fix = NULL,
      refgroup = 1, poolvar = TRUE, p.adjust = "none",
      return.fit = FALSE, method = "satorra.bentler.2001")

### Arguments

`fit` | A list of models for invariance testing. Each model should be assigned by appropriate names (see details). The result from `measurementInvariance` or `measurementInvarianceCat` could be used in this argument directly.
`type` | The types of invariance testing: "metric", "scalar", "strict", or "means"
`free` | A vector of variable names that are free across groups in advance. If partial mean invariance is tested, this argument represents a vector of factor names that are free across groups.
`fix` | A vector of variable names that are constrained to be equal across groups in advance. If partial mean invariance is tested, this argument represents a vector of factor names that are fixed across groups.
`refgroup` | The reference group used to make the effect size comparison with the other groups.
`poolvar` | If `TRUE`, the variances are pooled across group for standardization. Otherwise, the variances of the reference group are used for standardization.
`p.adjust` | The method used to adjust p values. See `p.adjust` for the options for adjusting p values. The default is to not use any corrections.
`fbound` | The z-scores of factor that is used to calculate the effect size of the loading difference proposed by Millsap and Olivera-Aguilar (2012).
`return.fit` | Return the submodels fitted by this function
`method` | The method used to calculate likelihood ratio test. See `lavTestLRT` for available options

### Details

There are four types of partial invariance testing:

- Partial weak invariance. The model named 'fit.configural' from the list of models is compared with the model named 'fit.loadings'. Each loading will be freed or fixed from the metric and configural invariance models respectively. The modified models are compared with the original model. Note that the objects in the list of models must have the names of "fit.configural" and "fit.loadings". Users may use "metric", "weak", "loading", or "loadings" in the `type` argument. Note that, for testing invariance on marker variables, other variables will be assigned as marker variables automatically.

- Partial strong invariance. The model named 'fit.loadings' from the list of models is compared with the model named either 'fit.intercepts' or 'fit.thresholds'. Each intercept will be freed or fixed from the scalar and metric invariance models respectively. The modified models are compared with the original model. Note that the objects in the list of models must have the names of "fit.loadings" and either "fit.intercepts" or "fit.thresholds". Users may use "scalar", "strong", "intercept", "intercepts", "threshold", or "thresholds" in the `type` argument. Note that, for testing invariance on marker variables, other variables will be assigned as marker variables automatically. Note that if all variables are dichotomous, scalar invariance testing is not available.

- Partial strict invariance. The model named either 'fit.intercepts' or 'fit.thresholds' (or 'fit.loadings') from the list of models is compared with the model named 'fit.residuals'. Each residual variance will be freed or fixed from the strict and scalar (or metric) invariance models respectively. The modified models are compared with the original model. Note that the objects in the list of models must have the names of "fit.residuals" and either "fit.intercepts", "fit.thresholds", or "fit.loadings". Users may use "strict", "residual", "residuals", "error", or "errors" in the `type` argument.

- Partial mean invariance. The model named either 'fit.intercepts' or 'fit.thresholds' (or 'fit.residuals' or 'fit.loadings') from the list of models is compared with the model named 'fit.means'. Each factor mean will be freed or fixed from the means and scalar (or strict or metric) invariance models respectively. The modified models are compared with the original model. Note that the objects in the list of models must have the names of "fit.means" and either "fit.residuals", "fit.intercepts", "fit.thresholds", or "fit.loadings". Users may use "means" or "mean" in the `type` argument.

Two types of comparisons are used in this function:

1. `free`: The nested model is used as a template. Then, one parameter indicating the differences between two models is free. The new model is compared with the nested model. This process is repeated for all differences between two models. The likelihood-ratio test and the difference in CFI are provided.

2. `fix`: The parent model is used as a template. Then, one parameter indicating the differences between two models is fixed or constrained to be equal to other parameters. The new model is then compared with the parent model. This process is repeated for all differences between two models. The likelihood-ratio test and the difference in CFI are provided.

3. `wald`: This method is similar to the `fix` method. However, instead of building a new model and compare them with likelihood-ratio test, multivariate wald test is used to compare equality between parameter estimates. See `lavTestWald` for further details. Note that if any rows of the contrast cannot be summed to 0, the Wald test is not provided, such as comparing two means where one of the means is fixed as 0. This test statistic is not as accurate as likelihood-ratio test provided in `fix`. I provide it here in case that likelihood-ratio test fails to converge.

Note that this function does not adjust for the inflated Type I error rate from multiple tests. The degree of freedom of all tests would be the number of groups minus 1.

The details of standardized estimates and the effect size used for each parameters are provided in the vignettes by running `vignette("partialInvariance")`.

### Value

A list of results are provided. The list will consists of at least two elements:

1. `estimates`: The results of parameter estimates including pooled estimates (`poolest`), the estimates for each group, standardized estimates for each group (`std`), the difference in standardized values, and the effect size statistic (q for factor loading difference and h for error variance difference). See the details of this effect size statistic by running `vignette("partialInvariance")`. In the `partialInvariance` function, the additional effect statistics proposed by Millsap and Olivera-Aguilar (2012) are provided. For factor loading, the additional outputs are the observed mean difference (`diff_mean`), the mean difference if factor scores are low (`low_fscore`), and the mean difference if factor scores are high (`high_fscore`). The low factor score is calculated by (a) finding the factor scores that its z score equals -`bound` (the default is -2) from all groups and (b) picking the minimum value among the factor scores. The high factor score is calculated by (a) finding the factor scores that its z score equals `bound` (default = 2) from all groups and (b) picking the maximum value among the factor scores. For measurement intercepts, the additional outputs are the observed means difference (`diff_mean`) and the proportion of the differences in the intercepts over the observed means differences (`propdiff`). For error variances, the additional outputs are the proportion of the difference in error variances over the difference in observed variances (`propdiff`).

2. `results`: Statistical tests as well as the change in CFI are provided. χ^2 and p value are provided for all methods.

3. `models`: The submodels used in the `free` and `fix` methods, as well as the nested and parent models. The nested and parent models will be changed from the original models if `free` or `fit` arguments are specified.

### Author(s)

Sunthud Pornprasertmanit (psunthud@gmail.com)

### References

Millsap, R. E., & Olivera-Aguilar, M. (2012). Investigating measurement invariance using confirmatory factor analysis. In R. H. Hoyle (Ed.), Handbook of structural equation modeling (pp. 380–392). New York, NY: Guilford.

### See Also

`measurementInvariance` for measurement invariance for continuous variables; `measurementInvarianceCat` for measurement invariance for categorical variables; `lavTestWald` for multivariate Wald test

### Examples

    ## Conduct weak invariance testing manually by using fixed-factor
    ## method of scale identification

    library(lavaan)

    conf <- "
    f1 =~ NA*x1 + x2 + x3
    f2 =~ NA*x4 + x5 + x6
    f1 ~~ c(1, 1)*f1
    f2 ~~ c(1, 1)*f2
    "

    weak <- "
    f1 =~ NA*x1 + x2 + x3
    f2 =~ NA*x4 + x5 + x6
    f1 ~~ c(1, NA)*f1
    f2 ~~ c(1, NA)*f2
    "

    configural <- cfa(conf, data = HolzingerSwineford1939, std.lv = TRUE, group="school")
    weak <- cfa(weak, data = HolzingerSwineford1939, group="school", group.equal="loadings")
    models <- list(fit.configural = configural, fit.loadings = weak)
    partialInvariance(models, "metric")

    ## Not run:
    partialInvariance(models, "metric", free = "x5") # "x5" is free across groups in advance
    partialInvariance(models, "metric", fix = "x4") # "x4" is fixed across groups in advance

    ## Use the result from the measurementInvariance function
    HW.model <- ' visual =~ x1 + x2 + x3
                  textual =~ x4 + x5 + x6
                  speed =~ x7 + x8 + x9 '

    models2 <- measurementInvariance(model = HW.model, data=HolzingerSwineford1939,
                                     group="school")
    partialInvariance(models2, "scalar")

    ## Conduct weak invariance testing manually by using fixed-factor
    ## method of scale identification for dichotomous variables

    f <- rnorm(1000, 0, 1)
    u1 <- 0.9*f + rnorm(1000, 1, sqrt(0.19))
    u2 <- 0.8*f + rnorm(1000, 1, sqrt(0.36))
    u3 <- 0.6*f + rnorm(1000, 1, sqrt(0.64))
    u4 <- 0.7*f + rnorm(1000, 1, sqrt(0.51))
    u1 <- as.numeric(cut(u1, breaks = c(-Inf, 0, Inf)))
    u2 <- as.numeric(cut(u2, breaks = c(-Inf, 0.5, Inf)))
    u3 <- as.numeric(cut(u3, breaks = c(-Inf, 0, Inf)))
    u4 <- as.numeric(cut(u4, breaks = c(-Inf, -0.5, Inf)))
    g <- rep(c(1, 2), 500)
    dat2 <- data.frame(u1, u2, u3, u4, g)

    configural2 <- "
    f1 =~ NA*u1 + u2 + u3 + u4
    u1 | c(t11, t11)*t1
    u2 | c(t21, t21)*t1
    u3 | c(t31, t31)*t1
    u4 | c(t41, t41)*t1
    f1 ~~ c(1, 1)*f1
    f1 ~ c(0, NA)*1
    u1 ~~ c(1, 1)*u1
    u2 ~~ c(1, NA)*u2
    u3 ~~ c(1, NA)*u3
    u4 ~~ c(1, NA)*u4
    "

    outConfigural2 <- cfa(configural2, data = dat2, group = "g",
                          parameterization = "theta", estimator = "wlsmv",
                          ordered = c("u1", "u2", "u3", "u4"))

    weak2 <- "
    f1 =~ NA*u1 + c(f11, f11)*u1 + c(f21, f21)*u2 + c(f31, f31)*u3 + c(f41, f41)*u4
    u1 | c(t11, t11)*t1
    u2 | c(t21, t21)*t1
    u3 | c(t31, t31)*t1
    u4 | c(t41, t41)*t1
    f1 ~~ c(1, NA)*f1
    f1 ~ c(0, NA)*1
    u1 ~~ c(1, 1)*u1
    u2 ~~ c(1, NA)*u2
    u3 ~~ c(1, NA)*u3
    u4 ~~ c(1, NA)*u4
    "

    outWeak2 <- cfa(weak2, data = dat2, group = "g", parameterization = "theta",
                    estimator = "wlsmv", ordered = c("u1", "u2", "u3", "u4"))
    modelsCat <- list(fit.configural = outConfigural2, fit.loadings = outWeak2)

    partialInvarianceCat(modelsCat, type = "metric")

    partialInvarianceCat(modelsCat, type = "metric", free = "u2")
    partialInvarianceCat(modelsCat, type = "metric", fix = "u3")

    ## Use the result from the measurementInvarianceCat function

    model <- ' f1 =~ u1 + u2 + u3 + u4
               f2 =~ u5 + u6 + u7 + u8'

    modelsCat2 <- measurementInvarianceCat(model = model, data = datCat, group = "g",
    	                                      parameterization = "theta",
    	                                      estimator = "wlsmv", strict = TRUE)

    partialInvarianceCat(modelsCat2, type = "scalar")

    ## End(Not run)

[Package semTools version 0.5-1 Index]