Setup

Load packages and data.

#packages
library(pacman)
p_load(kirkegaard, readr, dplyr, haven, lavaan, igraph, ggraph)
options(digits = 2, scipen = 5)

#data
d = haven::read_spss("data/VES.sav")

#rename variables to more sensible names
d %<>% rename(
  #Wide Range Achievement Test (WRAT)
  WRAT = WR01008,
  
  #California Verbal Learning Test (CVLT)
  CVLT = CV01144,
  
  #Wisconsin Card Sort Test (WCST)
  WCST = WCS25,
  
  #Wechsler Adult Intelligence Scale-Revised (WAIS-R) subtests
  WAIS_BD = WA01012B,
  WAIS_GI = WA01011B,
  
  #Rey±Osterrieth Complex Figure Drawing
  copy_direct = RE01011, #direct
  copy_immediate = RE01012, #immediate recall
  copy_delayed = RE01013, #delayed recall
  
  #Paced Auditory Serial Addition Test (PASAT)
  PASAT = SPASAT,
  
  #Grooved Pegboard Test (GPT)
  GPT_left = LEFTREV,
  GPT_right = RIGHTREV,
  
  #Word List Generation Test (WLGT), verbal fluency
  WLGT = FAS,
  
  #education
  Education = EDUC
) %>% mutate(
  #average of the memorized copy tests
  copy_combined = (standardize(copy_immediate) + standardize(copy_delayed))/2
)

Functions

Ad hoc functions.

#function to regress out early g from a variable
regressor = function(x) {
  #make model
  model_ = x + " ~ g_early"
  
  #fit
  lm(model_, data = d, na.action = na.exclude) %>% 
    #resids
    resid
}

Initial analyses

Extract g at different times.

#g tests
g_tests_early = c("VESS", "VE", "AR", "ARSS", "PA", "GIT", "AFQT")
g_tests_later = c("WAIS_BD", "WAIS_GI", "WRAT", "PASAT", "WLGT", "copy_combined", "CVLT", "WCST", "GPT_left", "GPT_right")
g_tests = c(g_tests_early, g_tests_later)

#test correlations
wtd.cors(d[g_tests])
##               VESS   VE   AR ARSS   PA  GIT AFQT WAIS_BD WAIS_GI WRAT
## VESS          1.00 0.82 0.66 0.69 0.48 0.62 0.68    0.45    0.72 0.77
## VE            0.82 1.00 0.70 0.64 0.52 0.66 0.72    0.44    0.73 0.75
## AR            0.66 0.70 1.00 0.79 0.58 0.59 0.74    0.50    0.64 0.59
## ARSS          0.69 0.64 0.79 1.00 0.54 0.55 0.69    0.53    0.62 0.58
## PA            0.48 0.52 0.58 0.54 1.00 0.47 0.73    0.63    0.48 0.41
## GIT           0.62 0.66 0.59 0.55 0.47 1.00 0.65    0.42    0.58 0.52
## AFQT          0.68 0.72 0.74 0.69 0.73 0.65 1.00    0.62    0.63 0.58
## WAIS_BD       0.45 0.44 0.50 0.53 0.63 0.42 0.62    1.00    0.45 0.38
## WAIS_GI       0.72 0.73 0.64 0.62 0.48 0.58 0.63    0.45    1.00 0.65
## WRAT          0.77 0.75 0.59 0.58 0.41 0.52 0.58    0.38    0.65 1.00
## PASAT         0.44 0.41 0.52 0.56 0.37 0.37 0.43    0.39    0.37 0.42
## WLGT          0.46 0.44 0.37 0.37 0.29 0.31 0.36    0.28    0.41 0.50
## copy_combined 0.32 0.31 0.34 0.39 0.46 0.32 0.46    0.50    0.35 0.28
## CVLT          0.33 0.32 0.33 0.36 0.26 0.25 0.31    0.27    0.33 0.31
## WCST          0.36 0.33 0.36 0.40 0.33 0.28 0.37    0.36    0.33 0.29
## GPT_left      0.23 0.21 0.21 0.24 0.26 0.19 0.27    0.31    0.19 0.20
## GPT_right     0.22 0.20 0.20 0.24 0.26 0.17 0.25    0.30    0.17 0.20
##               PASAT WLGT copy_combined CVLT WCST GPT_left GPT_right
## VESS           0.44 0.46          0.32 0.33 0.36     0.23      0.22
## VE             0.41 0.44          0.31 0.32 0.33     0.21      0.20
## AR             0.52 0.37          0.34 0.33 0.36     0.21      0.20
## ARSS           0.56 0.37          0.39 0.36 0.40     0.24      0.24
## PA             0.37 0.29          0.46 0.26 0.33     0.26      0.26
## GIT            0.37 0.31          0.32 0.25 0.28     0.19      0.17
## AFQT           0.43 0.36          0.46 0.31 0.37     0.27      0.25
## WAIS_BD        0.39 0.28          0.50 0.27 0.36     0.31      0.30
## WAIS_GI        0.37 0.41          0.35 0.33 0.33     0.19      0.17
## WRAT           0.42 0.50          0.28 0.31 0.29     0.20      0.20
## PASAT          1.00 0.36          0.29 0.29 0.28     0.22      0.23
## WLGT           0.36 1.00          0.22 0.28 0.21     0.16      0.17
## copy_combined  0.29 0.22          1.00 0.33 0.27     0.23      0.20
## CVLT           0.29 0.28          0.33 1.00 0.19     0.11      0.12
## WCST           0.28 0.21          0.27 0.19 1.00     0.20      0.19
## GPT_left       0.22 0.16          0.23 0.11 0.20     1.00      0.63
## GPT_right      0.23 0.17          0.20 0.12 0.19     0.63      1.00
#extract g - all data
fa_g = fa(d[g_tests])
d$g = fa_g$scores %>% as.vector

#method variance
#only run manually because this is slow!
if (F) {
  fa_method_variance = silence(fa_all_methods(d[g_tests]))
fa_method_variance$scores %>% wtd.cors %>% MAT_half %>% averages()
}

#g - early life
fa_g_early = fa(d[g_tests_early])
d$g_early = fa_g_early$scores %>% as.vector

#g - later life
fa_g_later = fa(d[g_tests_later])
d$g_later = fa_g_later$scores %>% as.vector

#g - gain
d$g_gain = d$g_later - d$g_early

#cors
wtd.cors(d[c("Education", "g", "g_early", "g_later", "g_gain")]) %>% round(2)
##           Education     g g_early g_later g_gain
## Education      1.00  0.57    0.55    0.54  -0.06
## g              0.57  1.00    0.99    0.92  -0.22
## g_early        0.55  0.99    1.00    0.85  -0.36
## g_later        0.54  0.92    0.85    1.00   0.18
## g_gain        -0.06 -0.22   -0.36    0.18   1.00
#plots
GG_denhist(d, "g_early", vline = NULL)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 106 rows containing non-finite values (stat_bin).
## Warning: Removed 106 rows containing non-finite values (stat_density).

silence(ggsave("figures/g_early_dist.png"))
GG_denhist(d, "g_later", vline = NULL)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 36 rows containing non-finite values (stat_bin).
## Warning: Removed 36 rows containing non-finite values (stat_density).

silence(ggsave("figures/g_later_dist.png"))
GG_denhist(d, "g_gain", vline = NULL)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 141 rows containing non-finite values (stat_bin).
## Warning: Removed 141 rows containing non-finite values (stat_density).

silence(ggsave("figures/g_gain_dist.png"))
GG_scatter(d, "Education", "g_gain", case_names = F, text_pos = "tl")

silence(ggsave("figures/education_g_gains.png"))

Simple path model

simple_path_model = "
g_later ~ g_early + Education
Education ~ g_early
"
simple_path = sem(simple_path_model, data = d, std.ov = T)
parameterestimates(simple_path)
##         lhs op       rhs  est    se  z pvalue ci.lower ci.upper
## 1   g_later  ~   g_early 0.79 0.009 85      0    0.773     0.81
## 2   g_later  ~ Education 0.11 0.009 12      0    0.093     0.13
## 3 Education  ~   g_early 0.55 0.013 43      0    0.524     0.57
## 4   g_later ~~   g_later 0.26 0.006 46      0    0.253     0.28
## 5 Education ~~ Education 0.70 0.015 46      0    0.670     0.73
## 6   g_early ~~   g_early 1.00 0.000 NA     NA    1.000     1.00

Jensen’s method

Are gains g-loaded?

#Add regressed versions of later life tests
for (test_ in g_tests_later) {
  #regress and save
  d[[test_ + "_adj"]] = regressor(test_)
}

#Jensen's method - Education x g for all data
fa_Jensens_method(fa = fa_g, criterion = "Education", df = d)
## Using Pearson correlations for the criterion-indicators relationships.

#Education IQ gains on g?
edu_g_gains = wtd.cors(d[c("Education", g_tests_later + "_adj")])
fa_Jensens_method(fa = fa_g_later, criterion = edu_g_gains[-1, 1], df = d)

#Model of g Before we can use SEM to determine whether IQ gains are plausibly on g or not, we need to figure out how to model the data well.

model_basic = "
g_early =~ VESS + VE + AR + ARSS + PA + GIT + AFQT
g_later =~ WAIS_BD + WAIS_GI + WRAT + PASAT + WLGT + copy_direct + copy_delayed + copy_immediate + CVLT + WCST + GPT_left + GPT_right

#correlated errors
GPT_left ~~ GPT_right
VESS ~~ VE
PA ~~ AFQT
AR ~~ ARSS
copy_delayed ~~ copy_immediate
copy_delayed ~~ copy_direct
copy_immediate ~~ copy_direct
"

model_basic2 = "
g_later =~ WAIS_BD + WAIS_GI + WRAT + PASAT + WLGT + copy_direct + copy_delayed + copy_immediate + CVLT + WCST + GPT_left + GPT_right

#correlated errors
GPT_left ~~ GPT_right
copy_delayed ~~ copy_immediate
copy_delayed ~~ copy_direct
copy_immediate ~~ copy_direct
"

model_g = model_basic + "
#g stability
g_later ~ g_early"

model_g2 = model_basic2 + "
#g stability
g_later ~ g_early"

#basic with two g's
sem_basic = sem(model_g, data = d, std.ov = T, orthogonal = T)
fit_measures = c("cfi", "gfi", "tli", "rmsea", "srmr", "AIC")
sem_basic %>% fitmeasures(fit.measures = fit_measures)
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.908      0.867      0.891      0.089      0.060 183970.813
sem_basic %>% resid
## $type
## [1] "raw"
## 
## $cov
##                VESS   VE     AR     ARSS   PA     GIT    AFQT   WAIS_B
## VESS            0.000                                                 
## VE              0.000  0.000                                          
## AR             -0.039 -0.002  0.000                                   
## ARSS            0.005 -0.046  0.000  0.000                            
## PA             -0.069 -0.041  0.047  0.024  0.000                     
## GIT             0.003  0.039  0.000 -0.030 -0.002  0.000              
## AFQT           -0.039 -0.001  0.056  0.021  0.000  0.039  0.000       
## WAIS_BD        -0.067 -0.087  0.005  0.042  0.240 -0.020  0.113  0.000
## WAIS_GI         0.048  0.050 -0.007 -0.010 -0.029  0.013 -0.035 -0.040
## WRAT            0.114  0.087 -0.038 -0.031 -0.085 -0.035 -0.067 -0.100
## PASAT          -0.024 -0.060  0.075  0.124  0.014 -0.027 -0.026  0.044
## WLGT            0.032  0.007 -0.045 -0.041 -0.040 -0.058 -0.064 -0.036
## copy_direct    -0.022 -0.057  0.000  0.053  0.120 -0.034  0.032  0.136
## copy_delayed   -0.070 -0.084 -0.030  0.020  0.162 -0.014  0.069  0.208
## copy_immediate -0.068 -0.082 -0.032  0.022  0.165 -0.011  0.070  0.205
## CVLT           -0.015 -0.035 -0.004  0.027 -0.005 -0.047 -0.026  0.014
## WCST           -0.009 -0.044  0.007  0.048  0.051 -0.028  0.004  0.080
## GPT_left       -0.023 -0.044 -0.026  0.004  0.073 -0.019  0.025  0.121
## GPT_right      -0.018 -0.041 -0.032  0.015  0.077 -0.028  0.017  0.123
##                WAIS_G WRAT   PASAT  WLGT   cpy_dr cpy_dl cpy_mm CVLT  
## VESS                                                                  
## VE                                                                    
## AR                                                                    
## ARSS                                                                  
## PA                                                                    
## GIT                                                                   
## AFQT                                                                  
## WAIS_BD                                                               
## WAIS_GI         0.000                                                 
## WRAT            0.031  0.000                                          
## PASAT          -0.079 -0.017  0.000                                   
## WLGT            0.006  0.103  0.070  0.000                            
## copy_direct    -0.047 -0.055  0.019 -0.030  0.000                     
## copy_delayed   -0.020 -0.086  0.027 -0.016  0.000  0.000              
## copy_immediate -0.021 -0.088  0.029 -0.019  0.000  0.000  0.000       
## CVLT            0.001 -0.007  0.061  0.063  0.036  0.142  0.131  0.000
## WCST           -0.021 -0.052  0.039 -0.020  0.106  0.065  0.065  0.012
## GPT_left       -0.049 -0.028  0.055  0.006  0.100  0.090  0.092 -0.013
## GPT_right      -0.053 -0.030  0.070  0.021  0.106  0.070  0.065 -0.003
##                WCST   GPT_lf GPT_rg
## VESS                               
## VE                                 
## AR                                 
## ARSS                               
## PA                                 
## GIT                                
## AFQT                               
## WAIS_BD                            
## WAIS_GI                            
## WRAT                               
## PASAT                              
## WLGT                               
## copy_direct                        
## copy_delayed                       
## copy_immediate                     
## CVLT                               
## WCST            0.000              
## GPT_left        0.063  0.000       
## GPT_right       0.061  0.000  0.000
## 
## $mean
##           VESS             VE             AR           ARSS             PA 
##              0              0              0              0              0 
##            GIT           AFQT        WAIS_BD        WAIS_GI           WRAT 
##              0              0              0              0              0 
##          PASAT           WLGT    copy_direct   copy_delayed copy_immediate 
##              0              0              0              0              0 
##           CVLT           WCST       GPT_left      GPT_right 
##              0              0              0              0
#with with only 1 g
sem_basic2 = sem(model_g2, data = d, std.ov = T, orthogonal = T)
fit_measures = c("cfi", "gfi", "tli", "rmsea", "srmr", "AIC")
sem_basic2 %>% fitmeasures(fit.measures = fit_measures)
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.937      0.958      0.920      0.081      0.060 133362.613
sem_basic2 %>% resid
## $type
## [1] "raw"
## 
## $cov
##                WAIS_B WAIS_G WRAT   PASAT  WLGT   cpy_dr cpy_dl cpy_mm
## WAIS_BD         0.000                                                 
## WAIS_GI        -0.046  0.000                                          
## WRAT           -0.104  0.043  0.000                                   
## PASAT           0.033 -0.080 -0.016  0.000                            
## WLGT           -0.040  0.012  0.111  0.070  0.000                     
## copy_direct     0.125 -0.051 -0.057  0.012 -0.032  0.000              
## copy_delayed    0.196 -0.024 -0.088  0.020 -0.019  0.000  0.000       
## copy_immediate  0.193 -0.025 -0.090  0.022 -0.022  0.000  0.000  0.000
## CVLT            0.008  0.002 -0.004  0.057  0.064  0.032  0.137  0.127
## WCST            0.071 -0.022 -0.051  0.034 -0.020  0.101  0.059  0.059
## GPT_left        0.114 -0.051 -0.028  0.051  0.005  0.096  0.085  0.088
## GPT_right       0.117 -0.055 -0.031  0.066  0.020  0.102  0.066  0.060
## g_early         0.008  0.010  0.007  0.004 -0.030 -0.001 -0.014 -0.013
##                CVLT   WCST   GPT_lf GPT_rg g_erly
## WAIS_BD                                          
## WAIS_GI                                          
## WRAT                                             
## PASAT                                            
## WLGT                                             
## copy_direct                                      
## copy_delayed                                     
## copy_immediate                                   
## CVLT            0.000                            
## WCST            0.009  0.000                     
## GPT_left       -0.015  0.060  0.000              
## GPT_right      -0.005  0.058  0.000  0.000       
## g_early        -0.020 -0.004 -0.012 -0.013  0.000
## 
## $mean
##        WAIS_BD        WAIS_GI           WRAT          PASAT           WLGT 
##              0              0              0              0              0 
##    copy_direct   copy_delayed copy_immediate           CVLT           WCST 
##              0              0              0              0              0 
##       GPT_left      GPT_right        g_early 
##              0              0              0

Model comparisons

#SEM comparisons
model_gains_1 = model_basic + "
Education ~ g_early
g_later ~ Education + g_early"

model_gains_2 = model_basic + "
Education ~ g_early
g_later ~ Education + g_early

#specific paths
WAIS_BD ~ Education
WAIS_GI ~ Education
WRAT ~ Education
PASAT ~ Education
copy_direct ~ Education
copy_delayed ~ Education
copy_immediate ~ Education
CVLT ~ Education
WCST ~ Education
GPT_left ~ Education
GPT_right ~ Education
"

model_gains_3 = model_basic + "
#g change
Education ~ g_early
g_later ~ g_early

#specific gains
WAIS_BD ~ Education
WAIS_GI ~ Education
WRAT ~ Education
PASAT ~ Education
copy_direct ~ Education
copy_delayed ~ Education
copy_immediate ~ Education
CVLT ~ Education
WCST ~ Education
GPT_left ~ Education
GPT_right ~ Education
"

model_gains_1b = model_basic2 + "
Education ~ g_early
g_later ~ Education + g_early
"

model_gains_2b = model_basic2 + "
Education ~ g_early
g_later ~ Education + g_early

#specific paths
WAIS_BD ~ Education
WAIS_GI ~ Education
WRAT ~ Education
PASAT ~ Education
copy_direct ~ Education
copy_delayed ~ Education
copy_immediate ~ Education
CVLT ~ Education
WCST ~ Education
GPT_left ~ Education
GPT_right ~ Education
"

model_gains_3b = model_basic2 + "
#g change
Education ~ g_early
g_later ~ g_early

#specific gains
WAIS_BD ~ Education
WAIS_GI ~ Education
WRAT ~ Education
PASAT ~ Education
copy_direct ~ Education
copy_delayed ~ Education
copy_immediate ~ Education
CVLT ~ Education
WCST ~ Education
GPT_left ~ Education
GPT_right ~ Education
"


gain_fits = list(
  #with early g explicitly modeled
  g_gains = sem(model_gains_1, data = d, std.ov = T, orthogonal = T),
  gs_gains = sem(model_gains_2, data = d, std.ov = T, orthogonal = T),
  s_gains = sem(model_gains_3, data = d, std.ov = T, orthogonal = T),
  
  #without early g explicitly modeled
  g_gains2 = sem(model_gains_1b, data = d, std.ov = T, orthogonal = T),
  gs_gains2 = sem(model_gains_2b, data = d, std.ov = T, orthogonal = T),
  s_gains2 = sem(model_gains_3b, data = d, std.ov = T, orthogonal = T)
)

#fit indexes
map(gain_fits, fitmeasures, fit.measures = fit_measures)
## $g_gains
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.906      0.866      0.890      0.087      0.060 194334.969 
## 
## $gs_gains
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.912      0.876      0.888      0.087      0.055 194051.740 
## 
## $s_gains
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.911      0.875      0.888      0.087      0.055 194073.741 
## 
## $g_gains2
##       cfi       gfi       tli     rmsea      srmr       aic 
##      0.93      0.95      0.92      0.08      0.06 143772.59 
## 
## $gs_gains2
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.945      0.963      0.918      0.079      0.052 143440.921 
## 
## $s_gains2
##        cfi        gfi        tli      rmsea       srmr        aic 
##      0.943      0.962      0.917      0.079      0.053 143493.260
#params
gain_fits$gs_gains2 %>% parameterestimates()
##               lhs op            rhs    est    se     z pvalue ci.lower
## 1         g_later =~        WAIS_BD  1.000 0.000    NA     NA    1.000
## 2         g_later =~        WAIS_GI  0.973 0.026 36.86  0.000    0.922
## 3         g_later =~           WRAT  0.983 0.027 36.19  0.000    0.930
## 4         g_later =~          PASAT  0.809 0.028 28.51  0.000    0.754
## 5         g_later =~           WLGT  0.654 0.027 23.99  0.000    0.601
## 6         g_later =~    copy_direct  0.637 0.028 22.59  0.000    0.582
## 7         g_later =~   copy_delayed  0.727 0.029 25.39  0.000    0.671
## 8         g_later =~ copy_immediate  0.713 0.028 25.04  0.000    0.657
## 9         g_later =~           CVLT  0.618 0.028 21.95  0.000    0.563
## 10        g_later =~           WCST  0.634 0.028 22.65  0.000    0.579
## 11        g_later =~       GPT_left  0.442 0.028 15.93  0.000    0.388
## 12        g_later =~      GPT_right  0.453 0.028 16.26  0.000    0.398
## 13       GPT_left ~~      GPT_right  0.543 0.016 33.35  0.000    0.511
## 14   copy_delayed ~~ copy_immediate  0.689 0.016 42.44  0.000    0.658
## 15    copy_direct ~~   copy_delayed  0.275 0.013 20.91  0.000    0.250
## 16    copy_direct ~~ copy_immediate  0.268 0.013 20.44  0.000    0.243
## 17      Education  ~        g_early  0.548 0.013 43.10  0.000    0.524
## 18        g_later  ~      Education  0.178 0.028  6.31  0.000    0.122
## 19        g_later  ~        g_early  0.640 0.014 45.05  0.000    0.612
## 20        WAIS_BD  ~      Education -0.250 0.032 -7.84  0.000   -0.312
## 21        WAIS_GI  ~      Education  0.046 0.030  1.54  0.123   -0.012
## 22           WRAT  ~      Education -0.006 0.030 -0.21  0.837   -0.065
## 23          PASAT  ~      Education -0.122 0.028 -4.32  0.000   -0.178
## 24    copy_direct  ~      Education -0.123 0.026 -4.74  0.000   -0.173
## 25   copy_delayed  ~      Education -0.172 0.027 -6.32  0.000   -0.226
## 26 copy_immediate  ~      Education -0.152 0.027 -5.62  0.000   -0.205
## 27           CVLT  ~      Education -0.118 0.026 -4.61  0.000   -0.168
## 28           WCST  ~      Education -0.091 0.026 -3.55  0.000   -0.142
## 29       GPT_left  ~      Education -0.074 0.023 -3.18  0.001   -0.120
## 30      GPT_right  ~      Education -0.101 0.024 -4.27  0.000   -0.147
## 31        WAIS_BD ~~        WAIS_BD  0.578 0.013 43.02  0.000    0.552
## 32        WAIS_GI ~~        WAIS_GI  0.360 0.009 41.02  0.000    0.343
## 33           WRAT ~~           WRAT  0.403 0.010 41.55  0.000    0.384
## 34          PASAT ~~          PASAT  0.681 0.015 44.61  0.000    0.651
## 35           WLGT ~~           WLGT  0.733 0.016 45.36  0.000    0.701
## 36    copy_direct ~~    copy_direct  0.814 0.018 45.51  0.000    0.779
## 37   copy_delayed ~~   copy_delayed  0.773 0.017 45.15  0.000    0.740
## 38 copy_immediate ~~ copy_immediate  0.774 0.017 45.20  0.000    0.741
## 39           CVLT ~~           CVLT  0.825 0.018 45.60  0.000    0.790
## 40           WCST ~~           WCST  0.802 0.018 45.52  0.000    0.768
## 41       GPT_left ~~       GPT_left  0.907 0.020 46.07  0.000    0.869
## 42      GPT_right ~~      GPT_right  0.910 0.020 46.05  0.000    0.871
## 43      Education ~~      Education  0.699 0.015 46.47  0.000    0.670
## 44        g_later ~~        g_later  0.057 0.004 14.06  0.000    0.049
## 45        g_early ~~        g_early  1.000 0.000    NA     NA    1.000
##    ci.upper
## 1     1.000
## 2     1.025
## 3     1.037
## 4     0.865
## 5     0.708
## 6     0.692
## 7     0.783
## 8     0.769
## 9     0.673
## 10    0.689
## 11    0.497
## 12    0.508
## 13    0.575
## 14    0.721
## 15    0.301
## 16    0.294
## 17    0.573
## 18    0.233
## 19    0.668
## 20   -0.187
## 21    0.104
## 22    0.053
## 23   -0.067
## 24   -0.072
## 25   -0.119
## 26   -0.099
## 27   -0.068
## 28   -0.041
## 29   -0.029
## 30   -0.055
## 31    0.605
## 32    0.377
## 33    0.422
## 34    0.711
## 35    0.765
## 36    0.849
## 37    0.807
## 38    0.808
## 39    0.861
## 40    0.837
## 41    0.946
## 42    0.949
## 43    0.729
## 44    0.065
## 45    1.000

Plot SEM

lavaan_to_igraph = function(fit) {
  #get params
  params = parameterestimates(fit)
  
  #subset to non-self
  params$self = params$rhs == params$lhs
  params = params[!params$self, ]
  
  #unique nodes
  unique_nodes = unique(c(params$rhs, params$lhs))
  
  #make adjacency matrix
  #init
  adj_mat = matrix(0, ncol = length(unique_nodes), nrow = length(unique_nodes))
  rownames(adj_mat) = colnames(adj_mat) = unique_nodes
  
  #loop over rows and add
  for (row_i in seq_along_rows(params)) {
    row_ = params[row_i, ]
    
    #latent regression
    if (row_[["op"]] %in% c("=~")) {
      adj_mat[row_[["lhs"]], row_[["rhs"]]] = 1
    } else if (row_[["op"]] %in% c("~")) {
      #observable regression
      adj_mat[row_[["rhs"]], row_[["lhs"]]] = 1
    } else if (row_[["op"]] %in% c("~~")) {
      #covariance
      adj_mat[row_[["rhs"]], row_[["lhs"]]] = 1
      adj_mat[row_[["lhs"]], row_[["rhs"]]] = 1
    } 
  }
  
  #to igraph
  igraph_ = igraph::graph_from_adjacency_matrix(adj_mat)
  
  #add node info
  browser()
  igraph_
}

lavaan_to_igraph(gain_fits$gs_gains2) %>% 
  ggraph(layout = "treemap") +
  geom_edge_fan() + 
  geom_node_point()
## Called from: lavaan_to_igraph(gain_fits$gs_gains2)
## debug at <text>#39: igraph_
## Multiple parents. Unfolding graph