38. Modello LCS bivariato#

I modelli LCSM sono stati sviluppati principalmente per studiare le associazioni sequenziali nel tempo tra due o più processi che cambiano nel tempo. In altre parole, le equazioni di cambiamento latente possono essere estese per includere effetti derivanti da variabili aggiuntive per modellare congiuntamente processi multipli di sviluppo in corso (McArdle, 2001; McArdle & Hamagami, 2001). Considereremo qui un modello LCS bivariato con parametri di accoppiamento cambiamento-cambiamento ritardati. Il seguene path diagram è fornito da Wiedemann et al. [WTKovsirE22].

_images/lcsm_bivariato.png

Fig. 38.1 Diagramma di percorso semplificato per un modello LCS bivariato con parametri di accoppiamento cambiamento-cambiamento ritardati (ad esempio, da dx2 a dy3). Quadrati bianchi = variabili osservate; cerchi verdi = punteggi veri latenti (prefisso ‘l’); cerchi blu = punteggi di cambiamento latenti (prefisso ‘d’); cerchi gialli = fattori di cambiamento latente costanti. Frecce direzionali = Regressioni; frecce bidirezionali = covarianze. I punteggi unici (\(ux_t\) e \(uy_t\)) e le varianze uniche (\(σ^2_{ux}\) e \(σ^2_{uy}\)) non sono mostrati in questa figura per semplicità.#

Come in precedenza per il caso del modello univariato, il modello LCSM bivariato include, per ciascuna di due variabili misurate nel tempo, un fattore di cambiamento costante (alpha_constant), un fattore di cambiamento proporzionale (beta) e l’autoregressione dei punteggi di cambiamento (phi). L’aspetto nuovo riguarda i parametri di “accoppiamento”. Per i modelli LCSM bivariati, tali parametri modellano le interazioni tra le variabili \(X\) e \(Y\). I test su tali parametri consentono di affrontare la seguente domanda della ricerca: le variazioni della variabile Y al momento (t) sono determinate dalle variazioni della variabile X al momento precedente (t-1)? E viceversa. Oppure tutte e due le condizioni insieme. I test statistici sui parametri di accoppiamento consentono di rispondere alle domande precedenti.

38.1. Illustrazione#

Per illustrare l’adattamento e l’interpretazione dei modelli LCS bivariati, analizziamo i dati longitudinali di matematica che sono stati utilizzati nel Capitolo 17 di [GRE16]. I dati longitudinali di matematica sono stati raccolti dall’NLSY-CYA (Center for Human Resource Research, 2009) e i punteggi di matematica provengono dal PIAT (Dunn & Markwardt, 1970). Vengono anche misurati i punteggi di comprensione nella lettura dal secondo all’ottavo grado scolastico. Il grado scolastico al momento del test viene utilizzato come metrica temporale e varia dalla seconda elementare (grado 2) alla terza media (grado 8).

Leggiamo i pacchetti necessari.

source("_common.R")
suppressPackageStartupMessages({
    library("lavaan")
    library("semPlot")
    library("knitr")
    library("markdown")
    library("patchwork")
    library("psych")
    library("DT")
    library("kableExtra")
    library("lme4")
    library("lcsm")
    library("tidyr")
    library("stringr")
})
set.seed(12345)

Importiamo i dati in R utilizzando un file messo a disposizione dagli autori.

nlsy_multi_data <- read.table(file = "data/nlsy_math_hyp_wide_R.dat", na.strings = ".")
names(nlsy_multi_data) <- c(
    "id", "female", "lb_wght", "anti_k1",
    "math2", "math3", "math4", "math5", "math6", "math7", "math8",
    "comp2", "comp3", "comp4", "comp5", "comp6", "comp7", "comp8",
    "rec2", "rec3", "rec4", "rec5", "rec6", "rec7", "rec8",
    "bpi2", "bpi3", "bpi4", "bpi5", "bpi6", "bpi7", "bpi8",
    "asl2", "asl3", "asl4", "asl5", "asl6", "asl7", "asl8",
    "ax2", "ax3", "ax4", "ax5", "ax6", "ax7", "ax8",
    "hds2", "hds3", "hds4", "hds5", "hds6", "hds7", "hds8",
    "hyp2", "hyp3", "hyp4", "hyp5", "hyp6", "hyp7", "hyp8",
    "dpn2", "dpn3", "dpn4", "dpn5", "dpn6", "dpn7", "dpn8",
    "wdn2", "wdn3", "wdn4", "wdn5", "wdn6", "wdn7", "wdn8",
    "age2", "age3", "age4", "age5", "age6", "age7", "age8",
    "men2", "men3", "men4", "men5", "men6", "men7", "men8",
    "spring2", "spring3", "spring4", "spring5", "spring6", "spring7", "spring8",
    "anti2", "anti3", "anti4", "anti5", "anti6", "anti7", "anti8"
)

Definiamo due vettori che serviranno per codificare le variabili math e rec.

x_var_list <- paste0("math", 2:8)
y_var_list <- paste0("rec", 2:8)

Estraiamo dal DataFrame originale solo le variabili relative alla matematica e alla capacità di lettura, oltre alla variabile id.

nlsy_multi_data <- nlsy_multi_data[, c("id", x_var_list, y_var_list)]
glimpse(nlsy_multi_data)
Rows: 933
Columns: 15
$ id    <int> 201, 303, 2702, 4303, 5002, 5005, 5701, 6102, 6801, 6802, 6803, …
$ math2 <int> NA, 26, 56, NA, NA, 35, NA, NA, NA, NA, NA, 35, NA, NA, NA, NA, …
$ math3 <int> 38, NA, NA, 41, NA, NA, 62, NA, 54, 55, 57, NA, 34, NA, 54, 66, …
$ math4 <int> NA, NA, 58, 58, 46, 50, 61, 55, NA, NA, NA, 59, 50, 48, NA, NA, …
$ math5 <int> 55, 33, NA, NA, NA, NA, NA, 67, 62, 66, 70, NA, NA, NA, NA, 65, …
$ math6 <int> NA, NA, NA, NA, 54, 60, NA, NA, NA, NA, NA, NA, NA, NA, 64, NA, …
$ math7 <int> NA, NA, NA, NA, NA, NA, NA, 81, 66, 68, NA, NA, NA, NA, 63, NA, …
$ math8 <int> NA, NA, 80, NA, 66, 59, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ rec2  <int> NA, 26, 33, NA, NA, 47, NA, NA, NA, NA, NA, 33, NA, NA, NA, NA, …
$ rec3  <int> 35, NA, NA, 34, NA, NA, 64, NA, 53, 66, 68, NA, 49, NA, 54, 55, …
$ rec4  <int> NA, NA, 50, 43, 46, 67, 70, 50, NA, NA, NA, 63, 53, 37, NA, NA, …
$ rec5  <int> 52, 35, NA, NA, NA, NA, NA, 69, 76, 66, 70, NA, NA, NA, NA, 78, …
$ rec6  <int> NA, NA, NA, NA, 70, 75, NA, NA, NA, NA, NA, NA, NA, NA, 71, NA, …
$ rec7  <int> NA, NA, NA, NA, NA, NA, NA, 71, 64, 75, NA, NA, NA, NA, 74, NA, …
$ rec8  <int> NA, NA, 66, NA, 77, 78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …

Esaminiamo le statistiche descrittive.

psych::describe(nlsy_multi_data)
A psych: 15 × 13
varsnmeansdmediantrimmedmadminmaxrangeskewkurtosisse
<int><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
id 1933532334.897113.280208e+05506602.0520130.77108391999.440020112566011256400 0.28416593-0.907887241.073892e+04
math2 2335 32.608961.028600e+01 32.0 32.27509 10.3782 12 60 48 0.26866808-0.460012965.619840e-01
math3 3431 39.883991.029949e+01 41.0 39.88406 10.3782 13 67 54-0.05209289-0.325916834.961091e-01
math4 4378 46.169311.016510e+01 46.0 46.22039 8.8956 18 70 52-0.05957828-0.075966535.228366e-01
math5 5372 49.774199.471909e+00 48.0 49.76510 8.8956 23 71 48 0.04254744-0.338112584.910956e-01
math6 6390 52.723089.915594e+00 50.5 52.38462 9.6369 24 78 54 0.25104168-0.380861525.020956e-01
math7 7173 55.352601.062727e+01 53.0 55.08633 11.8608 31 81 50 0.21484791-0.970962238.079765e-01
math8 8142 57.830991.153101e+01 56.0 57.42982 12.6021 26 81 55 0.15905447-0.522296749.676607e-01
rec2 9333 34.681681.036303e+01 34.0 33.89888 10.3782 15 79 64 0.80847754 1.058314295.678904e-01
rec310431 41.290021.146468e+01 40.0 40.80290 11.8608 19 81 62 0.42959720 0.052936115.522343e-01
rec411376 47.555851.233346e+01 47.0 47.16556 11.8608 21 83 62 0.32275983-0.074290876.360496e-01
rec512370 52.913511.303500e+01 52.0 52.86149 13.3434 21 84 63 0.03724543-0.483776046.776573e-01
rec613389 55.994861.261831e+01 56.0 55.92971 13.3434 21 82 61-0.02930758-0.370339886.397735e-01
rec714173 60.560691.360801e+01 62.0 61.15827 14.8260 23 84 61-0.39192427-0.532347041.034598e+00
rec815142 64.373241.215246e+01 66.0 65.10526 13.3434 32 84 52-0.50329787-0.558236901.019812e+00

Esaminiamo le traiettorie di crescita nel campione per la matematica.

plot_trajectories(
    data = nlsy_multi_data,
    id_var = "id",
    var_list = x_var_list,
    xlab = "Time", ylab = "Value",
    connect_missing = FALSE,
    # random_sample_frac = 0.018,
    title_n = TRUE
)
Warning message:
“Removed 2787 rows containing missing values (`geom_line()`).”
Warning message:
“Removed 4310 rows containing missing values (`geom_point()`).”
_images/a22fd0f0e457ae90a73469705956b75d8c685a16d878585ea3043f25b6329572.png

Esaminiamo i dati di alcuni soggetti presi a caso.

plot_trajectories(
    data = nlsy_multi_data,
    id_var = "id", 
    var_list = x_var_list,
    xlab = "Time", ylab = "Value",
    connect_missing = TRUE, 
    random_sample_frac = 0.01, 
    title_n = TRUE) +
  facet_wrap(~id)
Warning message:
“Removed 40 rows containing missing values (`geom_point()`).”
_images/02784a70409a897ba523550e12e6d7ba6ddc8890b27d2196329b9dd6ebc292ac.png

Esaminiamo le curve di crescita per la comprensione nella lettura.

plot_trajectories(
    data = nlsy_multi_data,
    id_var = "id",
    var_list = y_var_list,
    xlab = "Time", ylab = "Value",
    connect_missing = FALSE,
    # random_sample_frac = 0.018,
    title_n = TRUE
)
Warning message:
“Removed 2804 rows containing missing values (`geom_line()`).”
Warning message:
“Removed 4317 rows containing missing values (`geom_point()`).”
_images/4e721f01b3ba236a78d0c561ad6fcc898ab2f0b0c006d19170219218c6ba067a.png
plot_trajectories(
    data = nlsy_multi_data,
    id_var = "id", 
    var_list = y_var_list,
    xlab = "Time", ylab = "Value",
    connect_missing = TRUE, 
    random_sample_frac = 0.01, 
    title_n = TRUE) +
  facet_wrap(~id)
Warning message:
“Removed 40 rows containing missing values (`geom_point()`).”
_images/89dcfd7e5a9c8e7f15e6554db02c67fb473d067f32971df5eff80f46fe72594a.png

Adattiamo ora quattro modelli di complessità crescente. Il primo modello ipotizza che i parametri di accoppiamento da matematica a lettura e da lettura a matematica siano pari a zero. È il modello baseline. Il secondo modello ipotizza un effetto da lettura a matematica. Il terzo modello ipotizza un effetto da matematica a lettura. Il quarto modello ipotizza la presenza di entrambi i parametri di accoppiamento.

# baseline: no coupling
multi1_lavaan_results <- fit_bi_lcsm(
    data = nlsy_multi_data,
    var_x = x_var_list,
    var_y = y_var_list,
    model_x = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    model_y = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    coupling = list(xi_lag_xy = FALSE, xi_lag_yx = FALSE)
)

# reading affects change in math
multi2_lavaan_results <- fit_bi_lcsm(
    data = nlsy_multi_data,
    var_x = x_var_list,
    var_y = y_var_list,
    model_x = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    model_y = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    coupling = list(xi_lag_xy = TRUE, xi_lag_yx = FALSE)
)

# math affects change in reading
multi3_lavaan_results <- fit_bi_lcsm(
    data = nlsy_multi_data,
    var_x = x_var_list,
    var_y = y_var_list,
    model_x = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    model_y = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    coupling = list(xi_lag_xy = FALSE, xi_lag_yx = TRUE)
)

# both
multi4_lavaan_results <- fit_bi_lcsm(
    data = nlsy_multi_data,
    var_x = x_var_list,
    var_y = y_var_list,
    model_x = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    model_y = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    coupling = list(xi_lag_xy = TRUE, xi_lag_yx = TRUE)
)
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING: some cases are empty and will be ignored:
  741”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING:
    due to missing values, some pairwise combinations have less than
    10% coverage; use lavInspect(fit, "coverage") to investigate.”
Warning message in lav_mvnorm_missing_h1_estimate_moments(Y = X[[g]], wt = WT[[g]], :
“lavaan WARNING:
    Maximum number of iterations reached when computing the sample
    moments using EM; use the em.h1.iter.max= argument to increase the
    number of iterations”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING: some cases are empty and will be ignored:
  741”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING:
    due to missing values, some pairwise combinations have less than
    10% coverage; use lavInspect(fit, "coverage") to investigate.”
Warning message in lav_mvnorm_missing_h1_estimate_moments(Y = X[[g]], wt = WT[[g]], :
“lavaan WARNING:
    Maximum number of iterations reached when computing the sample
    moments using EM; use the em.h1.iter.max= argument to increase the
    number of iterations”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING: some cases are empty and will be ignored:
  741”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING:
    due to missing values, some pairwise combinations have less than
    10% coverage; use lavInspect(fit, "coverage") to investigate.”
Warning message in lav_mvnorm_missing_h1_estimate_moments(Y = X[[g]], wt = WT[[g]], :
“lavaan WARNING:
    Maximum number of iterations reached when computing the sample
    moments using EM; use the em.h1.iter.max= argument to increase the
    number of iterations”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING: some cases are empty and will be ignored:
  741”
Warning message in lav_data_full(data = data, group = group, cluster = cluster, :
“lavaan WARNING:
    due to missing values, some pairwise combinations have less than
    10% coverage; use lavInspect(fit, "coverage") to investigate.”
Warning message in lav_mvnorm_missing_h1_estimate_moments(Y = X[[g]], wt = WT[[g]], :
“lavaan WARNING:
    Maximum number of iterations reached when computing the sample
    moments using EM; use the em.h1.iter.max= argument to increase the
    number of iterations”

È ora possibile fare un confronto tra i vari modelli. Di seguito riportiamo la statistica BIC (valori minori sono preferibili). Dalle statistiche BIC emerge che il modello baseline è da preferire.

c(
    extract_fit(multi1_lavaan_results)$bic,
    extract_fit(multi2_lavaan_results)$bic,
    extract_fit(multi3_lavaan_results)$bic,
    extract_fit(multi4_lavaan_results)$bic
)
  1. 31518.9135405017
  2. 31524.4353027844
  3. 31525.7148821952
  4. 31533.2115797344

Eseguiamo ora i test del rapporto tra verosimiglianze tra i vari modelli.

lavTestLRT(multi1_lavaan_results, multi2_lavaan_results) |>
    print()
Scaled Chi-Squared Difference Test (method = “satorra.bentler.2001”)

lavaan NOTE:
    The “Chisq” column contains standard test statistics, not the
    robust test that should be reported per model. A robust difference
    test is a function of two standard (not robust) statistics.
 
                      Df   AIC   BIC  Chisq Chisq diff Df diff Pr(>Chisq)  
multi2_lavaan_results 97 31418 31524 179.14                                
multi1_lavaan_results 98 31417 31519 180.46     3.4354       1    0.06381 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
lavTestLRT(multi1_lavaan_results, multi3_lavaan_results) |>
    print()
Scaled Chi-Squared Difference Test (method = “satorra.bentler.2001”)

lavaan NOTE:
    The “Chisq” column contains standard test statistics, not the
    robust test that should be reported per model. A robust difference
    test is a function of two standard (not robust) statistics.
 
                      Df   AIC   BIC  Chisq Chisq diff Df diff Pr(>Chisq)
multi3_lavaan_results 97 31419 31526 180.42                              
multi1_lavaan_results 98 31417 31519 180.46    0.13804       1     0.7102
lavTestLRT(multi1_lavaan_results, multi4_lavaan_results) |>
    print()
Warning message in lavTestLRT(multi1_lavaan_results, multi4_lavaan_results):
“lavaan WARNING:
    Some restricted models fit better than less restricted models;
    either these models are not nested, or the less restricted model
    failed to reach a global optimum. Smallest difference =
    -0.623373603392196”
Scaled Chi-Squared Difference Test (method = “satorra.bentler.2001”)

lavaan NOTE:
    The “Chisq” column contains standard test statistics, not the
    robust test that should be reported per model. A robust difference
    test is a function of two standard (not robust) statistics.
 
                      Df   AIC   BIC  Chisq Chisq diff Df diff Pr(>Chisq)
multi4_lavaan_results 96 31422 31533 181.08                              
multi1_lavaan_results 98 31417 31519 180.46  -0.065354       2          1

Anche in questo caso non vi è evidenza che la presenza dei fattori di accoppiamento migliori l’adattamento del modello ai dati.

Per motivi didattici, però, proseguiamo l’analisi ipotizzando una presenza di entrambe le classi di parametri di accoppiamento (da comprensione nella lettura a matematica e viceversa).

multi4_lavaan_syntax <- fit_bi_lcsm(
    data = nlsy_multi_data,
    var_x = x_var_list,
    var_y = y_var_list,
    model_x = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    model_y = list(alpha_constant = TRUE, beta = TRUE, phi = TRUE),
    coupling = list(xi_lag_xy = TRUE, xi_lag_yx = TRUE),
    return_lavaan_syntax = TRUE
)

Di seguito riportiamo il path diagram del modello prescelto.

# Plot the results
plot_lcsm(
    lavaan_object = multi4_lavaan_results,
    lavaan_syntax = multi4_lavaan_syntax,
    edge.label.cex = .9,
    lcsm_colours = TRUE,
    lcsm = "bivariate"
)
_images/c11897b5e6a3622c9eb68de4c950beead041aa1b74eb4fbd08a10a430e2d103e.png

Esaminiamo la bontà di adattamento.

extract_fit(multi4_lavaan_results)
A tibble: 1 × 8
modelchisqnparaicbiccfirmseasrmr
<chr><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
1181.08362331421.9531533.210.96752020.030837510.1195777

Notiamo che le informazioni sull’adattamento del modello fornite da lcsm indicano che il modello di cambiamento duale si adatta bene ai dati con forti indici di adattamento globale (ad esempio, RMSEA inferiore a 0.05, CFI > 0.95).

Esaminiamo i parametri.

extract_param(multi4_lavaan_results)
A tibble: 23 × 8
labelestimatestd.errorstatisticp.valuestd.lvstd.allstd.nox
<chr><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
gamma_lx1 32.35819868 0.548238059.022178430.000000e+00 3.88643028 3.88643028 3.88643028
sigma2_lx1 69.32133408 6.542908510.594880610.000000e+00 1.00000000 1.00000000 1.00000000
sigma2_ux 31.90529890 4.9765703 6.411101751.444718e-1031.90529890 0.31518680 0.31518680
alpha_g2 15.41742212 7.7034105 2.001376174.535187e-02 6.62549284 6.62549284 6.62549284
sigma2_g2 5.41485895 5.2294946 1.035445933.004607e-01 1.00000000 1.00000000 1.00000000
sigma_g2lx1 14.5658196011.7423402 1.240452872.148079e-01 0.75180965 0.75180965 0.75180965
beta_x -0.23979369 0.2707290-0.885733183.757613e-01-1.28464649-1.28464649-1.28464649
phi_x 0.03905925 3.6535591 0.010690749.914702e-01 0.05208274 0.05208274 0.05208274
gamma_ly1 33.80333452 0.519978165.009148000.000000e+00 3.69882638 3.69882638 3.69882638
sigma2_ly1 83.52013611 8.6598050 9.644574740.000000e+00 1.00000000 1.00000000 1.00000000
sigma2_uy 33.44295186 4.5480603 7.353234011.934009e-1333.44295186 0.28592740 0.28592740
alpha_j2 11.17493867 7.1824927 1.555857991.197419e-01 4.75158482 4.75158482 4.75158482
sigma2_j2 5.53112309 5.7746611 0.957826443.381503e-01 1.00000000 1.00000000 1.00000000
sigma_j2ly1 16.8459967211.8243839 1.424682831.542489e-01 0.78378050 0.78378050 0.78378050
beta_y -0.09511973 0.1915302-0.496630476.194497e-01-0.49516329-0.49516329-0.49516329
phi_y -1.07256252 3.4523130-0.310679397.560444e-01-1.60935419-1.60935419-1.60935419
sigma_su 6.44906871 2.1942397 2.939090313.291771e-03 6.44906871 0.19743007 0.19743007
sigma_ly1lx157.5854253317.3864934 3.312078189.260566e-04 0.75680419 0.75680419 0.75680419
sigma_g2ly1 12.61120739 7.2337028 1.743395868.126449e-02 0.59301748 0.59301748 0.59301748
sigma_j2lx1 8.71687258 3.3506769 2.601525889.281006e-03 0.44516456 0.44516456 0.44516456
sigma_j2g2 3.54045248 2.4914443 1.421044211.553039e-01 0.64693185 0.64693185 0.64693185
xi_lag_xy -0.08212412 4.1890623-0.019604429.843589e-01-0.12370031-0.12370031-0.12370031
xi_lag_yx 0.84525244 3.3425366 0.252877548.003628e-01 1.12275575 1.12275575 1.12275575

L’output completo è fornito qui di seguito.

out = summary(multi4_lavaan_results)
print(out)
lavaan 0.6.15 ended normally after 382 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        67
  Number of equality constraints                    44

                                                  Used       Total
  Number of observations                           932         933
  Number of missing patterns                        66            

Model Test User Model:
                                              Standard      Scaled
  Test Statistic                               181.084     236.332
  Degrees of freedom                                96          96
  P-value (Chi-square)                           0.000       0.000
  Scaling correction factor                                  0.766
    Yuan-Bentler correction (Mplus variant)                       

Parameter Estimates:

  Standard errors                             Sandwich
  Information bread                           Observed
  Observed information based on                Hessian

Latent Variables:
                   Estimate  Std.Err  z-value  P(>|z|)
  lx1 =~                                              
    x1                1.000                           
  lx2 =~                                              
    x2                1.000                           
  lx3 =~                                              
    x3                1.000                           
  lx4 =~                                              
    x4                1.000                           
  lx5 =~                                              
    x5                1.000                           
  lx6 =~                                              
    x6                1.000                           
  lx7 =~                                              
    x7                1.000                           
  dx2 =~                                              
    lx2               1.000                           
  dx3 =~                                              
    lx3               1.000                           
  dx4 =~                                              
    lx4               1.000                           
  dx5 =~                                              
    lx5               1.000                           
  dx6 =~                                              
    lx6               1.000                           
  dx7 =~                                              
    lx7               1.000                           
  g2 =~                                               
    dx2               1.000                           
    dx3               1.000                           
    dx4               1.000                           
    dx5               1.000                           
    dx6               1.000                           
    dx7               1.000                           
  ly1 =~                                              
    y1                1.000                           
  ly2 =~                                              
    y2                1.000                           
  ly3 =~                                              
    y3                1.000                           
  ly4 =~                                              
    y4                1.000                           
  ly5 =~                                              
    y5                1.000                           
  ly6 =~                                              
    y6                1.000                           
  ly7 =~                                              
    y7                1.000                           
  dy2 =~                                              
    ly2               1.000                           
  dy3 =~                                              
    ly3               1.000                           
  dy4 =~                                              
    ly4               1.000                           
  dy5 =~                                              
    ly5               1.000                           
  dy6 =~                                              
    ly6               1.000                           
  dy7 =~                                              
    ly7               1.000                           
  j2 =~                                               
    dy2               1.000                           
    dy3               1.000                           
    dy4               1.000                           
    dy5               1.000                           
    dy6               1.000                           
    dy7               1.000                           

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)
  lx2 ~                                               
    lx1               1.000                           
  lx3 ~                                               
    lx2               1.000                           
  lx4 ~                                               
    lx3               1.000                           
  lx5 ~                                               
    lx4               1.000                           
  lx6 ~                                               
    lx5               1.000                           
  lx7 ~                                               
    lx6               1.000                           
  dx2 ~                                               
    lx1     (bt_x)   -0.240    0.271   -0.886    0.376
  dx3 ~                                               
    lx2     (bt_x)   -0.240    0.271   -0.886    0.376
  dx4 ~                                               
    lx3     (bt_x)   -0.240    0.271   -0.886    0.376
  dx5 ~                                               
    lx4     (bt_x)   -0.240    0.271   -0.886    0.376
  dx6 ~                                               
    lx5     (bt_x)   -0.240    0.271   -0.886    0.376
  dx7 ~                                               
    lx6     (bt_x)   -0.240    0.271   -0.886    0.376
  dx3 ~                                               
    dx2     (ph_x)    0.039    3.654    0.011    0.991
  dx4 ~                                               
    dx3     (ph_x)    0.039    3.654    0.011    0.991
  dx5 ~                                               
    dx4     (ph_x)    0.039    3.654    0.011    0.991
  dx6 ~                                               
    dx5     (ph_x)    0.039    3.654    0.011    0.991
  dx7 ~                                               
    dx6     (ph_x)    0.039    3.654    0.011    0.991
  ly2 ~                                               
    ly1               1.000                           
  ly3 ~                                               
    ly2               1.000                           
  ly4 ~                                               
    ly3               1.000                           
  ly5 ~                                               
    ly4               1.000                           
  ly6 ~                                               
    ly5               1.000                           
  ly7 ~                                               
    ly6               1.000                           
  dy2 ~                                               
    ly1     (bt_y)   -0.095    0.192   -0.497    0.619
  dy3 ~                                               
    ly2     (bt_y)   -0.095    0.192   -0.497    0.619
  dy4 ~                                               
    ly3     (bt_y)   -0.095    0.192   -0.497    0.619
  dy5 ~                                               
    ly4     (bt_y)   -0.095    0.192   -0.497    0.619
  dy6 ~                                               
    ly5     (bt_y)   -0.095    0.192   -0.497    0.619
  dy7 ~                                               
    ly6     (bt_y)   -0.095    0.192   -0.497    0.619
  dy3 ~                                               
    dy2     (ph_y)   -1.073    3.452   -0.311    0.756
  dy4 ~                                               
    dy3     (ph_y)   -1.073    3.452   -0.311    0.756
  dy5 ~                                               
    dy4     (ph_y)   -1.073    3.452   -0.311    0.756
  dy6 ~                                               
    dy5     (ph_y)   -1.073    3.452   -0.311    0.756
  dy7 ~                                               
    dy6     (ph_y)   -1.073    3.452   -0.311    0.756
  dx3 ~                                               
    dy2   (x_lg_x)   -0.082    4.189   -0.020    0.984
  dx4 ~                                               
    dy3   (x_lg_x)   -0.082    4.189   -0.020    0.984
  dx5 ~                                               
    dy4   (x_lg_x)   -0.082    4.189   -0.020    0.984
  dx6 ~                                               
    dy5   (x_lg_x)   -0.082    4.189   -0.020    0.984
  dx7 ~                                               
    dy6   (x_lg_x)   -0.082    4.189   -0.020    0.984
  dy3 ~                                               
    dx2   (x_lg_y)    0.845    3.343    0.253    0.800
  dy4 ~                                               
    dx3   (x_lg_y)    0.845    3.343    0.253    0.800
  dy5 ~                                               
    dx4   (x_lg_y)    0.845    3.343    0.253    0.800
  dy6 ~                                               
    dx5   (x_lg_y)    0.845    3.343    0.253    0.800
  dy7 ~                                               
    dx6   (x_lg_y)    0.845    3.343    0.253    0.800

Covariances:
                   Estimate  Std.Err  z-value  P(>|z|)
  lx1 ~~                                              
    g2 (sgm_g2lx1)   14.566   11.742    1.240    0.215
  ly1 ~~                                              
    j2 (sgm_j2ly1)   16.846   11.824    1.425    0.154
 .x1 ~~                                               
   .y1      (sgm_)    6.449    2.194    2.939    0.003
 .x2 ~~                                               
   .y2      (sgm_)    6.449    2.194    2.939    0.003
 .x3 ~~                                               
   .y3      (sgm_)    6.449    2.194    2.939    0.003
 .x4 ~~                                               
   .y4      (sgm_)    6.449    2.194    2.939    0.003
 .x5 ~~                                               
   .y5      (sgm_)    6.449    2.194    2.939    0.003
 .x6 ~~                                               
   .y6      (sgm_)    6.449    2.194    2.939    0.003
 .x7 ~~                                               
   .y7      (sgm_)    6.449    2.194    2.939    0.003
  lx1 ~~                                              
    l1      (s_11)   57.585   17.386    3.312    0.001
  g2 ~~                                               
    l1 (sgm_g2ly1)   12.611    7.234    1.743    0.081
  lx1 ~~                                              
    j2 (sgm_j2lx1)    8.717    3.351    2.602    0.009
  g2 ~~                                               
    j2      (s_22)    3.540    2.491    1.421    0.155

Intercepts:
                   Estimate  Std.Err  z-value  P(>|z|)
    lx1  (gmm_lx1)   32.358    0.548   59.022    0.000
   .lx2               0.000                           
   .lx3               0.000                           
   .lx4               0.000                           
   .lx5               0.000                           
   .lx6               0.000                           
   .lx7               0.000                           
   .x1                0.000                           
   .x2                0.000                           
   .x3                0.000                           
   .x4                0.000                           
   .x5                0.000                           
   .x6                0.000                           
   .x7                0.000                           
   .dx2               0.000                           
   .dx3               0.000                           
   .dx4               0.000                           
   .dx5               0.000                           
   .dx6               0.000                           
   .dx7               0.000                           
    g2   (alph_g2)   15.417    7.703    2.001    0.045
    ly1  (gmm_ly1)   33.803    0.520   65.009    0.000
   .ly2               0.000                           
   .ly3               0.000                           
   .ly4               0.000                           
   .ly5               0.000                           
   .ly6               0.000                           
   .ly7               0.000                           
   .y1                0.000                           
   .y2                0.000                           
   .y3                0.000                           
   .y4                0.000                           
   .y5                0.000                           
   .y6                0.000                           
   .y7                0.000                           
   .dy2               0.000                           
   .dy3               0.000                           
   .dy4               0.000                           
   .dy5               0.000                           
   .dy6               0.000                           
   .dy7               0.000                           
    j2   (alph_j2)   11.175    7.182    1.556    0.120

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)
    lx1 (sgm2_lx1)   69.321    6.543   10.595    0.000
   .lx2               0.000                           
   .lx3               0.000                           
   .lx4               0.000                           
   .lx5               0.000                           
   .lx6               0.000                           
   .lx7               0.000                           
   .x1    (sgm2_x)   31.905    4.977    6.411    0.000
   .x2    (sgm2_x)   31.905    4.977    6.411    0.000
   .x3    (sgm2_x)   31.905    4.977    6.411    0.000
   .x4    (sgm2_x)   31.905    4.977    6.411    0.000
   .x5    (sgm2_x)   31.905    4.977    6.411    0.000
   .x6    (sgm2_x)   31.905    4.977    6.411    0.000
   .x7    (sgm2_x)   31.905    4.977    6.411    0.000
   .dx2               0.000                           
   .dx3               0.000                           
   .dx4               0.000                           
   .dx5               0.000                           
   .dx6               0.000                           
   .dx7               0.000                           
    g2   (sgm2_g2)    5.415    5.229    1.035    0.300
    ly1 (sgm2_ly1)   83.520    8.660    9.645    0.000
   .ly2               0.000                           
   .ly3               0.000                           
   .ly4               0.000                           
   .ly5               0.000                           
   .ly6               0.000                           
   .ly7               0.000                           
   .y1    (sgm2_y)   33.443    4.548    7.353    0.000
   .y2    (sgm2_y)   33.443    4.548    7.353    0.000
   .y3    (sgm2_y)   33.443    4.548    7.353    0.000
   .y4    (sgm2_y)   33.443    4.548    7.353    0.000
   .y5    (sgm2_y)   33.443    4.548    7.353    0.000
   .y6    (sgm2_y)   33.443    4.548    7.353    0.000
   .y7    (sgm2_y)   33.443    4.548    7.353    0.000
   .dy2               0.000                           
   .dy3               0.000                           
   .dy4               0.000                           
   .dy5               0.000                           
   .dy6               0.000                           
   .dy7               0.000                           
    j2   (sgm2_j2)    5.531    5.775    0.958    0.338

38.1.1. Interpretazione#

Le stime dei parametri di questo modello descrivono le traiettorie medie e individuali per la matematica e la comprensione della lettura, nonché le loro associazioni nel tempo. Le traiettorie medie per la matematica e la comprensione della lettura iniziano rispettivamente a 32.27 e 33.99. Da lì, le traiettorie medie sono descritte dalle rispettive equazioni di cambiamento.

Per l’equazione di cambiamento della matematica, la media della componente di cambiamento costante è 15.82 e indica l’aumento costante ogni anno. La media della componente di cambiamento proporzionale è -0.27, il che indica un effetto limitativo (il coefficiente è negativo) sul cambiamento in matematica dovuto ai punteggi precedenti di matematica. Il modello assume l’assenza di un effetto di accoppiamento (0).

\[ dm_{t1} = 15.82 - 0.27 \cdot lm_{t-li} + 0 \]

Per l’equazione di cambiamento della comprensione nella lettura, la media della componente di cambiamento costante è 12.59 e indica l’aumento costante ogni anno. La media della componente di cambiamento proporzionale è -0.15, il che indica un effetto limitativo (il coefficiente è negativo) sul cambiamento nella comprensione nella lettura dovuto ai punteggi precedenti di comprensione nella lettura. Il modello assume l’assenza di un effetto di accoppiamento (0).

\[ dc_{t1} = 12.59 - 0.15 \cdot lc_{t-li} + 0 \]

Poniamoci ora il problema di creare una figura che riporta le traiettorie individuali previste dal modello bivariato. Per creare la figura dobbiamo innanzitutto recuperare la sintassi lavaan del modello duale.

Otteniamo i punteggi fattoriali.

nlsy_predicted <- cbind(
    nlsy_multi_data$id, 
    as.data.frame(lavPredict(multi4_lavaan_results, type = "yhat"))
)
names(nlsy_predicted)[1] <- "id"
#looking at data
head(nlsy_predicted)
A data.frame: 6 × 15
idx1x2x3x4x5x6x7y1y2y3y4y5y6y7
<int><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
1 20132.3140140.4493646.3108250.8615154.2742056.9534258.9326031.1116138.9151144.4830349.9971053.9365158.2282361.11388
2 30323.6315630.2673035.0662138.7714641.5705843.7454845.3745523.9761330.1230234.7011738.9738442.2433245.5118947.94291
3270247.2743455.2739661.0446765.5168468.8786871.5090973.4610437.2137544.8012450.2906555.6242359.5200363.6488766.51678
4430335.8743443.9279649.7670454.2585657.6685560.2995762.2888630.3695537.6501343.2366548.2369252.2513356.0271259.04127
5500233.6233142.2292848.3250553.1775856.6970359.5923061.5998938.5214848.0519953.7281060.8766464.7151070.6119173.21252
6500536.8941944.6808150.0916754.5207257.6146260.2951862.0257246.3579456.2540161.1762768.9569472.1018178.7911980.69319

Convertiamo i dati in formato long.

predicted_long <- reshape(
       data = nlsy_predicted,
       varying = c(
              "x1", "x2", "x3", "x4", "x5", "x6", "x7",
              "y1", "y2", "y3", "y4", "y5", "y6", "y7"
       ),
       timevar = c("grade"),
       idvar = c("id"),
       direction = "long", sep = ""
)

#sorting for easy viewing
#reorder by id and day
predicted_long <- predicted_long[order(predicted_long$id,predicted_long$grade), ]

#looking at the long data
head(predicted_long, 14)
A data.frame: 14 × 4
idgradexy
<int><dbl><dbl><dbl>
201.1201132.3140131.11161
201.2201240.4493638.91511
201.3201346.3108244.48303
201.4201450.8615149.99710
201.5201554.2742053.93651
201.6201656.9534258.22823
201.7201758.9326061.11388
303.1303123.6315623.97613
303.2303230.2673030.12302
303.3303335.0662134.70117
303.4303438.7714638.97384
303.5303541.5705842.24332
303.6303643.7454845.51189
303.7303745.3745547.94291

Creiamo un grafico del cambiamento intra-individuale per la matematica.

ggplot(data = predicted_long, aes(x = grade, y = x, group = id)) +
  #geom_point(color="blue") + 
  geom_line(color="blue", alpha= 0.1) +
  xlab("Grade") + 
  ylab("Predicted PIAT Mathematics") + 
  scale_x_continuous(limits=c(2,7), breaks=seq(2,8,by=1)) +
  scale_y_continuous(limits=c(0,90), breaks=seq(0,90,by=10))
Warning message:
“Removed 939 rows containing missing values (`geom_line()`).”
_images/89c83e4b9c3e594622c842f5a5fe6b56b3463ce7a1a4972826280fab8d350e08.png

Creiamo un grafico del cambiamento intra-individuale per la comprensione nella lettura.

ggplot(data = predicted_long, aes(x = grade, y = y, group = id)) +
  #geom_point(color="red") + 
  geom_line(color="red", alpha= 0.1) +
  xlab("Grade") + 
  ylab("Predicted PIAT Reading Recognition") +
  scale_x_continuous(limits=c(2,7), breaks=seq(2,8,by=1)) +
  scale_y_continuous(limits=c(0,90), breaks=seq(0,90,by=10))
Warning message:
“Removed 948 rows containing missing values (`geom_line()`).”
_images/754bd81c15e43b2b8b2c00d8124b04f839e6ac5656eb1b60ac69d4e01390e039.png

Esaminiamo gli effetti combinati dei cambiamenti nelle due variabili.

# reshaping wide to long
data_long <- reshape(
       data = nlsy_multi_data,
       varying = c(
              "math2", "math3", "math4", "math5", "math6", "math7", "math8",
              "rec2", "rec3", "rec4", "rec5", "rec6", "rec7", "rec8"
       ),
       timevar = c("grade"),
       idvar = c("id"),
       direction = "long", sep = ""
)

#sorting for easy viewing
#reorder by id and day
data_long <- data_long[order(data_long$id,data_long$grade), ]

#looking at the long data
head(data_long, 8)
A data.frame: 8 × 4
idgrademathrec
<int><dbl><int><int>
201.22012NANA
201.320133835
201.42014NANA
201.520155552
201.62016NANA
201.72017NANA
201.82018NANA
303.230322626
#creating a grid of starting values 
df <- expand.grid(math=seq(10, 90, 5), rec=seq(10, 90, 5))

#calculating change scores for each starting value 
#changes in math based on output from model
df$dm <- with(df, 15.09 - 0.293*math + 0.053*rec)
#changes in reading based on output from model
df$dr <- with(df, 10.89 - 0.495*rec + 0.391*math)

#Plotting vector field with .25 unit time change 
ggplot(data = df, aes(x = x, y = y)) +
  geom_point(data=data_long, aes(x=rec, y=math), alpha=.1) + 
  stat_ellipse(data=data_long, aes(x=rec, y=math)) +
  geom_segment(aes(x = rec, y = math, xend = rec+.25*dr, yend = math+.25*dm), arrow = arrow(length = unit(0.1, "cm"))) +
  xlab("Reading Recognition") + 
  ylab("Mathematics") +
  scale_x_continuous(limits=c(10,90), breaks=seq(10,90,by=10)) +
  scale_y_continuous(limits=c(10,90), breaks=seq(10,90,by=10))
Warning message:
“Removed 4317 rows containing non-finite values (`stat_ellipse()`).”
Warning message:
“Removed 4317 rows containing missing values (`geom_point()`).”
Warning message:
“Removed 1 rows containing missing values (`geom_segment()`).”
_images/4b184b3871cd3dbc17e0acf083c7e275af9f6b0a354b89e3543c61f0713b9553.png

Il grafico rappresenta l’evoluzione delle variabili nel tempo. Le frecce del campo vettoriale indicano le variazioni previste nello spazio bivariato per un intervallo di tempo di 0.25 unità. Si osserva che i dati si concentrano principalmente all’interno dell’ellisse di confidenza al 95%. Al di fuori di questa area, i vettori direzionali sono interpolati sulla base delle osservazioni e dei modelli derivati dai dati effettivi (cioè all’interno dell’ellisse). Pertanto, è importante evitare di sovrainterpretare le dinamiche al di fuori dell’ellisse.

La regione dello spazio vettoriale in cui i vettori tendono a zero indica le combinazioni di valori delle due variabili per cui non si prevedono ulteriori cambiamenti. L’aspetto più interessante del grafico non è tanto il risultato finale del processo, quanto la descrizione della forza e della direzione del cambiamento per ogni combinazione di valori delle due variabili considerate.