Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Measurement Invariance - Compare The Latent Means and Variances

    I am trying to do SEM to examine measurement invariance across gender groups (male = 0, female = 1, vs. others = 2). The model I am trying to examine is a two-factor structure (latent variables are A and B), each factor consisting of 6 items (a1 a2 a3 a4 a5 a6 and b1 b2 b3 b4 b5 b6). Each item consists of 5-point Likert scale. I am referencing this webpage https://stats.oarc.ucla.edu/stata/fa...mand-stata-12/ to write my code. The code I used for scalar invariance was this:

    sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a1 <- A _cons@0) (b1 <- B _cons@0), covstruct(_lexogenous, diagonal) group(gender) mean(A) mean(B) ginvariant(mcoef mcons) latent(A B ) cov( A*B ) nocapslatent standardized iterate(100)

    When I run this code, everything runs fine, but the problem is that the variances of both latent factors across groups – which means var(A) and var(B) from all three groups (i.e., 0, 1, 2 of gender) – are all 1. It doesn’t say “constrained.” They are just fixed at 1. So I tried to run configural invariance with exactly the same code except for using ginvariant(none) and metric invariance again with the same code except for using ginvariant(mcoef), and all of the var(A) and var(B) from all three groups are fixed at 1, Which leads to my first question.

    Question#1) Is this normal? I don’t think the variances should be fixed. What code should I use to examine scalar invariance in this case?

    Question#2) Relatedly, I would like to report the variances of A and B from each group from the scalar invariance model. But since it is all fixed at 1, I can’t. What code should I use to get the variances of each latent factor from each group from scalar invariance?

    Subsequently, I ran “estat ginvariant” after the scalar invariance was achieved to examine the latent mean and variance differences. 'Tests for group invariance of parameters' table showed that there were latent mean and variance differences across groups. That said, I would like to report the estimated latent means and variances of each group. Which leads to my third question.

    Question#3) What code should I use to fix the mean of one group to 0, and let the mean of the other two groups to vary freely?

    I tried using “sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a1 <- A _cons@0) (b1 <- B _cons@0), covstruct(_lexogenous, diagonal) group(gender) mean(A) mean(B) ginvariant(mcoef mcons meanex) latent(A B ) cov( A*B ) nocapslatent standardized iterate(100)” as the website suggests, but it still gives me mean(A) and mean(B) values for all three groups.

    Another approach I tried was the following code, but it also doesn’t work.

    constraint define 1 _b[A@gender == 0:_cons] = 0
    constraint define 2 _b[A@ gender ==1:_cons]
    constraint define 3 _b[A@ gender ==1:_cons]
    sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a1 <- A _cons@0) (b1 <- B _cons@0), covstruct(_lexogenous, diagonal) group(gender) mean(A) mean(B) ginvariant(mcoef mcons) latent(A B ) cov( A*B ) nocapslatent standardized iterate(100) constraint (1 2 3)

    Question#4) What code should I use to fix the variance of one group to 1, and let the variances of the other two groups to vary freely? I tried using the constraints or adding the code covex to ginvariant(covex) - like the website suggests-, but since all variances are already fixed to 1 in all my models, I am not sure what to do. Whatever I try to do, all of the variances are always fixed at 1 across 0, 1, 2 groups.

    I have spent the entire week to look for solutions, and I am still at a loss. Could you give me some clarifications on what to do here? Please let me know if you need any additional info on any thing!

    Thank you!
    Last edited by So Kang; 30 Sep 2024, 04:36.

  • #2
    Originally posted by So Kang View Post
    I am referencing this webpage https://stats.oarc.ucla.edu/stata/fa...mand-stata-12/ to write my code. The code I used for scalar invariance was this:

    sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a1 <- A _cons@0) (b1 <- B _cons@0), covstruct(_lexogenous, diagonal) group(gender) mean(A) mean(B) ginvariant(mcoef mcons) latent(A B ) cov( A*B ) nocapslatent standardized iterate(100)

    . . . the problem is that the variances of both latent factors across groups – which means var(A) and var(B) from all three groups (i.e., 0, 1, 2 of gender) – are all 1. It doesn’t say “constrained.” They are just fixed at 1. So I tried to run configural invariance with exactly the same code except for using ginvariant(none) . . . and all of the var(A) and var(B) from all three groups are fixed at 1, Which leads to my first question.

    Question#1) Is this normal? I don’t think the variances should be fixed. What code should I use to examine scalar invariance in this case?
    Starting with just your first question for now: remove the option standardized.

    More generally, you're deviating from the code shown in the UCLA website that your hyperlink points to. For example, you add a specification to have a diagonal covariance structure for the exogenous latent factors (off-diagonal elements are zero) but then go ahead and specify a covariance parameter for the A and B latent factors.

    There are others, for example, naming the two latent factors in upper-case, but then specifying nocapslatent.

    I recommend hewing a little more closely to what's shown in the referenced Web page.

    Comment


    • #3
      Thank you so much. I spent a lot of time exploring what to do, which led to these unnecessary and unsuitable codes.

      I removed the option standardized, and it resolved the issue with variances fixed to 1. I also removed diagonal covariance structure for the exogenous latent factors, and nocapslatent. I kept the covariance parameter for the A and B latent factors because it was theoretically necessary. This solved my questions #1 and #2. Could you also help with the questions 3 and 4?

      Question#3) What code should I use to fix the mean of one group (lets' say group 0 in gender) to 0, and let the mean of the other two groups to vary freely? I tried using constraints related codes such as below, and it is not working.
      constraint define 1 _b[A@ gender == 0:_cons] = 0
      constraint define 2 _b[A@ gender == 1:_cons]
      constraint define 3 _b[A@ gender == 2:_cons]
      constraint define 4 _b[B@ gender == 0:_cons] = 0
      constraint define 5 _b[B@ gender == 1:_cons]
      constraint define 6 _b[B@ gender == 2:_cons]

      Question#4) What code should I use to fix the variance of one group to 1, and let the variances of the other two groups to vary freely?

      Thank you so much again!

      Comment


      • #4
        Originally posted by So Kang View Post
        Could you also help with the questions 3 and 4?

        Question#3) What code should I use to fix the mean of one group (lets' say group 0 in gender) to 0, and let the mean of the other two groups to vary freely?
        This will do it:
        Code:
        sem ///
            (a? <- A) (b? <- B) ///
            (a1 <- A _cons@0) (b1 <- B _cons@0), ///
            group(gender) ginvariant(none)
        By default the latent factor means of the first group are constrained to zero, and so you don't need to specify any constraints explicitly in order to accomplish this..

        Question#4) What code should I use to fix the variance of one group to 1, and let the variances of the other two groups to vary freely?
        This:
        Code:
        constraint define 1 [/]var(A)#0bn.gender = 1
        constraint define 2 [/]var(B)#0bn.gender = 1
        sem ///
            (a? <- A) (b? <- B) ///
            (a1 <- A _cons@0) (b1 <- B _cons@0), constraints(1/2) ///
            group(gender) ginvariant(none)

        Comment


        • #5
          Thank you for your support again. I tried these code, and it did work in fixing the means, but not variance. I have three follow-up questions. I am hoping that these will be the last questions bothering you.


          The code I put in for the mean was: "sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a? <- A) (b? <-B) (a1 <- A _cons@0) (b1 <- B _cons@0), group(gender) ginvariant(none) latent(A B ) cov( A*B ) iterate(100)"
          The code I put in for the variance was: "
          constraint define 1 [/]var(A)#0bn.gender = 1 constraint define 2 [/]var(B)#0bn.gender = 1 sem (A -> a1 a2 a3 a4 a5 a6,) (B -> b1 b2 b3 b4 b5 b6,) (a? <- A) (b? <-B) (a1 <- A _cons@0) (b1 <- B _cons@0), group(gender) ginvariant(none) latent(A B ) cov( A*B ) iterate(100)"


          Question 1. Could you clarify why "(a? <- A) (b? <-B)" is necessary and what it means? I want to make sure that I am understanding the code!

          Question 2. I deleted "mean(A) mean(B)" to follow your suggestion. But in my original code from the first thread, I did include "mean(A) mean(B)," could you help me understand what including these codes do? I think I started including them after trying to build the SEM in the Stata by building the model figure function.

          Question 3. What if I want to hold the mean of the other group fixed? Is there any other way other than recoding the gender variable?

          Question 4. Since fixing the variance, did not work, could you suggest any other ways to fix the variance of one group to 1?

          Thank you so much again!

          So Kang

          Comment


          • #6
            Originally posted by So Kang View Post
            I tried these code, and it did work in fixing the means, but not variance.
            What do you mean that it didn't work for fixing the variance? It certainly works for me to do what you asked for, which was "to fix the variance of one group to 1, and let the variances of the other two groups to vary freely" . . . although that almost certainly isn't what you need to do in order to determine invariance in the latent factor variances. See below for more on both of these.

            Question 1. Could you clarify why "(a? <- A) (b? <-B)" is necessary and what it means? I want to make sure that I am understanding the code!
            It is an example of varlist syntax that takes advantage of Stata's variable abbreviation feature. See help varlist for more information.

            Question 2. I deleted "mean(A) mean(B)" to follow your suggestion. But in my original code from the first thread, I did include "mean(A) mean(B)," could you help me understand what including these codes do?
            To find out more about their purpose, see the help file. sem's group() option automatically calls for estimating means, and that's why I omit them.

            Question 3. What if I want to hold the mean of the other group fixed? Is there any other way other than recoding the gender variable?
            You might be able to free the default constraint and impose an alternative constraint with the means() option (again see its help file linked to above), but I don't see what doing that will accomplish practically—the three means are not inclusively estimable.

            Question 4. Since fixing the variance, did not work, could you suggest any other ways to fix the variance of one group to 1?
            Again, I don't know what you mean by "did not work". It certainly works for me. Run the code below to see that. (Begin at the "Begin here" comment. The code above just creates an artificial dataset for illustration inasmuch as you didn't furnish yours.)
            Code:
            version 18.0
            
            clear *
            
            // seedem
            set seed 895298638
            
            quietly drawnorm a b, double corr(1 0.5 \ 0.5 1) n(500)
            generate byte gender = mod(_n, 3)
            
            // Two-factor CFA with six-level ordered-categorical indicator variables
            foreach f in a b {
                forvalues i = 1/6 {
                    generate double lat`f'`i' = `f' + rnormal()
                    generate byte `f'`i' = 0
                    forvalues cut = 1/4 {
                        quietly replace `f'`i' = `f'`i' + 1 if `cut' / 5 > normal(lat`f'`i')
                    }
                }
            }
            keep gender a? b?
            
            *
            * Begin here
            *
            // Here's what you asked to do
            constraint define 1 [/]var(A)#0bn.gender = 1
            constraint define 2 [/]var(B)#0bn.gender = 1
            sem ///
                (a? <- A) (b? <- B) ///
                (a1 <- A _cons@0) (b1 <- B _cons@0), constraints(1/2) ///
                group(gender) ginvariant(none)
            
            // This is what I suspect you intend to do
            sem ///
                (a? <- A) (b? <- B) ///
                (a1 <- A _cons@0) (b1 <- B _cons@0), ///
                group(gender) ginvariant(covex)
            
            exit
            You don't have to run it: the do-file and its log file are attached. You can look at the latter to confirm that it fixes the latent factor variances in the first group as requested.

            As I alluded to above, it's not clear to me what you hope to accomplish by arbitrarily fixing the variances of the latent factors in one group to one. If you want to assess their invariance, then I recommend just eyeballing their values in the unconstrained model. If you have a journal referee to appease, then you can fit the unconstrained model, save it with estimates store, fit the equality-constrained model as shown above and then perform a null hypothesis significance test to compare them using lrtest.
            Attached Files

            Comment


            • #7
              Thank you so much! The do files and log files were so helpful in figuring everything out. I think I understand almost everything, and I was able to fix the variances of one group 1, while freeing others with the constraints code. My remaining questions are:

              1) When I run the code involving covex myself, I get a result that does not constraints variances of any group to 1. When I look at your log file, it is also not fixing the variances of any of the groups to 1. What does it do then? Am I missing something from the table?

              2) Just like in your log file, when I run the code with the constraints to fix the variance of one group to 1, it constraints both means and variances of group 0 to 0 and 1, respectively. Based on my understanding of the sem codes (which was possible with your help), I think it is automatically fixing the means of the group 0 to zero. Is there anyway that we can let all means of the three groups free, and only constrain the variance of one group to 1?

              I am hoping that these are the last batch of questions bothering you. Thank you so much again!!!

              Comment


              • #8
                Originally posted by So Kang View Post
                1) . . . the code involving covex . . . is also not fixing the variances of any of the groups to 1. What does it do then?
                As stated in the help file for sem's group options, "The ginvariant(pclassname) option specifies which parameters are to be constrained to be equal across the groups." In your case with a CFA, specifying covex for this option constrains the respective latent-factor variances to be equal between groups.

                2) . . .Is there anyway that we can let all means of the three groups free, and only constrain the variance of one group to 1?
                The following will do that.
                Code:
                constraint define 1 [/]var(A)#0bn.gender = 1
                constraint define 2 [/]var(B)#0bn.gender = 1
                sem ///
                    (a? <- A) (b? <- B) ///
                    (a1 <- A _cons@0) (b1 <- B _cons@0), constraints(1/2) ///
                    group(gender) means(A B) ginvariant(none)
                I'm curious as to why do you want to do this.

                The title of your thread is Measurement Invariance - Compare The Latent Means and Variances. My understanding of the way in which latent-factor means and variances are customarily compared between groups (and the one contemplated by Stata's sem , group() options) is that an SEM that constrains the respective parameter estimates to be equal is fitted. And that is compared to the corresponding unconstrained model using a likelihood ratio test.

                By constraining one group's latent factors' variances to some arbitrary value (one), you're obviously interested in something else, something that I'm not familiar with.
                Last edited by Joseph Coveney; 06 Oct 2024, 05:58.

                Comment


                • #9
                  Thank you for clarifying everything. In regards to #1, I think I was confusing between constraining them to get equal, and fixing them to 1, and now I get it. The reason why I am trying to do the analysis related to the second question is that several papers doing a similar analysis as mine (i.e., measurement invariance across the group) reported this values (i.e., the values of mean and variance of one group while putting constraints on means and variances of the other groups), after conducting the likelihood ratio test.

                  Thank you so much again!!

                  Comment

                  Working...
                  X