Validation of Estonian versions of the Pediatric Symptom Checklist -Youth Self-Report and PSC-17 Parent Report

Author

(Authors of the article: Iiris Tuvi, Kenn Konstabel, Hedvig Sultson, Diva Eensoo, Merle Havik, Kaia Laidra, Carolina Murd, Jaana Rahno, Eike Siilbek, Tiia Tulviste; Source code contributed by Kenn Konstabel)

Reading in the data; custom functions

Code
# some simpler variable names
D$att <- D$`Y_PSC-17.Attention.Subscale`
D$int <- D$`Y_PSC-17.Internalizing.Subscale`
D$ext <- D$`Y_PSC-17.Externalizing.Subscale`
D$attlv <- D$`LV_PSC-17.Attention.Subscale`
D$intlv <- D$`LV_PSC-17.Internalizing.Subscale`
D$extlv <- D$`LV_PSC-17.Externalizing.Subscale`
D$rdep <- D$RCADS.Depressioon  # RCADS depression score 
D$ranx <- D$RCADS.Ärevus       # RCADS anxiety score
D$rtot <- D$RCADS.kokku        # RCADS total score
D$kwb <- D$Kidscreen.HEAOLU    # Kindscreen well-being scale

# renaming parent-reported diagnoses
# * LV_terv_prob_5  343 13.5. ...Ärevushäire, nt mõni foobia, obsessiiv-kompulsiivne häire või paanikahäire --> Anxiety disorders
# * LV_terv_prob_6  344 13.6. ...Meeleoluhäire, nt depressioon, bipolaarne häire, maania või düstüümia --> Mood disorders incl depression
# * LV_terv_prob_7  345 13.7. ...Söömishäire, nt anoreksia, buliimia või liigsöömishäire --> eating disorders
# * LV_terv_prob_8  346 13.8. ...Õpiraskused või spetsiifilise akadeemilise oskuse kasutamise raskused (nt kõneareng, lugemine, kirjutamine, aritmeetika) --> learning difficulties
# * LV_terv_prob_9  347 13.9. ...Aktiivsus- ja tähelepanuhäire ehk ATH --> ADHD
# * LV_terv_prob_10 348 13.10. ...Autismispektri häire (varasemalt nimetatud ka kui autism, Aspergeri sündroom, pervasiivne arenguhäire) --> autism spectrum disorder

D$d_adhd <- D$LV_terv_prob_9
D$d_anxm <- D$LV_terv_prob_5 == 1 | D$LV_terv_prob_6 == 1

# gender and age group
D$sugu2 <- factor(D$sugu, levels=1:2)       # gender
D$vg2 <- factor(D$vanus_grupp, levels=2:3)  # age group

# PSC child (self-)report items (variable names)
psc_laps <- c("Y_PSC_1", "Y_PSC_2", "Y_PSC_3", "Y_PSC_4", "Y_PSC_5", "Y_PSC_6",  "Y_PSC_7", "Y_PSC_8", "Y_PSC_9", "Y_PSC_10", "Y_PSC_11", "Y_PSC_12", "Y_PSC_13", "Y_PSC_14", "Y_PSC_15", "Y_PSC_16", "Y_PSC_17")
# PSC parent report variable names
psc_vanem <- gsub("Y", "LV", psc_laps)
names(D)[names(D) %in% psc_laps] <- paste0("PSC", 1:17) -> psc_l
names(D)[names(D) %in% psc_vanem] <- paste0("LV", 1:17) -> psc_lv
# PSC subscales 
att <- c(1,3,7,13,17)
int <- c(2,6,9,11,15)
ext <- setdiff(1:17, c(att,int))
Code
with(D, fftable(ankeedikeel, LV_ankeedikeel, exclude=NULL, labs=c("Child", "Parent")))

Parent

Child

1

2

Total

1

533

10

543

2

15

123

138

Total

548

133

681

Code
D0 <- D
incl <- D$ankeedikeel == 1 & D$LV_ankeedikeel == 1
D <- subset(D, incl)
# Di <- Dj <- Dij <- D

Keeping the respondents if both the parent and the child responded in Estonian. A few 18- and 19-year-olds are included (even though they are not in the target age group).

Descriptive analyses

Background

Chidren’s gender and age (including only those who responded in Estonian)

Code
fftable(D$sugu, D$vanus, labs = c("gender", "age"))

age

gender

8

9

10

11

12

13

14

15

16

17

18

19

Total

1

13

30

32

24

25

26

19

26

24

25

6

0

250

2

13

36

24

28

19

24

23

28

38

33

10

1

277

3

0

1

0

0

0

0

0

0

0

3

0

0

4

4

0

0

0

0

1

0

0

0

0

1

0

0

2

Total

26

67

56

52

45

50

42

54

62

62

16

1

533

Child’s gender and age group (1= 8-10; 2= 11-14; 3= 15+)

Code
fftable(D$sugu, D$vanus_grupp, labs = c("gender", "age group"))

age group

gender

1

2

3

Total

1

75

94

81

250

2

73

94

110

277

3

1

0

3

4

4

0

1

1

2

Total

149

189

195

533

Parent’s gender and age (incl only parents who responded in Estonian)

Code
D$LV_vg <- cut(D$LV_vanus, 2:7*10)
fftable(D$LV_sugu, D$LV_vg, labs=c("gender", "age group"))

age group

gender

(20,30]

(30,40]

(40,50]

(50,60]

(60,70]

Total

1

0

8

20

5

1

34

2

9

150

177

36

1

373

Total

9

158

197

41

2

407

Code
# Correlations in 2nd vs 3rd age group
c1 <- cor(subset(D, D$vanus_grupp==2, select=psc_l), use="pai")
c2 <- cor(subset(D, D$vanus_grupp==3, select=psc_l), use="pai")
plot(lt(c1), lt(c2), xlab="Correlations in the 2nd age group", ylab="Correlations in the 3rd age group")

PSC means by gender and age

Table 4 (first part). Descriptive analysis for gender and age groups and the Cohen d’s of PSC-17-Y and PSC-17-P.

Code
vars1 <- c("att", "int", "ext", "attlv", "intlv", "extlv",  "rdep", "ranx", "rtot", "kwb")
D2 <- subset(D, vg2 %in% 2:3)

a <- aggregate(D2[, vars1], D2['sugu2'], mean, na.rm=T)[,-1]
b <- aggregate(D2[, vars1], D2['sugu2'], mean, na.rm=T)[,-1]

koond <- a
pnts <- c(4,5,6,10)
koond[, pnts] <- b[,pnts]

a <- aggregate(D2[, vars1], D2['sugu2'], sd, na.rm=T)[,-1]
b <- aggregate(D2[, vars1], D2['sugu2'], sd, na.rm=T)[,-1]

koond.sd <- a
koond.sd[, pnts] <- b[, pnts]

n <- function(x) length(na.omit(x))
a <- aggregate(D2[, vars1], D2['sugu2'], n)[,-1]
b <- aggregate(D2[, vars1], D2['sugu2'], n)[,-1]

koond.n <- a
koond.n[, pnts] <- b[, pnts]

koond <- as.matrix(koond); koond.sd <- as.matrix(koond.sd); koond.n <- as.matrix(koond.n)

codi <- function(...){
  res <- effsize::cohen.d(...)
  c(res$estimate, res$conf.int[1], res$conf.int[2])
  }
cohen1 <- sapply(D2[, vars1], function(x) codi(x, D2$sugu2, na.rm=TRUE))

koond1 <- data.frame(VAR = vars1, 
                     Mean.b = koond[1,], SD.b = koond.sd[1,], N.b = koond.n[1,],
                     Mean.g = koond[2,], SD.g = koond.sd[2,], N.g = koond.n[2,],
                     Cd = cohen1[1,], Cd.CIL = cohen1[2,], Cd.CIU = cohen1[3,]
                     )
koond1[,-1] <- lapply(koond1[,-1], round, 2)
qflextable(koond1)

VAR

Mean.b

SD.b

N.b

Mean.g

SD.g

N.g

Cd

Cd.CIL

Cd.CIU

att

3.98

2.44

174

4.73

2.47

203

-0.31

-0.51

-0.10

int

3.48

2.68

175

4.94

2.66

203

-0.55

-0.75

-0.34

ext

3.12

2.13

175

2.53

2.12

203

0.28

0.07

0.48

attlv

3.53

2.32

120

3.38

2.47

130

0.06

-0.18

0.31

intlv

4.02

1.92

120

4.85

2.09

130

-0.41

-0.67

-0.16

extlv

2.95

2.47

120

2.57

2.86

130

0.14

-0.11

0.39

rdep

7.71

5.50

175

9.97

5.93

203

-0.39

-0.60

-0.19

ranx

8.87

6.35

175

13.24

7.37

203

-0.63

-0.84

-0.42

rtot

16.59

11.15

175

23.21

12.58

203

-0.56

-0.76

-0.35

kwb

22.89

5.24

175

21.06

4.84

204

0.36

0.16

0.57

Table 4 (second part). Descriptive analysis for gender and age groups and the Cohen d’s of PSC-17-Y and PSC-17-P.

Code
a <- aggregate(D2[, vars1], D2['vg2'], mean, na.rm=T)[,-1]
b <- aggregate(D2[, vars1], D2['vg2'], mean, na.rm=T)[,-1]

koond <- a
pnts <- c(4,5,6,10)
koond[, pnts] <- b[,pnts]

a <- aggregate(D2[, vars1], D2['vg2'], sd, na.rm=T)[,-1]
b <- aggregate(D2[, vars1], D2['vg2'], sd, na.rm=T)[,-1]

koond.sd <- a
koond.sd[, pnts] <- b[, pnts]

n <- function(x) length(na.omit(x))
a <- aggregate(D2[, vars1], D2['vg2'], n)[,-1]
b <- aggregate(D2[, vars1], D2['vg2'], n)[,-1]

koond.n <- a
koond.n[, pnts] <- b[, pnts]

koond <- as.matrix(koond); koond.sd <- as.matrix(koond.sd); koond.n <- as.matrix(koond.n)
cohen2 <- sapply(D2[, vars1], function(x) codi(x, D2$vg2, na.rm=TRUE))

koond2 <- data.frame(VAR = vars1, 
                     Mean.1 = koond[1,], SD.1 = koond.sd[1,], N.1 = koond.n[1,],
                     Mean.2 = koond[2,], SD.2 = koond.sd[2,], N.2 = koond.n[2,],
                     Cd = cohen2[1,], Cd.CIL = cohen2[2,], Cd.CIU = cohen2[3,]
                     )
koond2[,-1] <- lapply(koond2[,-1], round, 2)

qflextable(koond2)

VAR

Mean.1

SD.1

N.1

Mean.2

SD.2

N.2

Cd

Cd.CIL

Cd.CIU

att

3.96

2.60

187

4.87

2.29

195

-0.37

-0.57

-0.17

int

3.57

2.68

188

4.97

2.68

195

-0.52

-0.73

-0.32

ext

2.73

2.11

188

2.87

2.16

195

-0.07

-0.27

0.13

attlv

3.84

2.50

133

3.03

2.17

122

0.35

0.10

0.59

intlv

4.20

2.04

133

4.74

2.10

122

-0.26

-0.51

-0.01

extlv

3.38

2.54

133

2.04

2.67

122

0.51

0.26

0.77

rdep

7.56

5.89

189

10.38

5.49

194

-0.50

-0.70

-0.29

ranx

10.40

7.19

189

12.13

7.17

194

-0.24

-0.44

-0.04

rtot

17.96

12.52

189

22.50

11.83

194

-0.37

-0.58

-0.17

kwb

23.22

5.01

189

20.52

4.94

195

0.54

0.34

0.75

Correlation matrix of PSC-17-Y items

NB! Order of items as in the questionnaire (different from parental questionnaire)

Code
foo <- D[, psc_l]
foo <- foo[rowSums(!is.na(foo))>0,]

Using pairwise deletion: 384 children responded to at least 1 PSC-17-Y item.

Code
corrs <- corr.test(foo)

p2stars <- function(p) {
  times <- (p<0.05)*1 + (p<0.01)*1 + (p<0.001)*1
  sapply(times, \(x) paste(rep("*",x), collapse=""))
}
combo <- mapply(function(X,Y) sprintf("%.2f%s", X, p2stars(Y)), data.frame(corrs$r), data.frame(corrs$p))
combo[upper.tri(combo, diag = TRUE)] <- ""
combo <- data.frame(" " = colnames(combo), combo)
qflextable(combo)

X.

PSC1

PSC2

PSC3

PSC4

PSC5

PSC6

PSC7

PSC8

PSC9

PSC10

PSC11

PSC12

PSC13

PSC14

PSC15

PSC16

PSC17

PSC1

PSC2

0.36***

PSC3

0.24***

0.32***

PSC4

0.27***

0.23***

0.18***

PSC5

0.29***

0.20***

0.19***

0.32***

PSC6

0.39***

0.60***

0.30***

0.25***

0.30***

PSC7

0.50***

0.43***

0.37***

0.28***

0.31***

0.45***

PSC8

0.20***

0.07

0.07

0.13*

0.15**

0.13*

0.12*

PSC9

0.30***

0.45***

0.34***

0.13*

0.17***

0.49***

0.36***

0.03

PSC10

0.26***

0.10*

0.19***

0.19***

0.18***

0.20***

0.24***

0.15**

0.18***

PSC11

0.32***

0.42***

0.30***

0.21***

0.25***

0.48***

0.39***

0.21***

0.34***

0.15**

PSC12

0.28***

0.18***

0.13**

0.17***

0.24***

0.16**

0.24***

0.26***

0.13*

0.27***

0.19***

PSC13

0.41***

0.24***

0.23***

0.15**

0.20***

0.30***

0.31***

0.16**

0.32***

0.22***

0.21***

0.23***

PSC14

0.24***

0.05

0.15**

0.09

0.18***

0.04

0.13**

0.33***

0.11*

0.30***

0.09

0.29***

0.22***

PSC15

0.32***

0.58***

0.39***

0.15**

0.19***

0.50***

0.37***

0.03

0.54***

0.17***

0.37***

0.09

0.22***

0.08

PSC16

0.16**

0.13*

0.07

0.23***

0.11*

0.13*

0.10*

0.16**

0.10

0.15**

0.12*

0.23***

0.12*

0.23***

0.08

PSC17

0.52***

0.38***

0.37***

0.19***

0.21***

0.38***

0.64***

0.10*

0.32***

0.25***

0.34***

0.23***

0.28***

0.16**

0.33***

0.13*

Code
qflextable(data.frame(" " = colnames(corrs$n), corrs$n))

X.

PSC1

PSC2

PSC3

PSC4

PSC5

PSC6

PSC7

PSC8

PSC9

PSC10

PSC11

PSC12

PSC13

PSC14

PSC15

PSC16

PSC17

PSC1

383

383

381

380

383

379

382

382

382

382

382

381

382

383

382

381

383

PSC2

383

384

382

381

384

380

383

383

383

383

383

382

383

384

383

382

384

PSC3

381

382

382

379

382

379

381

381

381

381

381

380

382

382

381

380

382

PSC4

380

381

379

381

381

379

380

380

380

380

380

379

380

381

380

379

381

PSC5

383

384

382

381

384

380

383

383

383

383

383

382

383

384

383

382

384

PSC6

379

380

379

379

380

380

379

379

379

379

379

378

380

380

379

378

380

PSC7

382

383

381

380

383

379

383

383

383

383

383

382

382

383

382

381

383

PSC8

382

383

381

380

383

379

383

383

383

383

383

382

382

383

382

381

383

PSC9

382

383

381

380

383

379

383

383

383

383

383

382

382

383

382

381

383

PSC10

382

383

381

380

383

379

383

383

383

383

383

382

382

383

382

381

383

PSC11

382

383

381

380

383

379

383

383

383

383

383

382

382

383

382

381

383

PSC12

381

382

380

379

382

378

382

382

382

382

382

382

381

382

381

380

382

PSC13

382

383

382

380

383

380

382

382

382

382

382

381

383

383

382

381

383

PSC14

383

384

382

381

384

380

383

383

383

383

383

382

383

384

383

382

384

PSC15

382

383

381

380

383

379

382

382

382

382

382

381

382

383

383

381

383

PSC16

381

382

380

379

382

378

381

381

381

381

381

380

381

382

381

382

382

PSC17

383

384

382

381

384

380

383

383

383

383

383

382

383

384

383

382

384

Correlation matrix of PSC-17-P items

NB! Order of items as in the parental questionnaire (different from the self-report version)

Code
qux <- D[, psc_lv]
# qux <- D[, pk$lv]
qux <- qux[rowSums(!is.na(qux))>0,]

Using pairwise deletion: 384 children responded to at least 1 PSC-17-Y item.

Code
corrs <- corr.test(qux)

combo <- mapply(function(X,Y) sprintf("%.2f%s", X, p2stars(Y)), data.frame(corrs$r), data.frame(corrs$p))
combo[upper.tri(combo, diag = TRUE)] <- ""
combo <- data.frame(" " = colnames(combo), combo)
qflextable(combo)

X.

LV1

LV2

LV3

LV4

LV5

LV6

LV7

LV8

LV9

LV10

LV11

LV12

LV13

LV14

LV15

LV16

LV17

LV1

LV2

0.47***

LV3

0.36***

0.41***

LV4

0.27***

0.29***

0.47***

LV5

0.39***

0.49***

0.36***

0.30***

LV6

0.12*

0.26***

0.13*

0.00

0.15**

LV7

0.03

0.15**

0.07

0.15**

0.24***

0.17**

LV8

0.17**

0.27***

0.12*

-0.03

0.19***

0.55***

0.35***

LV9

0.24***

0.35***

0.20***

0.04

0.25***

0.57***

0.22***

0.77***

LV10

0.07

0.22***

0.10

0.05

0.17***

0.63***

0.20***

0.41***

0.43***

LV11

0.13*

0.19***

0.08

0.02

0.09

0.33***

0.04

0.20***

0.21***

0.30***

LV12

0.11*

0.22***

0.11*

-0.07

0.18***

0.44***

0.15**

0.40***

0.40***

0.34***

0.41***

LV13

0.14**

0.21***

0.07

-0.02

0.30***

0.33***

0.15**

0.24***

0.24***

0.21***

0.26***

0.45***

LV14

0.08

0.21***

0.05

-0.03

0.12*

0.32***

0.09

0.28***

0.26***

0.22***

0.49***

0.42***

0.45***

LV15

0.21***

0.29***

0.16**

0.01

0.15**

0.37***

0.14**

0.27***

0.35***

0.29***

0.31***

0.47***

0.38***

0.48***

LV16

0.19***

0.23***

0.15**

0.09

0.16**

0.21***

0.15**

0.20***

0.17**

0.18***

0.33***

0.34***

0.40***

0.40***

0.47***

LV17

0.15**

0.20***

0.14**

0.06

0.24***

0.29***

0.14**

0.24***

0.23***

0.28***

0.34***

0.37***

0.41***

0.44***

0.40***

0.45***

Code
qflextable(data.frame(" " = colnames(corrs$n), corrs$n))

X.

LV1

LV2

LV3

LV4

LV5

LV6

LV7

LV8

LV9

LV10

LV11

LV12

LV13

LV14

LV15

LV16

LV17

LV1

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV2

363

363

363

363

363

363

361

363

362

363

363

362

363

361

362

363

363

LV3

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV4

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV5

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV6

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV7

364

361

364

364

364

364

364

364

363

364

364

363

364

363

363

364

364

LV8

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV9

365

362

365

365

365

365

363

365

365

365

365

364

365

363

364

365

365

LV10

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV11

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV12

365

362

365

365

365

365

363

365

364

365

365

365

365

363

364

365

365

LV13

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV14

364

361

364

364

364

364

363

364

363

364

364

363

364

364

363

364

364

LV15

365

362

365

365

365

365

363

365

364

365

365

364

365

363

365

365

365

LV16

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

LV17

366

363

366

366

366

366

364

366

365

366

366

365

366

364

365

366

366

Internal consistency and interitem correlations

See the big combined table below, keeping intermediate results for checking (just in case…)

Table 5 (first part). Internal consistency and interitem correlations - self-reports

Code
Ds <- subset(D, select=psc_l)
t2 <- rbind(alphaomega(Ds, att), alphaomega(Ds, int), alphaomega(Ds, ext)) |> round(2) |> as.data.frame()
t21t <- data.frame(Subscale=c("ATT", "INT", "EXT"), t2)
qflextable(t21t)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.76

0.82

0.39

0.23

0.64

INT

0.82

0.85

0.48

0.34

0.60

EXT

0.65

0.74

0.21

0.10

0.34

Internal consistency and interitem correlations: boys

Code
Ds <- subset(D, sugu==1, select=psc_l)
t2 <- rbind(alphaomega(Ds, att), alphaomega(Ds, int), alphaomega(Ds, ext)) |> round(2) |> as.data.frame()
t21b <- data.frame(Subscale=c("ATT", "INT", "EXT"), t2)
qflextable(t21b)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.77

0.83

0.41

0.23

0.61

INT

0.81

0.84

0.45

0.32

0.56

EXT

0.60

0.73

0.18

0.03

0.36

Internal consistency and interitem correlations: girls

Code
Ds <- subset(D, sugu==2, select=psc_l)
t2 <- rbind(alphaomega(Ds, att), alphaomega(Ds, int), alphaomega(Ds, ext)) |> round(2) |> as.data.frame()
t21g <- data.frame(Subscale=c("ATT", "INT", "EXT"), t2)
qflextable(t21g)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.74

0.80

0.36

0.17

0.65

INT

0.82

0.86

0.48

0.36

0.60

EXT

0.69

0.77

0.25

0.08

0.42

Table 5 (second part). Internal consistency and interitem correlations: parent reports

Code
Dslv <- D[, pk$lv]
t5b <- rbind(alphaomega(Dslv, att), alphaomega(Dslv, int), alphaomega(Dslv, ext)) |> round(2) |> as.data.frame()
t52t <- data.frame(Subscale=c("ATT", "INT", "EXT"), t5b)
qflextable(t52t)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.79

0.87

0.43

0.17

0.77

INT

0.75

0.79

0.38

0.27

0.49

EXT

0.83

0.88

0.40

0.25

0.49

Internal consistency and interitem correlations (parent reports): boys

Code
Dslv <- D[D$sugu==1, pk$lv]
t5b <- rbind(alphaomega(Dslv, att), alphaomega(Dslv, int), alphaomega(Dslv, ext)) |> round(2) |> as.data.frame()
t52b <- data.frame(Subscale=c("ATT", "INT", "EXT"), t5b)
qflextable(t52b)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.81

0.90

0.47

0.16

0.81

INT

0.69

0.76

0.31

0.16

0.47

EXT

0.82

0.88

0.39

0.24

0.53

Internal consistency and interitem correlations (parent reports): girls

Code
Dslv <- D[D$sugu==2, pk$lv]
t5b <- rbind(alphaomega(Dslv, att), alphaomega(Dslv, int), alphaomega(Dslv, ext)) |> round(2) |> as.data.frame()
t52g <- data.frame(Subscale=c("ATT", "INT", "EXT"), t5b)
qflextable(t52g)

Subscale

alpha

omega.tot

avgcor

mincor

maxcor

ATT

0.76

0.85

0.39

0.11

0.72

INT

0.78

0.82

0.42

0.34

0.52

EXT

0.83

0.88

0.41

0.25

0.53

Table 5 (combined)

Code
bt <- cbind(rbind(cbind(t21t, t21b, t21g),
            cbind(t52t, t52b, t52g)), NA, NA)

bt <- bt[, c(1, 2, 8, 14, 20, 3, 9, 15, 20, 4:6, 20, 10:12, 20, 16:18)]
names(bt) <- c("Subscale", "aT", "aB", "aG", " ", "oT", "oB", "oG", "   ", "avgT", "minT", "maxT", "  ", "avgB", "minB", "maxB", "       ", "avgG", "minG", "maxG")
bt$Subscale=c("ATT-Y", "INT-Y", "EXT-Y", "ATT-P", "INT-P", "EXT-P")
qflextable(bt)

Subscale

aT

aB

aG

oT

oB

oG

avgT

minT

maxT

avgB

minB

maxB

avgG

minG

maxG

ATT-Y

0.76

0.77

0.74

0.82

0.83

0.80

0.39

0.23

0.64

0.41

0.23

0.61

0.36

0.17

0.65

INT-Y

0.82

0.81

0.82

0.85

0.84

0.86

0.48

0.34

0.60

0.45

0.32

0.56

0.48

0.36

0.60

EXT-Y

0.65

0.60

0.69

0.74

0.73

0.77

0.21

0.10

0.34

0.18

0.03

0.36

0.25

0.08

0.42

ATT-P

0.79

0.81

0.76

0.87

0.90

0.85

0.43

0.17

0.77

0.47

0.16

0.81

0.39

0.11

0.72

INT-P

0.75

0.69

0.78

0.79

0.76

0.82

0.38

0.27

0.49

0.31

0.16

0.47

0.42

0.34

0.52

EXT-P

0.83

0.82

0.83

0.88

0.88

0.88

0.40

0.25

0.49

0.39

0.24

0.53

0.41

0.25

0.53

Column labels: lowercase part: a = alpha, o = omega, avg = average interitem correlation, min = minimum interitem correlation, max = maximum interitem correlation UPPERCASE part_: T = total, B=boys, G=girls

Gender means and differences

M1 - boys M2 - girls

Code
rbind(msdd(D$att, D$sugu2, "ATT"),
      msdd(D$int, D$sugu2, "INT"),
      msdd(D$ext, D$sugu2, "EXT"),
      msdd(D$attlv, D$sugu2, "ATT (parent report)"),
      msdd(D$intlv, D$sugu2, "INT (parent report)"),
      msdd(D$extlv, D$sugu2, "EXT (parent report)")) |> qflextable()

Subscale

M1

SD1

M2

SD2

d

d.lo

d.up

ATT

3.98

2.44

4.73

2.47

-0.31

-0.51

-0.10

INT

3.48

2.68

4.94

2.66

-0.55

-0.75

-0.34

EXT

3.12

2.13

2.53

2.12

0.28

0.07

0.48

ATT (parent report)

3.85

2.64

3.41

2.39

0.17

-0.03

0.38

INT (parent report)

4.02

1.88

4.59

2.12

-0.29

-0.49

-0.08

EXT (parent report)

3.21

2.63

2.51

2.66

0.26

0.06

0.47

Age group means and differences

M1 - 11-14 M2 - 15+

Code
rbind(msdd(D$att, D$vg2, "ATT"),
      msdd(D$int, D$vg2, "INT"),
      msdd(D$ext, D$vg2, "EXT"),
      msdd(D$attlv, D$vg2, "ATT (parent report)"),
      msdd(D$intlv, D$vg2, "INT (parent report)"),
      msdd(D$extlv, D$vg2, "EXT (parent report)")) |> qflextable()

Subscale

M1

SD1

M2

SD2

d

d.lo

d.up

ATT

3.96

2.60

4.87

2.29

-0.37

-0.57

-0.17

INT

3.57

2.68

4.97

2.68

-0.52

-0.73

-0.32

EXT

2.73

2.11

2.87

2.16

-0.07

-0.27

0.13

ATT (parent report)

3.84

2.50

3.03

2.17

0.35

0.10

0.59

INT (parent report)

4.20

2.04

4.74

2.10

-0.26

-0.51

-0.01

EXT (parent report)

3.38

2.54

2.04

2.67

0.51

0.26

0.77

Self-reports: CFA models and invariance testing

Choices in CFA

We used the WLSMV estimator due to its suitability for ordered categorical indicators and its less stringent sample size requirements compared to alternatives (Brown, 2015). Following the recommendations of Brosseau-Liard and Savalei (2014), we applied robust corrections to the fit indices (CFI, TLI, RMSEA, and SRMR). To interpret the invariance tests, we used the following cutoff values for noninvariance based on Chen (2007): (1) for metric invariance (testing for equality of loadings), a CFI decrease of .010 or greater along with an RMSEA increase of .015 or greater or an SRMR increase of .030 or greater; (2) for scalar invariance (testing for equality of intercepts), a CFI decrease of .010 or greater combined with an RMSEA increase of .015 or greater or an SRMR increase of .010 or greater. Scaled chi-square and df are reported.

Brosseau-Liard, P. E., & Savalei, V. (2014). Adjusting Incremental Fit Indices for Nonnormality. Multivariate Behavioral Research, 49(5), 460–470. https://doi.org/10.1080/00273171.2014.933697

Brown, T. A. (2015). Confirmatory factor analysis for applied research (2nd ed.). Guilford Press. [ ISBN 978-1-4625-1536-3]

Chen, F. F. (2007). Sensitivity of goodness of fit indexes to lack of measurement invariance. Structural Equation Modeling, 14(3), 464–504. https://doi.org/10.1080/10705510701301834

Single-group model

Code
mud1 <- " ATT =~ PSC1 + PSC3 + PSC7 + PSC13 + PSC17
         INT =~ PSC2 + PSC6 + PSC9 + PSC11 + PSC15
         EXT =~ PSC4 + PSC5 + PSC8 + PSC10 + PSC12 + PSC14 + PSC16
"
fit1 <- cfa(mud1, data=D, estimator="WLSMV")

Fit of single-group model in overall sample:

Code
getfms(fit1)

chisq.sc

df.sc

pvalue.sc

cfi.r

tli.r

srmr

rmsea.r

rmsea.ci.lo.r

rmsea.ci.up.r

210

116

0.000000196

0.994

0.993

0.0515

0.0412

0.0322

0.0501

Code
semPaths(fit1, rotation=2, what="std", residuals=FALSE, edge.color="black", esize=1, edge.label.cex=1, sizeMan = 6, node.width=1, node.height=1, weighted=FALSE, nodeLabels = c(PSC1 = "i1", PSC3 = "i3", PSC7 = "i7", PSC13 = "i13", PSC17 = "i17",  PSC2 = "i2", PSC6 = "i6", PSC9 = "i9", PSC11 = "i11", PSC15 = "i15", PSC4 = "i4", PSC5 = "i5", PSC8 = "i8", PSC10 = "i10", PSC12 = "i12", PSC14 = "i14", PSC16 = "i16", ATT = "ATT", INT = "INT", EXT = "EXT" ))

Code
ss <- standardizedsolution(fit1) |> as.data.frame()
ss[,] <- lapply(ss, formatif, 3)
qflextable(ss)

lhs

op

rhs

est.std

se

z

pvalue

ci.lower

ci.upper

ATT

=~

PSC1

0.690

0.0362

19.08

0.0000000000000000

0.619

0.761

ATT

=~

PSC3

0.521

0.0421

12.40

0.0000000000000000

0.439

0.604

ATT

=~

PSC7

0.752

0.0278

27.04

0.0000000000000000

0.697

0.806

ATT

=~

PSC13

0.491

0.0427

11.50

0.0000000000000000

0.407

0.574

ATT

=~

PSC17

0.687

0.0343

20.02

0.0000000000000000

0.619

0.754

INT

=~

PSC2

0.739

0.0340

21.74

0.0000000000000000

0.672

0.805

INT

=~

PSC6

0.768

0.0291

26.40

0.0000000000000000

0.711

0.825

INT

=~

PSC9

0.656

0.0387

16.93

0.0000000000000000

0.580

0.732

INT

=~

PSC11

0.616

0.0428

14.40

0.0000000000000000

0.532

0.700

INT

=~

PSC15

0.679

0.0357

19.03

0.0000000000000000

0.609

0.749

EXT

=~

PSC4

0.486

0.0551

8.82

0.0000000000000000

0.378

0.594

EXT

=~

PSC5

0.548

0.0568

9.65

0.0000000000000000

0.437

0.660

EXT

=~

PSC8

0.321

0.0609

5.27

0.0000001346236267

0.202

0.441

EXT

=~

PSC10

0.495

0.0558

8.87

0.0000000000000000

0.385

0.604

EXT

=~

PSC12

0.530

0.0539

9.83

0.0000000000000000

0.424

0.636

EXT

=~

PSC14

0.389

0.0634

6.14

0.0000000008258743

0.265

0.513

EXT

=~

PSC16

0.355

0.0640

5.55

0.0000000291205704

0.230

0.480

PSC1

~~

PSC1

0.524

0.0499

10.50

0.0000000000000000

0.426

0.622

PSC3

~~

PSC3

0.728

0.0439

16.60

0.0000000000000000

0.642

0.814

PSC7

~~

PSC7

0.435

0.0418

10.40

0.0000000000000000

0.353

0.517

PSC13

~~

PSC13

0.759

0.0419

18.13

0.0000000000000000

0.677

0.841

PSC17

~~

PSC17

0.529

0.0471

11.22

0.0000000000000000

0.436

0.621

PSC2

~~

PSC2

0.455

0.0502

9.06

0.0000000000000000

0.356

0.553

PSC6

~~

PSC6

0.410

0.0447

9.18

0.0000000000000000

0.323

0.498

PSC9

~~

PSC9

0.570

0.0508

11.22

0.0000000000000000

0.470

0.670

PSC11

~~

PSC11

0.620

0.0527

11.77

0.0000000000000000

0.517

0.724

PSC15

~~

PSC15

0.539

0.0485

11.10

0.0000000000000000

0.443

0.634

PSC4

~~

PSC4

0.764

0.0535

14.28

0.0000000000000000

0.659

0.869

PSC5

~~

PSC5

0.699

0.0623

11.23

0.0000000000000000

0.577

0.822

PSC8

~~

PSC8

0.897

0.0391

22.91

0.0000000000000000

0.820

0.974

PSC10

~~

PSC10

0.755

0.0552

13.69

0.0000000000000000

0.647

0.863

PSC12

~~

PSC12

0.719

0.0571

12.59

0.0000000000000000

0.607

0.831

PSC14

~~

PSC14

0.848

0.0494

17.19

0.0000000000000000

0.752

0.945

PSC16

~~

PSC16

0.874

0.0454

19.24

0.0000000000000000

0.785

0.963

ATT

~~

ATT

1.000

0.0000

NA

NA

1.000

1.000

INT

~~

INT

1.000

0.0000

NA

NA

1.000

1.000

EXT

~~

EXT

1.000

0.0000

NA

NA

1.000

1.000

ATT

~~

INT

0.769

0.0359

21.39

0.0000000000000000

0.698

0.839

ATT

~~

EXT

0.690

0.0511

13.50

0.0000000000000000

0.590

0.790

INT

~~

EXT

0.471

0.0612

7.70

0.0000000000000133

0.351

0.591

Age group invariance

Code
fit1mg <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3), estimator = "WLSMV", group="vanus_grupp")
sf1mg <- summary(fit1mg, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg)

#### Age group metric invariance (multigroup model, equal loadings)
fit1mg.el <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3), estimator = "WLSMV", group="vanus_grupp", group.equal="loadings")
sf1mg.el <- summary(fit1mg.el, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg.el)
cf1  <- compareFit(fit1mg, fit1mg.el)
t1 <- cfxtract(cf1, "metric invariance") 

#### Age group scalar invariance (multigroup model, equal intercepts) 
fit1mg.ei <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3), estimator = "WLSMV", group="vanus_grupp", group.equal=c("loadings", "intercepts"))
cf1mg.ei <- summary(fit1mg.ei, fit.measures = TRUE, standardized = TRUE)
cf2 <- compareFit(fit1mg.el, fit1mg.ei)
t1 <- rbind(t1, cfxtract(cf2, "scalar invariance")[2,])
Code
t1$Model[1] <- "configural invariance"
qflextable(t1)

Model

chisq

df

cfi

tli

rmsea

rmsea.ci.lo

rmsea.ci.up

srmr

d.cfi

d.tli

d.rmsea

d.srmr

configural invariance

318.94

232

1.000

1.008

0.043

0.030

0.054

0.059

metric invariance

316.60

246

0.999

0.999

0.043

0.028

0.056

0.065

-0.001

-0.010

0.000

0.005

scalar invariance

340.13

260

0.996

0.996

0.045

0.030

0.057

0.067

-0.002

-0.002

0.002

0.003

Gender invariance

Code
fit1mgs <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu")
sf1mgs <- summary(fit1mg, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg)

#### Gender metric invariance 
fit1mgs.el <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu", group.equal="loadings")
sf1mgs.el <- summary(fit1mgs.el, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg.el)
cf1s  <- compareFit(fit1mgs, fit1mgs.el)
t1s <- cfxtract(cf1s, "metric invariance") 


#### Gender scalar invariance
fit1mgs.ei <- cfa(mud1, data=subset(D, vanus_grupp %in% 2:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu", group.equal=c("loadings", "intercepts"))
sf1mgs.ei <- summary(fit1mgs.ei, fit.measures = TRUE, standardized = TRUE)
cf2s <- compareFit(fit1mgs.el, fit1mgs.ei)
t1s <- rbind(t1s, cfxtract(cf2s, "scalar invariance")[2,])
qflextable(t1s)

Model

chisq

df

cfi

tli

rmsea

rmsea.ci.lo

rmsea.ci.up

srmr

d.cfi

d.tli

d.rmsea

d.srmr

292.06

232

0.986

0.983

0.035

0.020

0.047

0.055

metric invariance

331.93

246

0.971

0.968

0.048

0.034

0.061

0.066

-0.014

-0.015

0.013

0.012

scalar invariance

376.01

260

0.961

0.959

0.054

0.042

0.066

0.072

-0.010

-0.009

0.006

0.005

Parent reports: CFA models and invariance

Single-group model

Code
mud2 <- " ATT =~ LV6 + LV7 + LV8 + LV9 + LV10
         INT =~ LV1 + LV2 + LV3 + LV4 + LV5
         EXT =~ LV11 + LV12 + LV13 + LV14 + LV15 + LV16 + LV17
"

fit2 <- cfa(mud2, data=subset(D, vg2 %in% 2:3), estimator="WLSMV")
Code
getfms(fit2)

chisq.sc

df.sc

pvalue.sc

cfi.r

tli.r

srmr

rmsea.r

rmsea.ci.lo.r

rmsea.ci.up.r

188

116

0.0000271

0.967

0.961

0.0641

0.0465

0.0339

0.0583

Code
semPaths(fit2, rotation=2, what="std", residuals=FALSE, edge.color="black", esize=1, edge.label.cex=1, sizeMan = 6, node.width=1, node.height=1, weighted=FALSE)

Code
ss <- standardizedsolution(fit2) |> as.data.frame()
ss[,] <- lapply(ss, formatif, 3)
qflextable(ss)

lhs

op

rhs

est.std

se

z

pvalue

ci.lower

ci.upper

ATT

=~

LV6

0.778

0.0453

17.18

0.00000000000000000

0.689

0.867

ATT

=~

LV7

0.321

0.0796

4.03

0.00005657285212757

0.165

0.477

ATT

=~

LV8

0.741

0.0382

19.37

0.00000000000000000

0.666

0.816

ATT

=~

LV9

0.773

0.0460

16.80

0.00000000000000000

0.682

0.863

ATT

=~

LV10

0.589

0.0618

9.52

0.00000000000000000

0.468

0.710

INT

=~

LV1

0.684

0.0617

11.08

0.00000000000000000

0.563

0.805

INT

=~

LV2

0.822

0.0489

16.81

0.00000000000000000

0.726

0.918

INT

=~

LV3

0.552

0.0559

9.86

0.00000000000000000

0.442

0.661

INT

=~

LV4

0.450

0.0733

6.14

0.00000000084809404

0.306

0.594

INT

=~

LV5

0.663

0.0614

10.80

0.00000000000000000

0.543

0.783

EXT

=~

LV11

0.602

0.0671

8.97

0.00000000000000000

0.470

0.733

EXT

=~

LV12

0.690

0.0512

13.48

0.00000000000000000

0.590

0.791

EXT

=~

LV13

0.637

0.0544

11.70

0.00000000000000000

0.530

0.744

EXT

=~

LV14

0.711

0.0516

13.78

0.00000000000000000

0.610

0.812

EXT

=~

LV15

0.721

0.0400

18.02

0.00000000000000000

0.643

0.799

EXT

=~

LV16

0.599

0.0556

10.77

0.00000000000000000

0.490

0.708

EXT

=~

LV17

0.562

0.0710

7.91

0.00000000000000244

0.423

0.701

LV6

~~

LV6

0.394

0.0705

5.59

0.00000002234565355

0.256

0.533

LV7

~~

LV7

0.897

0.0511

17.57

0.00000000000000000

0.797

0.997

LV8

~~

LV8

0.451

0.0567

7.95

0.00000000000000178

0.340

0.562

LV9

~~

LV9

0.403

0.0710

5.68

0.00000001370515212

0.264

0.542

LV10

~~

LV10

0.653

0.0728

8.97

0.00000000000000000

0.511

0.796

LV1

~~

LV1

0.532

0.0845

6.30

0.00000000030035685

0.367

0.698

LV2

~~

LV2

0.324

0.0804

4.04

0.00005434458825659

0.167

0.482

LV3

~~

LV3

0.696

0.0617

11.27

0.00000000000000000

0.575

0.817

LV4

~~

LV4

0.797

0.0660

12.08

0.00000000000000000

0.668

0.927

LV5

~~

LV5

0.560

0.0814

6.88

0.00000000000593547

0.401

0.720

LV11

~~

LV11

0.638

0.0807

7.90

0.00000000000000266

0.480

0.796

LV12

~~

LV12

0.524

0.0707

7.40

0.00000000000013145

0.385

0.662

LV13

~~

LV13

0.594

0.0693

8.57

0.00000000000000000

0.458

0.730

LV14

~~

LV14

0.494

0.0734

6.74

0.00000000001592215

0.351

0.638

LV15

~~

LV15

0.480

0.0577

8.33

0.00000000000000000

0.367

0.593

LV16

~~

LV16

0.641

0.0666

9.62

0.00000000000000000

0.511

0.772

LV17

~~

LV17

0.685

0.0797

8.58

0.00000000000000000

0.528

0.841

ATT

~~

ATT

1.000

0.0000

NA

NA

1.000

1.000

INT

~~

INT

1.000

0.0000

NA

NA

1.000

1.000

EXT

~~

EXT

1.000

0.0000

NA

NA

1.000

1.000

ATT

~~

INT

0.353

0.0853

4.13

0.00003550285574838

0.186

0.520

ATT

~~

EXT

0.553

0.0599

9.22

0.00000000000000000

0.435

0.670

INT

~~

EXT

0.299

0.0829

3.61

0.00030527438946271

0.137

0.462

Age group invariance

Code
fit2mg <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3), estimator = "WLSMV", group="vanus_grupp")
sf2mg <- summary(fit2mg, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg)

#### Age group metric invariance (multigroup model, equal loadings)
fit2mg.el <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3), estimator = "WLSMV", group="vanus_grupp", group.equal="loadings")
sf2mg.el <- summary(fit2mg.el, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg.el)
cf3  <- compareFit(fit2mg, fit2mg.el)
t3 <- cfxtract(cf3, "metric invariance") 
anova(fit2mg, fit2mg.el)

Scaled Chi-Squared Difference Test (method = "satorra.2000")

lavaan->lavTestLRT():  
   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)
fit2mg    348         278.63                              
fit2mg.el 376         345.00     28.486      28     0.4389
Code
#### Age group scalar invariance (multigroup model, equal intercepts) 
fit2mg.ei <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3), estimator = "WLSMV", group="vanus_grupp", group.equal=c("loadings", "intercepts"))
cf2mg.ei <- summary(fit2mg.ei, fit.measures = TRUE, standardized = TRUE)
cf4 <- compareFit(fit2mg.el, fit2mg.ei)
anova(fit2mg.el, fit2mg.ei)

Scaled Chi-Squared Difference Test (method = "satorra.2000")

lavaan->lavTestLRT():  
   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)
fit2mg.el 376         345.00                              
fit2mg.ei 404         365.43     32.543      28      0.253
Code
t4 <- rbind(t3, cfxtract(cf4, "scalar invariance")[2,])
Code
t4$Model[1] <- "configural invariance"
qflextable(t4)

Model

chisq

df

cfi

tli

rmsea

rmsea.ci.lo

rmsea.ci.up

srmr

d.cfi

d.tli

d.rmsea

d.srmr

configural invariance

453.21

348

1

1.027

0.051

0.037

0.064

0.074

metric invariance

449.83

376

1

1.011

0.049

0.028

0.065

0.082

0

-0.016

-0.002

0.008

scalar invariance

480.04

404

1

1.013

0.048

0.028

0.064

0.084

0

0.002

-0.001

0.002

Gender invariance

Code
fit2mgs <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu")
sf2mgs <- summary(fit2mg, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg)

#### Gender metric invariance 
fit2mgs.el <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu", group.equal="loadings")
sf2mgs.el <- summary(fit2mgs.el, fit.measures = TRUE, standardized = TRUE)
#getfms(sf1mg.el)
cf2s  <- compareFit(fit2mgs, fit2mgs.el)
anova(fit2mgs, fit2mgs.el)

Scaled Chi-Squared Difference Test (method = "satorra.2000")

lavaan->lavTestLRT():  
   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)
fit2mgs    232         195.56                              
fit2mgs.el 246         226.77     13.365      14      0.498
Code
t2s <- cfxtract(cf2s, "metric invariance") 


#### Gender scalar invariance
fit2mgs.ei <- cfa(mud2, data=subset(D, vanus_grupp %in% 1:3 & sugu %in% 1:2), estimator = "WLSMV", group="sugu", group.equal=c("loadings", "intercepts"))
sf2mgs.ei <- summary(fit2mgs.ei, fit.measures = TRUE, standardized = TRUE)
cf2s <- compareFit(fit2mgs.el, fit2mgs.ei)
anova (fit2mgs.el, fit2mgs.ei)

Scaled Chi-Squared Difference Test (method = "satorra.2000")

lavaan->lavTestLRT():  
   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)    
fit2mgs.el 246         226.77                                  
fit2mgs.ei 260         259.96     50.723      14  4.618e-06 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
t2s <- rbind(t2s, cfxtract(cf2s, "scalar invariance")[2,])
qflextable(t2s)

Model

chisq

df

cfi

tli

rmsea

rmsea.ci.lo

rmsea.ci.up

srmr

d.cfi

d.tli

d.rmsea

d.srmr

329.53

232

1

1.014

0.045

0.034

0.056

0.064

metric invariance

315.95

246

1

1.007

0.044

0.028

0.057

0.068

0

-0.007

-0.002

0.005

scalar invariance

350.58

260

1

1.000

0.048

0.034

0.061

0.072

0

-0.007

0.005

0.004

Convergent correlations

Correlations among PSC subscales and with RCADS and Kidscreen

Table 6. Correlations (Pearson’s r) between the PSC-17-Y, PSC-17-P, depression, anxiety and well-being measures

Code
vars <- c("att", "int", "ext", "attlv", "intlv", "extlv",
"rdep", "ranx", "rtot", "kwb")
kt <- psych::corr.test(subset(D, vg2%in%2:3)[, vars])
ktr <- kt$r
ktr[upper.tri(ktr)]<-NA
rownames(ktr) <- colnames(ktr) <- c("att", "int", "ext", "att(p)", "int(p)", "ext(p)", "R.Depr", "R.Anx", "R.tot", "KS.WB")
ktr <- data.frame(Scale = rownames(ktr), round(ktr,3))
maxp <- format(max(kt$p), digits=2, scientific=FALSE)
qflextable(ktr)

Scale

att

int

ext

att.p.

int.p.

ext.p.

R.Depr

R.Anx

R.tot

KS.WB

att

1.000

int

0.613

1.000

ext

0.483

0.346

1.000

att(p)

0.272

0.127

0.161

1.000

int(p)

0.233

0.344

0.006

0.246

1.000

ext(p)

0.071

0.080

0.271

0.442

0.213

1.000

R.Depr

0.679

0.784

0.431

0.234

0.342

0.115

1.000

R.Anx

0.635

0.746

0.358

0.164

0.311

0.091

0.788

1.000

R.tot

0.692

0.806

0.413

0.206

0.343

0.108

0.933

0.957

1.000

KS.WB

-0.445

-0.592

-0.236

-0.146

-0.317

-0.129

-0.650

-0.511

-0.606

1

The largest p-value for these correlations was 0.92. N varies from 254 to 384.

Parent reports: Correlations with RCADS and Kidscreen

Age groups 2 and 3

Code
vars <- c("attlv", "intlv", "extlv", "RCADS.Depressioon", "RCADS.Ärevus", "RCADS.kokku", "Kidscreen.HEAOLU")
kt <- psych::corr.test(subset(D, vg2%in%2:3)[, vars])
ktr <- kt$r
ktr[upper.tri(ktr)]<-NA
rownames(ktr) <- colnames(ktr) <- c("att", "int", "ext", "RCADS.Depr", "RCADS.Anx", "RCADS.tot", "KS.WB")
p <- kt$p[, 1:3]
p[upper.tri(p)] <- NA
ktr <- data.frame(Scale = rownames(ktr), do.call(cbind, lapply(1:3, \(i) data.frame(round(ktr[,i],2), round(p[,i], 5)))))
names(ktr)[-1] <- c("att.r", "att.p", "int.r", "int.p", "ext.r", "ext.p")
qflextable(ktr)

Scale

att.r

att.p

int.r

int.p

ext.r

ext.p

att

1.00

0.00000

int

0.25

0.00007

1.00

0.00000

ext

0.44

0.00000

0.21

0.00061

1.00

0.00000

RCADS.Depr

0.23

0.00017

0.34

0.00000

0.12

0.06651

RCADS.Anx

0.16

0.00865

0.31

0.00000

0.09

0.14727

RCADS.tot

0.21

0.00094

0.34

0.00000

0.11

0.08707

KS.WB

-0.15

0.01959

-0.32

0.00000

-0.13

0.04018

Code
n <- kt$n[,1:3]

N varies from 254 to 255.

Age group 1

Code
vars <- c("attlv", "intlv", "extlv", "Kidscreen.HEAOLU", "Kidscreen.MEELEOLU")
kt <- psych::corr.test(subset(D, vanus_grupp%in%1)[, vars])
ktr <- kt$r
ktr[upper.tri(ktr)]<-NA
rownames(ktr) <- colnames(ktr) <- c("att", "int", "ext", "KS.WB", "KS.Mood")
p <- kt$p[, 1:3]
p[upper.tri(p)] <- NA
ktr <- data.frame(Scale = rownames(ktr), do.call(cbind, lapply(1:3, \(i) data.frame(round(ktr[,i],2), round(p[,i], 5)))))
names(ktr)[-1] <- c("att.r", "att.p", "int.r", "int.p", "ext.r", "ext.p")
qflextable(ktr)

Scale

att.r

att.p

int.r

int.p

ext.r

ext.p

att

1.00

0.00000

int

0.40

0.00001

1.00

0.00000

ext

0.57

0.00000

0.41

0.00001

1.00

0.00000

KS.WB

-0.14

0.13086

-0.21

0.03099

-0.14

0.14727

KS.Mood

-0.22

0.02205

-0.15

0.11896

-0.17

0.08261

Code
n <- kt$n[,1:3]

N varies from 108 to 111.

Correlations between self- and parental reports

Included: only respondents in 2 older age groups if both child and parent responded in Estonian

Code
#dimensions of data frame: rows x columns
dim(subset(D, vg2%in% 2:3))
[1] 384 480
Code
ct <- corr.test(D[, c("att", "int", "ext")], D[, c("attlv", "intlv", "extlv")])
res <- data.frame(var = rownames(ct$r), r = round(diag(ct$r),3), p = round(diag(ct$p), 5), N = if(length(ct$n)==1) ct$n else diag(ct$n))
qflextable(res)

var

r

p

N

att

0.272

0.00001

254

int

0.344

0.00000

254

ext

0.271

0.00001

254

Correlations between single items (the order of items was different in child’s and parental questionnaires: in the table, the order used in child’s version is used).

Code
ct <- corr.test(D[, pk$laps], D[, pk$lv])
res <- data.frame(var = rownames(ct$r), item = pk$laps_item, r = round(diag(ct$r),3), p = round(diag(ct$p), 5), N = if(length(ct$n)==1) ct$n else diag(ct$n))
qflextable(res)

var

item

r

p

N

PSC1

1. Olen rahutu, ei suuda paigal püsida

0.324

0.00000

255

PSC2

2. Olen kurb, õnnetu

0.168

0.00717

255

PSC3

3. Unistan liiga palju

0.073

0.24758

254

PSC4

4. Keeldun oma asju jagamast

0.170

0.00670

254

PSC5

5. Ma ei mõista teiste inimeste tundeid

0.141

0.02442

255

PSC6

6. Tunnen lootusetust

0.327

0.00000

250

PSC7

7. Mul on raske keskenduda

0.324

0.00000

253

PSC8

8. Kaklen teiste lastega

0.117

0.06290

254

PSC9

9. Olen enda suhtes kriitiline, karm

0.252

0.00005

254

PSC10

10. Süüdistan oma muredes teisi

0.233

0.00018

253

PSC11

11. Mul ei ole nii lõbus kui varem

0.156

0.01290

254

PSC12

12. Ma ei järgi reegleid

0.218

0.00049

252

PSC13

13. Tunnen vajadust pidevalt tegutseda, nagu oleksin üles keeratud

0.105

0.09414

255

PSC14

14. Narrin teisi

0.186

0.00306

253

PSC15

15. Muretsen palju

0.234

0.00017

254

PSC16

16. Võtan asju, mis ei kuulu mulle

0.223

0.00034

254

PSC17

17. Minu tähelepanu kaldub kergesti kõrvale

0.277

0.00001

255

Prediction of health problems

Parental questionnaire included a question about different diseases / disorders diagnosed in the child; among these: anxiety disorders, mood disorders, eating disorders, learning difficulties, ADHD, autism spectrum disorders.

Using the following variables from the data set (see end of each row for English summary:)

Descriptive stats of parent-reported diagnoses

Table 7. Descriptive statistics of parent-reported health problems

Code
# table(D$d_adhd)
# table(D2$d_adhd)
# table(D$d_anxm)
# table(D2$d_anxm)

cd <- function(a,b){
  b <- factor(b)
  res <- effsize::cohen.d(a,b, na.rm=TRUE)
  tt <- t.test(a~ b)
  ttp <- tt$p.value
  ttpa <- (ttp<0.05) + (ttp < 0.01) + (ttp<0.01)
  ttpa <- paste0("", rep("*", ttpa), collapse="")
  res <- c(res$estimate, res$conf.int) 
  sprintf("%0.2f (%0.2f;%0.2f)%s", res[1], res[2], res[3], ttpa)
}

r1m <- with(D2, tapply(att, d_adhd, mean, na.rm=TRUE))
r1sd <- with(D2, tapply(att, d_adhd, sd, na.rm=TRUE))
r1n <- table(subset(D2, !is.na(att))$d_adhd)
r1cd <- with(D2, cd(att, d_adhd))


r2m <- with(D2, tapply(int, d_anxm, mean, na.rm=TRUE))
r2sd <- with(D2, tapply(int, d_anxm, sd, na.rm=TRUE))
r2n <- table(subset(D2, !is.na(int))$d_anxm)
r2cd <- with(D2, cd(int, d_anxm))

r3m <- with(D2, tapply(attlv, d_adhd, mean, na.rm=TRUE))
r3sd <- with(D2, tapply(attlv, d_adhd, sd, na.rm=TRUE))
r3n <- table(subset(D2, !is.na(attlv))$d_adhd)
r3cd <- with(D2, cd(attlv, d_adhd))

r4m <- with(D2, tapply(intlv, d_anxm, mean, na.rm=TRUE))
r4sd <- with(D2, tapply(intlv, d_anxm, sd, na.rm=TRUE))
r4n <- table(subset(D2, !is.na(intlv))$d_anxm)
r4cd <- with(D2, cd(intlv, d_anxm))

t9 <- rbind(
  c(r1m, r1sd, r1n),
    c(r2m, r2sd, r2n),
  c(r3m, r3sd, r3n),
  c(r4m, r4sd, r4n))[, c(2,4,6, 1,3,5)]
t9 <- round(t9,2)

t9 <- data.frame(
  what = c("Att-Y, ADHD", "INT-Y, anx or mood disorder", "ATT-P, ADHD", "INT-P, anx or mood disorder"), as.data.frame(t9), "Cohen_d" = c(r1cd, r2cd, r3cd, r4cd))

names(t9) <- c(" ", "M_d", "SD_d", "N_d", "M_0", "SD_0", "N_0", "Cohen_d")
qflextable(t9)

M_d

SD_d

N_d

M_0

SD_0

N_0

Cohen_d

Att-Y, ADHD

5.36

3.13

14

4.34

2.50

241

-0.40 (-0.94;0.14)

INT-Y, anx or mood disorder

5.96

2.98

27

4.09

2.76

228

-0.67 (-1.08;-0.27)***

ATT-P, ADHD

7.00

2.18

14

3.25

2.22

241

-1.69 (-2.25;-1.13)***

INT-P, anx or mood disorder

6.50

2.18

26

4.23

1.95

229

-1.15 (-1.57;-0.73)***

Fequencies of parent-reported diagnoses by age group

Table: y1= cases of this diagnosis in the first age group; n1 = cases without this diagnosis in the first age group … etc

Code
vars <- paste0("LV_terv_prob_", 5:10)
legend <- c("anxiety disorders", "mood disorders", "eating disorders", "learning difficulties", "ADHD", "autism spectrum disorders")
res <- data.frame(t(aggregate(D[, vars], D['vanus_grupp'], sum, na.rm=T)[,-1]))
res2 <- data.frame(t(aggregate(D[, vars], D['vanus_grupp'], function(x) sum(1-x, na.rm=T))[,-1]))
RES <- do.call(data.frame,mapply(data.frame, res, res2 , SIMPLIFY = FALSE))
names(RES) <- c(outer(c("y", "n"), 1:3, FUN=paste0))
RES$Y = rowSums(res)
RES$N = rowSums(res2)

RES <- data.frame(diagn=legend, RES)
qflextable(RES)

diagn

y1

n1

y2

n2

y3

n3

Y

N

anxiety disorders

5

106

3

131

11

111

19

348

mood disorders

2

109

3

131

17

105

22

345

eating disorders

4

107

2

132

2

120

8

359

learning difficulties

11

100

11

123

6

116

28

339

ADHD

5

106

8

126

6

116

19

348

autism spectrum disorders

2

109

4

130

4

118

10

357

Predicting internalizing disorders (anxiety + mood disorders)

Just sex and age as predictors (using only age groups 2 and 3!)

Code
glm.anx1 <- glm(I(LV_terv_prob_5 | LV_terv_prob_6)~ factor(sugu2) + vanus, data=subset(D, vg2 %in% 2:3), family="binomial")
summary(glm.anx1)

Call:
glm(formula = I(LV_terv_prob_5 | LV_terv_prob_6) ~ factor(sugu2) + 
    vanus, family = "binomial", data = subset(D, vg2 %in% 2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)     -7.8256     1.7534  -4.463 8.08e-06 ***
factor(sugu2)2   0.6950     0.4556   1.525  0.12715    
vanus            0.3532     0.1115   3.167  0.00154 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 167.11  on 250  degrees of freedom
Residual deviance: 151.99  on 248  degrees of freedom
  (133 observations deleted due to missingness)
AIC: 157.99

Number of Fisher Scoring iterations: 5
Code
PseudoR2(glm.anx1)
 McFadden 
0.0904597 

Adding child’s self-reported PSC-internalizing scale

Code
glm.anx2 <- glm(I(LV_terv_prob_5 | LV_terv_prob_6)~  factor(sugu2) + vanus + scale(int), data=subset(D, vg2 %in% 2:3), family="binomial") 
summary(glm.anx2)

Call:
glm(formula = I(LV_terv_prob_5 | LV_terv_prob_6) ~ factor(sugu2) + 
    vanus + scale(int), family = "binomial", data = subset(D, 
    vg2 %in% 2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)     -7.0928     1.7861  -3.971 7.15e-05 ***
factor(sugu2)2   0.6076     0.4617   1.316   0.1882    
vanus            0.3002     0.1142   2.628   0.0086 ** 
scale(int)       0.4277     0.2267   1.887   0.0592 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 166.89  on 249  degrees of freedom
Residual deviance: 148.18  on 246  degrees of freedom
  (134 observations deleted due to missingness)
AIC: 156.18

Number of Fisher Scoring iterations: 6
Code
PseudoR2(glm.anx2)
 McFadden 
0.1121497 

–> OR = 1.67 (for 1 SD change in child’s self-report)

Adding parent report

Code
glm.anx3 <- glm(I(LV_terv_prob_5 | LV_terv_prob_6)~  factor(sugu2) + vanus + scale(int) + scale(intlv), data=subset(D, vg2 %in% 2:3), family="binomial") 
summary(glm.anx3)

Call:
glm(formula = I(LV_terv_prob_5 | LV_terv_prob_6) ~ factor(sugu2) + 
    vanus + scale(int) + scale(intlv), family = "binomial", data = subset(D, 
    vg2 %in% 2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)     -8.5034     2.0265  -4.196 2.72e-05 ***
factor(sugu2)2   0.2315     0.4978   0.465 0.641883    
vanus            0.3788     0.1266   2.993 0.002762 ** 
scale(int)       0.2463     0.2430   1.014 0.310807    
scale(intlv)     1.0285     0.2699   3.811 0.000139 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 162.33  on 248  degrees of freedom
Residual deviance: 124.41  on 244  degrees of freedom
  (135 observations deleted due to missingness)
AIC: 134.41

Number of Fisher Scoring iterations: 6
Code
PseudoR2(glm.anx3)
 McFadden 
0.2335861 

–> OR = 3.15 (for 1 SD change in parent report)

Predicting ADHD from attention subscale

Code
glm.ath1 <- glm(LV_terv_prob_9 ~ factor(sugu2) + vanus, data=subset(D, vg2 %in% 2:3), family="binomial") 
summary(glm.ath1)

Call:
glm(formula = LV_terv_prob_9 ~ factor(sugu2) + vanus, family = "binomial", 
    data = subset(D, vg2 %in% 2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)
(Intercept)     -1.0086     1.7940  -0.562    0.574
factor(sugu2)2  -0.3457     0.5590  -0.618    0.536
vanus           -0.1188     0.1301  -0.913    0.361

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 108.02  on 250  degrees of freedom
Residual deviance: 106.65  on 248  degrees of freedom
  (133 observations deleted due to missingness)
AIC: 112.65

Number of Fisher Scoring iterations: 6
Code
PseudoR2(glm.ath1)
  McFadden 
0.01269651 

Adding self-report

Code
glm.ath2 <- glm(LV_terv_prob_9 ~ factor(sugu2) + vanus + scale(att), data=subset(D, vg2 %in% 2:3), family="binomial") 
summary(glm.ath2)

Call:
glm(formula = LV_terv_prob_9 ~ factor(sugu2) + vanus + scale(att), 
    family = "binomial", data = subset(D, vg2 %in% 2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)  
(Intercept)     -0.4205     1.8448  -0.228    0.820  
factor(sugu2)2  -0.3967     0.5650  -0.702    0.483  
vanus           -0.1641     0.1349  -1.216    0.224  
scale(att)       0.4871     0.2708   1.799    0.072 .
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 107.91  on 249  degrees of freedom
Residual deviance: 103.26  on 246  degrees of freedom
  (134 observations deleted due to missingness)
AIC: 111.26

Number of Fisher Scoring iterations: 6
Code
PseudoR2(glm.ath2)
  McFadden 
0.04304296 

Adding parent report

Code
glm.ath3 <- glm(LV_terv_prob_9 ~ factor(sugu2) + vanus + scale(att) + scale(attlv), data=subset(D, vg2 %in% 2:3), family="binomial") 
summary(glm.ath3)

Call:
glm(formula = LV_terv_prob_9 ~ factor(sugu2) + vanus + scale(att) + 
    scale(attlv), family = "binomial", data = subset(D, vg2 %in% 
    2:3))

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)    -3.86399    2.30009  -1.680    0.093 .  
factor(sugu2)2 -0.53616    0.63236  -0.848    0.397    
vanus           0.01926    0.15530   0.124    0.901    
scale(att)      0.07749    0.30639   0.253    0.800    
scale(attlv)    1.48335    0.33447   4.435 9.21e-06 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 107.793  on 248  degrees of freedom
Residual deviance:  77.497  on 244  degrees of freedom
  (135 observations deleted due to missingness)
AIC: 87.497

Number of Fisher Scoring iterations: 7
Code
PseudoR2(glm.ath3)
 McFadden 
0.2810518