library(learnr) library(learnSEM) knitr::opts_chunk$set(echo = FALSE) library(lavaan) library(semPlot) data(meaningdata)
This section of the course examines the nature of using multiple scales to assess the same underlying latent traits. We will cover the procedure to examine if multiple methods converge on measuring the same traits, if the traits are divergent (i.e., not the same), and if the methods measure different portions of each latent trait. You will learn how to interpret parameter estimates in this fashion as well. The learning outcomes are:
~~
parametersYou can use vignette("lecture_mtmm", "learnSEM")
to view these notes in R.
In this next section, you will answer questions using the R code blocks provided. Be sure to use the solution
option to see the answer if you need it!
Please enter your name for submission. If you do not need to submit, just type anything you'd like in this box.
question_text( "Student Name:", answer("Your Name", correct = TRUE), incorrect = "Thanks!", try_again_button = "Modify your answer", allow_retry = TRUE )
The data is provided for you below, and it has been loaded for you in the background, along with the lavaan
and semPlot
libraries. The data contains three scales that measure meaning and purpose: The Meaning in Life Questionnaire, the Purpose in Life Questionnaire, and the Seeking of Noetic Goals test.
head(meaningdata)
The mapping of traits and methods are:
In this section, we will start with step one of the MTMM models. You should build, analyze, and summarize the Correlated Traits / Correlated Methods model below. You should save this model as step1.model
to use later. Save the model output as step1.fit
. Do not forget that you need to standardize on the latent variable! We will do model comparison after defining each model.
Sometimes, with a lot of code, the helpful answer cuts off. You can use control + a to highlight all the text, then control + c to copy it, and control + v to paste it in the box to view all of it at once. Don't forget you can go back to the previous page to look at the mappings of traits and methods to each other.
step1.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ' step1.fit <- cfa(model = step1.model, data = meaningdata, std.lv = TRUE) summary(step1.fit, rsquare = TRUE, fit.measures = TRUE, standardized = TRUE)
In this step, you want to create step2.fit
for the methods only model. Save the model output as step2.fit
, and summarize the output.
step2.model <- ' mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ' step2.fit <- cfa(model = step2.model, data = meaningdata, std.lv = TRUE) summary(step2.fit, rsquare = TRUE, fit.measures = TRUE, standardized = TRUE)
In this step, you want to create step3.fit
perfectly correlated traits model. Save the model output as step3.fit
, and summarize the output.
step3.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##perfect traits meaning ~~ 1*purpose ' step3.fit <- cfa(model = step3.model, data = meaningdata, std.lv = TRUE) summary(step3.fit, rsquare = TRUE, fit.measures = TRUE, standardized = TRUE)
In this step, you want to create step4.fit
uncorrelated methods model. Save the model output as step4.fit
, and summarize the output.
step4.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##methods covariances to zero mlq ~~ 0*song mlq ~~ 0*pil song ~~ 0*pil ' step4.fit <- cfa(model = step4.model, data = meaningdata, std.lv = TRUE) summary(step4.fit, rsquare = TRUE, fit.measures = TRUE, standardized = TRUE)
We can use kable()
from the knitr
library to help us build a table to compare models. You will want to change the 1:5
to the appropriate model step using fitmeasures
to grab the fit statistics mentioned. An example is provided below. There are lots of ways to make these types of tables, including broom
. Additionally, flextable
is a great table package as well. Here's just an example of how one might summarize their models.
step1.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ' step1.fit <- cfa(model = step1.model, data = meaningdata, std.lv = TRUE) step2.model <- ' mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ' step2.fit <- cfa(model = step2.model, data = meaningdata, std.lv = TRUE) step3.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##perfect traits meaning ~~ 1*purpose ' step3.fit <- cfa(model = step3.model, data = meaningdata, std.lv = TRUE) step4.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##methods covariances to zero mlq ~~ 0*song mlq ~~ 0*pil song ~~ 0*pil ' step4.fit <- cfa(model = step4.model, data = meaningdata, std.lv = TRUE)
library(knitr) tableprint <- matrix(NA, nrow = 4, ncol = 6) colnames(tableprint) <- c("Model", "Chi-Square", "df", "RMSEA", "SRMR", "CFI") ##replace the 1:5 with the appropriate code ##the code should be fitmeasures(step1.fit, c("chisq", "df", "rmsea", "srmr", "cfi")) ##add that code for each section tableprint[1, ] = c("Model 1 - Correlated traits and methods", 1:5) tableprint[2, ] = c("Model 2 - No traits, correlated methods", 1:5) tableprint[3, ] = c("Model 3 - Perfectly correlated traits, correlated methods", 1:5) tableprint[4, ] = c("Model 4 - Correlated traits, uncorrelated methods", 1:5) kable(tableprint)
library(knitr) tableprint <- matrix(NA, nrow = 4, ncol = 6) colnames(tableprint) <- c("Model", "Chi-Square", "df", "RMSEA", "SRMR", "CFI") ##replace the 1:5 with the appropriate code ##the code should be fitmeasures(step1.fit, c("chisq", "df", "rmsea", "srmr", "cfi")) ##add that code for each section tableprint[1, ] = c("Model 1 - Correlated traits and methods", fitmeasures(step1.fit, c("chisq", "df", "rmsea", "srmr", "cfi"))) tableprint[2, ] = c("Model 2 - No traits, correlated methods", fitmeasures(step2.fit, c("chisq", "df", "rmsea", "srmr", "cfi"))) tableprint[3, ] = c("Model 3 - Perfectly correlated traits, correlated methods", fitmeasures(step3.fit, c("chisq", "df", "rmsea", "srmr", "cfi"))) tableprint[4, ] = c("Model 4 - Correlated traits, uncorrelated methods", fitmeasures(step4.fit, c("chisq", "df", "rmsea", "srmr", "cfi"))) kable(tableprint)
Using CFI change, what do the model results suggest? For each step note if the models are different, and if that supports/does not support convergent and divergent validity.
question_text( "Model 1 versus Model 2: Convergent Validity:", answer("Model 1 is better, which supports convergent validity.", correct = TRUE), incorrect = "Model 1 is better, supporting convergent validity.", try_again_button = "Modify your answer", allow_retry = TRUE )
question_text( "Model 1 versus Model 3: Divergent Validity:", answer("Model 1 is the same as Model 3, which does not support divergent validity.", correct = TRUE), incorrect = "Model 1 is the same as Model 3, which does not support divergent validity.", try_again_button = "Modify your answer", allow_retry = TRUE )
question_text( "Model 1 versus Model 4: Divergent Validity:", answer("Model 1 is better than Model 4, which is not what we want. Therefore, it does not support convergent validity.", correct = TRUE), incorrect = "Model 1 is better than Model 4, which is not what we want. Therefore, it does not support convergent validity.", try_again_button = "Modify your answer", allow_retry = TRUE )
Print out the parameterestimates
for Model 1 step1.fit
.
step1.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ' step1.fit <- cfa(model = step1.model, data = meaningdata, std.lv = TRUE) step2.model <- ' mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ' step2.fit <- cfa(model = step2.model, data = meaningdata, std.lv = TRUE) step3.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##perfect traits meaning ~~ 1*purpose ' step3.fit <- cfa(model = step3.model, data = meaningdata, std.lv = TRUE) step4.model <- ' meaning =~ m1 + m2 + m5 + m10 + s1 + s9 + p4 + p17 purpose =~ m3 + m4 + m6 + m8 + m9 + s2 + s8 + p3 + p20 mlq =~ m1 + m2 + m5 + m10 + m3 + m4 + m6 + m8 + m9 song =~ s1 + s9 + s2 + s8 pil =~ p4 + p17 + p3 + p20 ##cross covariances to zero meaning ~~ 0*mlq meaning ~~ 0*song meaning ~~ 0*pil purpose ~~ 0*mlq purpose ~~ 0*song purpose ~~ 0*pil ##methods covariances to zero mlq ~~ 0*song mlq ~~ 0*pil song ~~ 0*pil ' step4.fit <- cfa(model = step4.model, data = meaningdata, std.lv = TRUE)
parameterestimates(step1.fit, standardized = TRUE)
question_text( "Are the parameter estimates for the traits higher than the ones for the methods?", answer("About half and half.", correct = TRUE), incorrect = "There is a mix of ones that are higher for traits than methods.", try_again_button = "Modify your answer", allow_retry = TRUE )
question_text( "Examine the correlations between traits. Do the correlations support divergent validity of the traits?", answer("Nope! It's nearly one.", correct = TRUE), incorrect = "Nope! It's nearly one.", try_again_button = "Modify your answer", allow_retry = TRUE )
question_text( "Examine the correlation between the methods. Do the correlations support the divergent validity of the methods?", answer("The MLQ and SONG are correlated but otherwise they are uncorrelated.", correct = TRUE), incorrect = "The MLQ and SONG are correlated but otherwise they are uncorrelated.", try_again_button = "Modify your answer", allow_retry = TRUE )
On this page, you will create the submission for your instructor (if necessary). Please copy this report and submit using a Word document or paste into the text window of your submission page. Click "Generate Submission" to get your work!
encoder_logic()
encoder_ui()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.