Path models

Again, some very rough guide to model respecification:

  1. Look at the “Model test” table first. If the pvalue for the chisq test is significant, the model departs from the data.

  2. To see how much are the data incompatible with the model, see the other fit indices. For an approximately fitting model, CFI and TLI should be >.95, RMSEA < .06.

  3. If the model does not fit the data, we cannot rely on model parameters. Usually, they may be slightly off for a misspecified model (say in units), but with severe misspecification, they can be way off (sometimes even in tenths). The next step is then to look at the modification indices table. Collumn “mi” stands for the modification index. It represents the change in chi square statistics if you allow the given parameter. “~” stands for regression path (read as “predicted by”), “~~” denotes a correlation. “sepc.all” is the value of correlation or standardized regression path that the model missed.

Exploratory model 1 all types of touch

Includes also a direct line from CS -> Reflection.

path.model1 <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + f*CloseOthersTouchTest + d*SSTouchTest + e*OSTouchTest  + g*ZCommunalStrength
stress ~ h*reflection
health ~ i*stress
TargetSharingSplit ~~ 0*ZCommunalStrength
SSTouchTest ~~ OSTouchTest
SSTouchTest ~~ CloseOthersTouchTest
OSTouchTest ~~ CloseOthersTouchTest
TargetSharingSplit ~~ SSTouchTest
TargetSharingSplit ~~ OSTouchTest
TargetSharingSplit ~~ CloseOthersTouchTest
'

fit.path.model1 <- sem(path.model1, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model1, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         35.495         21.000          0.025          0.969          0.946 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.040          0.014          0.062          0.542       9787.026

As you can see, the model fits is relatively good, it fits the data approximately.

Modification indices

modificationindices(fit.path.model1, alpha = .05, sort. = TRUE, maximum.number = 5)
##                  lhs op                  rhs    mi   epc sepc.lv sepc.all
## 64             PriBC  ~           reflection 7.502 0.263   0.263    0.432
## 92 ZCommunalStrength  ~ CloseOthersTouchTest 6.595 0.139   0.139    0.139
## 70             PriBC  ~          OSTouchTest 6.144 0.076   0.076    0.119
## 53            stress ~~ CloseOthersTouchTest 5.120 0.062   0.062    0.084
## 77            stress  ~ CloseOthersTouchTest 5.117 0.076   0.076    0.102
##    sepc.nox
## 64    0.432
## 92    0.139
## 70    0.119
## 53    0.084
## 77    0.102

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model1, rsquare = TRUE, standardized = TRUE)[1:13,]
##                     lhs op                  rhs label    est    se      z
## 1                 PriBC  ~    ZCommunalStrength     a  0.066 0.037  1.784
## 2            reflection  ~                PriBC     b  0.179 0.077  2.319
## 3            reflection  ~   TargetSharingSplit     c  0.159 0.066  2.400
## 4            reflection  ~ CloseOthersTouchTest     f  0.057 0.058  0.986
## 5            reflection  ~          SSTouchTest     d  0.076 0.060  1.262
## 6            reflection  ~          OSTouchTest     e  0.208 0.061  3.401
## 7            reflection  ~    ZCommunalStrength     g  0.170 0.063  2.710
## 8                stress  ~           reflection     h -0.271 0.035 -7.662
## 9                health  ~               stress     i  0.547 0.068  7.992
## 10    ZCommunalStrength ~~   TargetSharingSplit        0.000 0.000     NA
## 11          SSTouchTest ~~          OSTouchTest        0.435 0.050  8.758
## 12 CloseOthersTouchTest ~~          SSTouchTest        0.537 0.053 10.138
## 13 CloseOthersTouchTest ~~          OSTouchTest        0.263 0.055  4.811
##    pvalue ci.lower ci.upper std.lv std.all std.nox
## 1   0.074   -0.030    0.124  0.066   0.103   0.103
## 2   0.020   -0.019    0.326  0.179   0.109   0.109
## 3   0.016    0.022    0.272  0.159   0.125   0.125
## 4   0.324   -0.061    0.177  0.057   0.054   0.054
## 5   0.207   -0.032    0.191  0.076   0.072   0.072
## 6   0.001    0.094    0.334  0.208   0.197   0.197
## 7   0.007    0.057    0.337  0.170   0.161   0.161
## 8   0.000   -0.328   -0.198 -0.271  -0.385  -0.385
## 9   0.000    0.415    0.689  0.547   0.396   0.396
## 10     NA    0.000    0.000  0.000   0.000   0.000
## 11  0.000    0.333    0.535  0.435   0.436   0.436
## 12  0.000    0.444    0.646  0.537   0.538   0.538
## 13  0.000    0.148    0.383  0.263   0.263   0.263

Bivariate correlations

lavCor(fit.path.model1)
##                      PriBC  rflctn stress health ZCmmnS TrgtSS ClsOTT
## PriBC                 1.000                                          
## reflection            0.165  1.000                                   
## stress               -0.019 -0.387  1.000                            
## health               -0.083 -0.230  0.397  1.000                     
## ZCommunalStrength     0.108  0.178 -0.071 -0.054  1.000              
## TargetSharingSplit    0.043  0.158 -0.056 -0.016  0.000  1.000       
## CloseOthersTouchTest  0.072  0.188  0.026  0.028  0.135  0.151  1.000
## SSTouchTest           0.116  0.223 -0.055 -0.065  0.096  0.101  0.538
## OSTouchTest           0.118  0.261 -0.155 -0.130 -0.011  0.070  0.263
##                      SSTchT OSTchT
## PriBC                             
## reflection                        
## stress                            
## health                            
## ZCommunalStrength                 
## TargetSharingSplit                
## CloseOthersTouchTest              
## SSTouchTest           1.000       
## OSTouchTest           0.436  1.000

Power analysis

For approximate fit (based on the RMSEA distribution). Statistical power for the detection of a likely misspecified model (RMSEA > .08).

df <- fit.path.model1@test[[1]]$df
alpha <- .05
n <- nrow(exdat)
rmsea0 <- .05           # RMSEA given H0
rmseaa <- .08           # RMSEA given Ha

ncp0 <- (n-1)*df*rmsea0**2 ;
ncpa <-(n-1)*df*rmseaa**2 ;
if(rmsea0 < rmseaa) {
  cval <- qchisq(1-alpha,df=df,ncp=ncp0)
  pwr.rmsea <- 1 - pchisq(cval,df=df,ncp=ncpa)
} else {
  cval <- qchisq(alpha,df=df,ncp=ncp0)
  pwr.rmsea <- pchisq(cval,df=df,ncp=ncpa)
}
rm(ncp0, ncpa, cval)
print(round(pwr.rmsea,10))
## [1] 0.8157743

The power to detect mild model misspecifications is sufficient.

Path model

semPaths(fit.path.model1, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .5, curvature = 2)

Touchscales seem to share most of their variance that is predictive of reflection. Here, OSTouch gets the highest path estimate because it has highest bivariate correlation with reflection. However, that isn’t something that could back up a substantive interpretation of that sort.

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f1 <- NULL
bf1 <- NULL
posterior1 <- NULL
for(i in letters[1:9]){
  f1 <- sem(path.model1, data = exdat, mimic = "Mplus", missing = "ML")
  bf1[i] <- 1/(exp((BIC(f1) - BIC(sem(path.model1, data = exdat, mimic = "Mplus", missing = "ML",
                                      constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior1[i] <- bf1[i]/(1+bf1[i])
}
data.frame(BF10 = bf1, Posterior = round(posterior1, 3))
##           BF10 Posterior
## a 3.148734e-01     0.239
## b 8.142104e-01     0.449
## c 1.866956e+00     0.651
## d 1.048879e-01     0.095
## e 9.492683e+01     0.990
## f 7.952776e-02     0.074
## g 4.820713e+00     0.828
## h 9.072473e+13     1.000
## i 5.810263e+14     1.000

Exploratory model 1a COTouch

path.model1a <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*CloseOthersTouchTest + e*ZCommunalStrength
stress ~ f*reflection
health ~ g*stress
CloseOthersTouchTest ~~ h*TargetSharingSplit
TargetSharingSplit ~~ 0*ZCommunalStrength
'

fit.path.model1a <- sem(path.model1a, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model1a, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         21.626         13.000          0.061          0.957          0.930 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.039          0.000          0.067          0.558       7527.887

The model fits the data exactly.

#####Modification indices
#modificationindices(fit.path.model1a, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model1a, rsquare = TRUE, standardized = TRUE)[1:8,]
##                  lhs op                  rhs label    est    se      z
## 1              PriBC  ~    ZCommunalStrength     a  0.065 0.039  1.678
## 2         reflection  ~                PriBC     b  0.222 0.080  2.781
## 3         reflection  ~   TargetSharingSplit     c  0.168 0.068  2.463
## 4         reflection  ~ CloseOthersTouchTest     d  0.151 0.048  3.127
## 5         reflection  ~    ZCommunalStrength     e  0.159 0.054  2.942
## 6             stress  ~           reflection     f -0.271 0.035 -7.726
## 7             health  ~               stress     g  0.547 0.064  8.577
## 8 TargetSharingSplit ~~ CloseOthersTouchTest     h  0.125 0.043  2.886
##   pvalue ci.lower ci.upper std.lv std.all std.nox
## 1  0.093   -0.022    0.134  0.065   0.102   0.102
## 2  0.005    0.060    0.384  0.222   0.135   0.135
## 3  0.014    0.037    0.302  0.168   0.131   0.131
## 4  0.002    0.057    0.240  0.151   0.143   0.143
## 5  0.003    0.075    0.292  0.159   0.150   0.150
## 6  0.000   -0.337   -0.196 -0.271  -0.386  -0.386
## 7  0.000    0.415    0.681  0.547   0.396   0.396
## 8  0.004    0.029    0.208  0.125   0.151   0.151
#####Bivariate correlations
#lavCor(fit.path.model1a)

Power analysis

For approximate fit (based on the RMSEA distribution). Statistical power for the detection of a likely misspecified model (RMSEA > .08).

df <- fit.path.model1a@test[[1]]$df
alpha <- .05
n <- nrow(exdat)
rmsea0 <- .05           # RMSEA given H0
rmseaa <- .08           # RMSEA given Ha

ncp0 <- (n-1)*df*rmsea0**2 ;
ncpa <-(n-1)*df*rmseaa**2 ;
if(rmsea0 < rmseaa) {
  cval <- qchisq(1-alpha,df=df,ncp=ncp0)
  pwr.rmsea <- 1 - pchisq(cval,df=df,ncp=ncpa)
} else {
  cval <- qchisq(alpha,df=df,ncp=ncp0)
  pwr.rmsea <- pchisq(cval,df=df,ncp=ncpa)
}
rm(ncp0, ncpa, cval)
print(round(pwr.rmsea,10))
## [1] 0.6443162

The power to detect mild model misspecifications is rather low for this and next two models.

Path model

semPaths(fit.path.model1a, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .5)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f1a <- NULL
bf1a <- NULL
posterior1a <- NULL
for(i in letters[1:8]){
  f1a <- sem(path.model1a, data = exdat, mimic = "Mplus", missing = "ML")
  bf1a[i] <- 1/(exp((BIC(f1a) - BIC(sem(path.model1a, data = exdat, mimic = "Mplus", missing = "ML",
                                      constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior1a[i] <- bf1a[i]/(1+bf1a[i])
}
data.frame(BF10 = bf1a, Posterior = round(posterior1a, 3))
##           BF10 Posterior
## a 2.980744e-01     0.230
## b 3.121931e+00     0.757
## c 2.285883e+00     0.696
## d 4.538370e+00     0.819
## e 2.185709e+00     0.686
## f 9.072473e+13     1.000
## g 5.810263e+14     1.000
## h 6.931197e+00     0.874

Exploratory model 1b SSTouch

path.model1b <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*SSTouchTest + e*ZCommunalStrength
stress ~ f*reflection
health ~ g*stress
SSTouchTest ~~ h*TargetSharingSplit
TargetSharingSplit ~~ 0*ZCommunalStrength
'

fit.path.model1b <- sem(path.model1b, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model1b, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         16.586         13.000          0.219          0.982          0.970 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.025          0.000          0.057          0.572       7526.982

The model fits the data exactly.

#####Modification indices
#modificationindices(fit.path.model1b, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model1b, rsquare = TRUE, standardized = TRUE)[1:8,]
##                  lhs op                rhs label    est    se      z
## 1              PriBC  ~  ZCommunalStrength     a  0.065 0.037  1.791
## 2         reflection  ~              PriBC     b  0.203 0.069  2.928
## 3         reflection  ~ TargetSharingSplit     c  0.172 0.071  2.416
## 4         reflection  ~        SSTouchTest     d  0.195 0.054  3.598
## 5         reflection  ~  ZCommunalStrength     e  0.162 0.053  3.052
## 6             stress  ~         reflection     f -0.271 0.034 -8.033
## 7             health  ~             stress     g  0.547 0.059  9.196
## 8 TargetSharingSplit ~~        SSTouchTest     h  0.083 0.038  2.194
##   pvalue ci.lower ci.upper std.lv std.all std.nox
## 1  0.073   -0.010    0.140  0.065   0.102   0.102
## 2  0.003    0.035    0.328  0.203   0.123   0.123
## 3  0.016    0.020    0.292  0.172   0.135   0.135
## 4  0.000    0.075    0.296  0.195   0.184   0.184
## 5  0.002    0.060    0.265  0.162   0.153   0.153
## 6  0.000   -0.329   -0.195 -0.271  -0.385  -0.385
## 7  0.000    0.428    0.656  0.547   0.396   0.396
## 8  0.028    0.019    0.154  0.083   0.101   0.101
#####Bivariate correlations
#lavCor(fit.path.model1b)

Path model

semPaths(fit.path.model1b, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .5)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f1b <- NULL
bf1b <- NULL
posterior1b <- NULL
for(i in letters[1:8]){
  f1b <- sem(path.model1b, data = exdat, mimic = "Mplus", missing = "ML")
  bf1b[i] <- 1/(exp((BIC(f1b) - BIC(sem(path.model1b, data = exdat, mimic = "Mplus", missing = "ML",
                                        constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior1b[i] <- bf1b[i]/(1+bf1b[i])
}
data.frame(BF10 = bf1b, Posterior = round(posterior1b, 3))
##           BF10 Posterior
## a 2.993474e-01     0.230
## b 1.627116e+00     0.619
## c 3.100855e+00     0.756
## d 1.118658e+02     0.991
## e 2.818561e+00     0.738
## f 9.072473e+13     1.000
## g 5.810263e+14     1.000
## h 4.419832e-01     0.307

Exploratory model 1c OSTouch

path.model1c <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*OSTouchTest + e*ZCommunalStrength
stress ~ f*reflection
health ~ g*stress
OSTouchTest ~~ h*TargetSharingSplit
TargetSharingSplit ~~ 0*ZCommunalStrength
'

fit.path.model1c <- sem(path.model1c, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model1c, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         16.905         13.000          0.204          0.981          0.969 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.026          0.000          0.058          0.573       7517.666

The model fits the data exactly.

#####Modification indices
#modificationindices(fit.path.model1c, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

#parameterEstimates(fit.path.model1c, rsquare = TRUE, standardized = TRUE)[1:8,]
#####Bivariate correlations
#lavCor(fit.path.model1c)

Path model

semPaths(fit.path.model1c, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .5)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f1c <- NULL
bf1c <- NULL
posterior1c <- NULL
for(i in letters[1:8]){
  f1c <- sem(path.model1c, data = exdat, mimic = "Mplus", missing = "ML")
  bf1c[i] <- 1/(exp((BIC(f1c) - BIC(sem(path.model1c, data = exdat, mimic = "Mplus", missing = "ML",
                                        constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior1c[i] <- bf1c[i]/(1+bf1c[i])
}
data.frame(BF10 = bf1c, Posterior = round(posterior1c, 3))
##           BF10 Posterior
## a 3.185981e-01     0.242
## b 1.028741e+00     0.507
## c 3.932608e+00     0.797
## d 3.770004e+04     1.000
## e 1.218759e+01     0.924
## f 9.072473e+13     1.000
## g 5.810263e+14     1.000
## h 1.382756e-01     0.121

Models comparison

anova(fit.path.model1c, fit.path.model1b, fit.path.model1a)
## Chi Square Difference Test
## 
##                  Df    AIC    BIC  Chisq Chisq diff Df diff Pr(>Chisq)    
## fit.path.model1c 13 7428.1 7517.7 16.905                                  
## fit.path.model1b 13 7437.4 7527.0 16.586    -0.3190       0          1    
## fit.path.model1a 13 7438.3 7527.9 21.626     5.0402       0     <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Comparison of models in terms of fit based on likelihood ratio test. Models involving SST and OST do not differ from each other but they both fit the data better than the model with COT. It may mean that in the context of modelled variables, COT involves a bit more (but still not a significant portion) of extraneous variance, not explained by the model. Specifically, COT correlates with CS (.14) and that correlation is not accounted for in the model (although the correlation is not so substantial as to cause significantly bad global fit). SST and OST are in no relationship to CS and that’s why they fare a bit better (modelled zero correlation is also observed in the data - statistical zero).

Exploratory model 2 COTouch

Also involving a direct path from CS to reflection. OK?

path.model2 <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*CloseOthersTouchTest + e*ZCommunalStrength
rumination ~ f*ZCommunalStrength + g*CloseOthersTouchTest + h*int_COT_CS
stress ~ i*reflection + j*rumination
health ~ k*stress
reflection ~~ l*rumination
TargetSharingSplit ~~ m*CloseOthersTouchTest
TargetSharingSplit ~~ 0*ZCommunalStrength
CloseOthersTouchTest ~~ ZCommunalStrength
CloseOthersTouchTest ~~ int_COT_CS
int_COT_CS ~~ ZCommunalStrength
'
fit.path.model2 <- sem(path.model2, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model2, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         18.130         20.000          0.579          1.000          1.008 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.000          0.000          0.037          0.535       9691.396

The model fits the data exactly.

#####Modification indices
#modificationindices(fit.path.model2, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model2, rsquare = TRUE)[1:13,]
##                   lhs op                  rhs label    est    se      z
## 1               PriBC  ~    ZCommunalStrength     a  0.069 0.033  2.084
## 2          reflection  ~                PriBC     b  0.214 0.077  2.778
## 3          reflection  ~   TargetSharingSplit     c  0.129 0.043  2.986
## 4          reflection  ~ CloseOthersTouchTest     d  0.151 0.051  2.978
## 5          reflection  ~    ZCommunalStrength     e  0.161 0.055  2.913
## 6          rumination  ~    ZCommunalStrength     f -0.173 0.077 -2.238
## 7          rumination  ~ CloseOthersTouchTest     g  0.014 0.072  0.193
## 8          rumination  ~           int_COT_CS     h -0.196 0.078 -2.507
## 9              stress  ~           reflection     i -0.094 0.032 -2.949
## 10             stress  ~           rumination     j  0.280 0.028 10.045
## 11             health  ~               stress     k  0.547 0.062  8.814
## 12         reflection ~~           rumination     l -0.658 0.072 -9.128
## 13 TargetSharingSplit ~~ CloseOthersTouchTest     m  0.122 0.036  3.392
##    pvalue ci.lower ci.upper
## 1   0.037    0.018    0.152
## 2   0.005    0.042    0.386
## 3   0.003    0.041    0.223
## 4   0.003    0.053    0.282
## 5   0.004    0.051    0.269
## 6   0.025   -0.337   -0.009
## 7   0.847   -0.122    0.169
## 8   0.012   -0.323   -0.017
## 9   0.003   -0.165   -0.027
## 10  0.000    0.226    0.335
## 11  0.000    0.427    0.675
## 12  0.000   -0.829   -0.485
## 13  0.001    0.049    0.194
#####Bivariate correlations
#lavCor(fit.path.model2)

Power analysis

For approximate fit (based on the RMSEA distribution). Statistical power for the detection of a likely misspecified model (RMSEA > .08). Models 1SST and 1OST have the same power.

df <- fit.path.model2@test[[1]]$df
alpha <- .05
n <- nrow(exdat)
rmsea0 <- .05           # RMSEA given H0
rmseaa <- .08           # RMSEA given Ha

ncp0 <- (n-1)*df*rmsea0**2 ;
ncpa <-(n-1)*df*rmseaa**2 ;
if(rmsea0 < rmseaa) {
  cval <- qchisq(1-alpha,df=df,ncp=ncp0)
  pwr.rmsea <- 1 - pchisq(cval,df=df,ncp=ncpa)
} else {
  cval <- qchisq(alpha,df=df,ncp=ncp0)
  pwr.rmsea <- pchisq(cval,df=df,ncp=ncpa)
}
rm(ncp0, ncpa, cval)
print(round(pwr.rmsea,10))
## [1] 0.7994089

The power is sufficient. ####Path model

semPaths(fit.path.model2, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .45, curvature = 3)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f2 <- NULL
bf2 <- NULL
posterior2 <- NULL
for(i in letters[1:13]){
  f2 <- sem(path.model2, data = exdat, mimic = "Mplus", missing = "ML")
  bf2[i] <- 1/(exp((BIC(f2) - BIC(sem(path.model2, data = exdat, mimic = "Mplus", missing = "ML",
                                      constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior2[i] <- bf2[i]/(1+bf2[i])
}
data.frame(BF10 = bf2, Posterior = round(posterior2, 3))
##           BF10 Posterior
## a 3.673561e-01     0.269
## b 8.460169e+00     0.894
## c 1.047416e+00     0.512
## d 4.507381e+00     0.818
## e 2.448003e+00     0.710
## f 8.157399e-01     0.449
## g 4.920057e-02     0.047
## h 2.373109e+00     0.704
## i 3.459359e+00     0.776
## j 1.685678e+21     1.000
## k 5.810263e+14     1.000
## l 1.008702e+26     1.000
## m 5.679214e+00     0.850

Exploratory model 2b SSTouch

Also involving a direct path from CS to reflection. OK?

path.model2b <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*SSTouchTest + e*ZCommunalStrength
rumination ~ f*ZCommunalStrength + g*SSTouchTest + h*int_SST_CS
stress ~ i*reflection + j*rumination
health ~ k*stress
reflection ~~ l*rumination
TargetSharingSplit ~~ m*SSTouchTest
TargetSharingSplit ~~ 0*ZCommunalStrength
SSTouchTest ~~ ZCommunalStrength
SSTouchTest ~~ int_SST_CS
int_SST_CS ~~ ZCommunalStrength
'
fit.path.model2b <- sem(path.model2b, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model2b, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         15.584         20.000          0.742          1.000          1.019 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.000          0.000          0.030          0.537       9740.340

The model fits the data exactly (in statistical sense, within the bounds of alpha, of course) - the path estimates are thus fully interpretable.

#####Modification indices
#modificationindices(fit.path.model2b, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model2b, rsquare = TRUE)[1:13,]
##                   lhs op                rhs label    est    se      z
## 1               PriBC  ~  ZCommunalStrength     a  0.069 0.036  1.923
## 2          reflection  ~              PriBC     b  0.195 0.084  2.313
## 3          reflection  ~ TargetSharingSplit     c  0.139 0.054  2.584
## 4          reflection  ~        SSTouchTest     d  0.194 0.051  3.839
## 5          reflection  ~  ZCommunalStrength     e  0.163 0.055  2.989
## 6          rumination  ~  ZCommunalStrength     f -0.150 0.086 -1.747
## 7          rumination  ~        SSTouchTest     g -0.087 0.069 -1.255
## 8          rumination  ~         int_SST_CS     h -0.093 0.080 -1.170
## 9              stress  ~         reflection     i -0.094 0.031 -2.990
## 10             stress  ~         rumination     j  0.280 0.022 12.802
## 11             health  ~             stress     k  0.547 0.072  7.617
## 12         reflection ~~         rumination     l -0.653 0.083 -7.902
## 13 TargetSharingSplit ~~        SSTouchTest     m  0.083 0.041  2.022
##    pvalue ci.lower ci.upper
## 1   0.054   -0.010    0.136
## 2   0.021    0.014    0.393
## 3   0.010    0.042    0.258
## 4   0.000    0.082    0.292
## 5   0.003    0.086    0.306
## 6   0.081   -0.332    0.014
## 7   0.210   -0.215    0.072
## 8   0.242   -0.246    0.079
## 9   0.003   -0.160   -0.026
## 10  0.000    0.228    0.316
## 11  0.000    0.396    0.699
## 12  0.000   -0.808   -0.467
## 13  0.043   -0.002    0.166
#####Bivariate correlations
#lavCor(fit.path.model2b)

Path model

semPaths(fit.path.model2b, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .45, curvature = 3)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f2b <- NULL
bf2b <- NULL
posterior2b <- NULL
for(i in letters[1:13]){
  f2b <- sem(path.model2b, data = exdat, mimic = "Mplus", missing = "ML")
  bf2b[i] <- 1/(exp((BIC(f2b) - BIC(sem(path.model2b, data = exdat, mimic = "Mplus", missing = "ML",
                                      constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior2b[i] <- bf2b[i]/(1+bf2b[i])
}
data.frame(BF10 = bf2b, Posterior = round(posterior2b, 3))
##           BF10 Posterior
## a 3.567341e-01     0.263
## b 3.644417e+00     0.785
## c 1.872462e+00     0.652
## d 1.047007e+02     0.991
## e 2.997525e+00     0.750
## f 4.060272e-01     0.289
## g 1.234676e-01     0.110
## h 1.272959e-01     0.113
## i 3.459359e+00     0.776
## j 1.685678e+21     1.000
## k 5.810263e+14     1.000
## l 4.761972e+25     1.000
## m 4.208289e-01     0.296

Exploratory model 3b OSTouch

Also involving a direct path from CS to reflection. OK?

path.model2c <- 'PriBC ~ a*ZCommunalStrength
reflection ~ b*PriBC + c*TargetSharingSplit + d*OSTouchTest + e*ZCommunalStrength
rumination ~ f*ZCommunalStrength + g*OSTouchTest + h*int_OST_CS
stress ~ i*reflection + j*rumination
health ~ k*stress
reflection ~~ l*rumination
TargetSharingSplit ~~ m*OSTouchTest
TargetSharingSplit ~~ 0*ZCommunalStrength
OSTouchTest ~~ ZCommunalStrength
OSTouchTest ~~ int_OST_CS
int_OST_CS ~~ ZCommunalStrength
'
fit.path.model2c <- sem(path.model2c, data = exdat, se = "bootstrap", bootstrap = nboot, mimic = "Mplus", missing = "ML")

Model test and approximate fit indices

fitmeasures(fit.path.model2c, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr_mplus", "pnfi", "bic"))
##          chisq             df         pvalue            cfi            tli 
##         27.806         20.000          0.114          0.982          0.968 
##          rmsea rmsea.ci.lower rmsea.ci.upper           pnfi            bic 
##          0.030          0.000          0.055          0.523       9735.083

The model fits the data exactly (in statistical sense, within the bounds of alpha, of course) - the path estimates are thus fully interpretable.

#####Modification indices
#modificationindices(fit.path.model2c, alpha = .05, sort. = TRUE, maximum.number = 5)

Parameter estimates, standard errors, p-values, CI’s, \(R^2\)

parameterEstimates(fit.path.model2c, rsquare = TRUE)[1:13,]
##                   lhs op                rhs label    est    se      z
## 1               PriBC  ~  ZCommunalStrength     a  0.068 0.036  1.879
## 2          reflection  ~              PriBC     b  0.185 0.088  2.101
## 3          reflection  ~ TargetSharingSplit     c  0.142 0.054  2.603
## 4          reflection  ~        OSTouchTest     d  0.257 0.053  4.862
## 5          reflection  ~  ZCommunalStrength     e  0.185 0.057  3.254
## 6          rumination  ~  ZCommunalStrength     f -0.157 0.088 -1.791
## 7          rumination  ~        OSTouchTest     g -0.129 0.070 -1.848
## 8          rumination  ~         int_OST_CS     h -0.006 0.096 -0.062
## 9              stress  ~         reflection     i -0.094 0.030 -3.143
## 10             stress  ~         rumination     j  0.280 0.024 11.448
## 11             health  ~             stress     k  0.547 0.059  9.306
## 12         reflection ~~         rumination     l -0.637 0.065 -9.784
## 13 TargetSharingSplit ~~        OSTouchTest     m  0.058 0.041  1.414
##    pvalue ci.lower ci.upper
## 1   0.060   -0.009    0.146
## 2   0.036   -0.014    0.360
## 3   0.009    0.015    0.242
## 4   0.000    0.164    0.365
## 5   0.001    0.077    0.301
## 6   0.073   -0.349    0.015
## 7   0.065   -0.281    0.009
## 8   0.951   -0.196    0.188
## 9   0.002   -0.160   -0.038
## 10  0.000    0.229    0.325
## 11  0.000    0.456    0.675
## 12  0.000   -0.779   -0.509
## 13  0.157   -0.025    0.150
#####Bivariate correlations
#lavCor(fit.path.model2c)

Path model

semPaths(fit.path.model2c, layout = "tree2", rotation = 2, nDigits = 2, "Standardized", intercepts = FALSE, residuals = FALSE,
         fade = FALSE, nCharNodes = 0, sizeMan = 9, edge.label.cex = .9, edge.label.position = .45, curvature = 3)

Bayes factor in favor of the alternative hypothesis (BF10) and posterior probability for model parameters (given 1:1 prior odds for H0:Ha)

These are Bayes Factors based on model selection / information criteria approach as proposed by Wagenmakers, 2007. Each BF represents the relative evidence in the data favoring alternative hypothesis (parameter freely estimated) over the null (the given parameter fixed to 0). Bayes Factors using BIC approximation implicitly assume unit information prior which makes them rather conservative with regard to the alternative hypothesis.

f2c <- NULL
bf2c <- NULL
posterior2c <- NULL
for(i in letters[1:13]){
  f2c <- sem(path.model2c, data = exdat, mimic = "Mplus", missing = "ML")
  bf2c[i] <- 1/(exp((BIC(f2c) - BIC(sem(path.model2c, data = exdat, mimic = "Mplus", missing = "ML",
                                      constraints = paste(i, '==', '0', sep = ""))))/2))
  posterior2c[i] <- bf2c[i]/(1+bf2c[i])
}
data.frame(BF10 = bf2c, Posterior = round(posterior2c, 3))
##           BF10 Posterior
## a 3.489356e-01     0.259
## b 2.479296e+00     0.713
## c 2.359068e+00     0.702
## d 4.928325e+04     1.000
## e 1.176502e+01     0.922
## f 5.142526e-01     0.340
## g 3.960512e-01     0.284
## h 4.824207e-02     0.046
## i 3.459359e+00     0.776
## j 1.685678e+21     1.000
## k 5.810263e+14     1.000
## l 8.773228e+24     1.000
## m 1.385690e-01     0.122

Models comparison

anova(fit.path.model2, fit.path.model2b, fit.path.model2c)
## Chi Square Difference Test
## 
##                  Df    AIC    BIC  Chisq Chisq diff Df diff Pr(>Chisq)    
## fit.path.model2  20 9553.0 9691.4 18.130                                  
## fit.path.model2b 20 9601.9 9740.3 15.584    -2.5453       0          1    
## fit.path.model2c 20 9596.7 9735.1 27.806    12.2212       0     <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Comparison of models in terms of fit based on likelihood ratio test. Model involving OST fits the data significantly worse than models with COT and SST (they don’t differ from each other in terms of fit).