pcfa-examples

Note: the estimation process can be time consuming depending on the computing power. You can same some time by reducing the length of the chains.

Continuous Data w/o Local Dependence:

  1. Load the package, obtain the data, loading pattern (qlam), and setup the design matrix Q.
library(LAWBL)
dat <- sim18cfa0$dat
J <- ncol(dat) # no. of items
K <- 3 # no. of factors
qlam <- sim18cfa0$qlam
qlam
#>       [,1] [,2] [,3]
#>  [1,]  0.7  0.0  0.0
#>  [2,]  0.7  0.0  0.0
#>  [3,]  0.7  0.0  0.0
#>  [4,]  0.7  0.0  0.0
#>  [5,]  0.7  0.4  0.0
#>  [6,]  0.7  0.4  0.0
#>  [7,]  0.0  0.7  0.0
#>  [8,]  0.0  0.7  0.0
#>  [9,]  0.0  0.7  0.0
#> [10,]  0.0  0.7  0.0
#> [11,]  0.0  0.7  0.4
#> [12,]  0.0  0.7  0.4
#> [13,]  0.0  0.0  0.7
#> [14,]  0.0  0.0  0.7
#> [15,]  0.0  0.0  0.7
#> [16,]  0.0  0.0  0.7
#> [17,]  0.4  0.0  0.7
#> [18,]  0.4  0.0  0.7

Q<-matrix(-1,J,K); # -1 for unspecified items
Q[1:2,1]<-Q[7:8,2]<-Q[13:14,3]<-1 # 1 for specified items
Q
#>       [,1] [,2] [,3]
#>  [1,]    1   -1   -1
#>  [2,]    1   -1   -1
#>  [3,]   -1   -1   -1
#>  [4,]   -1   -1   -1
#>  [5,]   -1   -1   -1
#>  [6,]   -1   -1   -1
#>  [7,]   -1    1   -1
#>  [8,]   -1    1   -1
#>  [9,]   -1   -1   -1
#> [10,]   -1   -1   -1
#> [11,]   -1   -1   -1
#> [12,]   -1   -1   -1
#> [13,]   -1   -1    1
#> [14,]   -1   -1    1
#> [15,]   -1   -1   -1
#> [16,]   -1   -1   -1
#> [17,]   -1   -1   -1
#> [18,]   -1   -1   -1
  1. E-step: Estimate with the PCFA-LI model (E-step) by setting LD=F. Only a few loadings need to be specified in Q (e.g., 2 per factor). Longer chain is suggested for stabler performance (burn=iter=5,000 by default). Note the sampling information is updated every 1000 draws by default, with Feigen for factorial eigenvalue, “NLA_lg3” for no. of \(\lambda\) larger than .3, Shrink for shrinkage, and Adj PSR for adjusted PSRF. Estimates are close to the true values.
m0 <- pcfa(dat = dat, Q = Q,LD = FALSE, burn = 2000, iter = 2000)

# summarize basic information
summary(m0)
#> $N
#> [1] 500
#> 
#> $J
#> [1] 18
#> 
#> $K
#> [1] 3
#> 
#> $`Miss%`
#> [1] 0
#> 
#> $`LD enabled`
#> [1] FALSE
#> 
#> $`Burn in`
#> [1] 2000
#> 
#> $Iteration
#> [1] 2000
#> 
#> $`No. of sig lambda`
#> [1] 24
#> 
#> $`Adj. PSR`
#>    Point est. Upper C.I.
#> F1   1.159097   1.437669
#> F2   1.377527   2.323779
#> F3   1.069836   1.274876

#summarize significant loadings in pattern/Q-matrix format
summary(m0, what = 'qlambda') 
#>          [,1]      [,2]      [,3]
#> I1  0.7006520 0.0000000 0.0000000
#> I2  0.7129764 0.0000000 0.0000000
#> I3  0.7201485 0.0000000 0.0000000
#> I4  0.6764871 0.0000000 0.0000000
#> I5  0.7018335 0.3981160 0.0000000
#> I6  0.6705350 0.4148202 0.0000000
#> I7  0.0000000 0.7219834 0.0000000
#> I8  0.0000000 0.7758877 0.0000000
#> I9  0.0000000 0.7342936 0.0000000
#> I10 0.0000000 0.6643274 0.0000000
#> I11 0.0000000 0.6936387 0.3736486
#> I12 0.0000000 0.6626755 0.4260824
#> I13 0.0000000 0.0000000 0.6365149
#> I14 0.0000000 0.0000000 0.6849702
#> I15 0.0000000 0.0000000 0.7129319
#> I16 0.0000000 0.0000000 0.7902067
#> I17 0.3956917 0.0000000 0.7233275
#> I18 0.3888041 0.0000000 0.7186225

#factorial eigenvalue
summary(m0,what='eigen') 
#>         est        sd    lower    upper sig
#> F1 3.332857 0.4751161 2.472778 4.148886   1
#> F2 3.485774 0.5385707 2.567001 4.614304   1
#> F3 3.492405 0.4823052 2.616686 4.444067   1

#plotting factorial eigenvalue
par(mar = rep(2, 4))
plot_eigen(m0) # trace

plot_eigen(m0, what='density') #density

plot_eigen(m0, what='APSR') #adj, PSRF

  1. C-step: Reconfigure the Q matrix for the C-step with one specified loading per item based on results from the E-step. Estimate with the PCFA model by setting LD=TRUE (by default). Longer chain is suggested for stabler performance. LD>.2 >.1 are no. of LD terms larger than .2 and .1. Results are very close to the E-step, since there’s no LD in the data.
Q<-matrix(-1,J,K);
tmp<-summary(m0, what="qlambda")
cind<-apply(tmp,1,which.max)
Q[cbind(c(1:J),cind)]<-1
#alternatively
#Q[1:6,1]<-Q[7:12,2]<-Q[13:18,3]<-1 # 1 for specified items

m1 <- pcfa(dat = dat, Q = Q, burn = 2000, iter = 2000)
summary(m1)
summary(m1, what = 'qlambda')
summary(m1, what = 'offpsx') #summarize significant LD terms
summary(m1,what='eigen')

#plotting factorial eigenvalue
oldmar <- par("mar")
par(mar = rep(2, 4))
plot_eigen(m1) # trace
plot_eigen(m1, what='density') #density
plot_eigen(m1, what='APSR') #adj, PSRF
  1. CFA-LD: One can also configure the Q matrix for a CFA model with local dependence (i.e. without any unspecified loading) based on results from the C-step. Results are also very close.
Q<-summary(m1, what="qlambda")
Q[Q!=0]<-1
Q

m2 <- pcfa(dat = dat, Q = Q, burn = 2000, iter = 2000)
summary(m2)
summary(m2, what = 'qlambda') 
summary(m2, what = 'offpsx')
summary(m2,what='eigen')

plot_eigen(m2) # Eigens' traces are excellent without regulazation of the loadings

Continuous Data with Local Dependence:

  1. Load the the data, loading pattern (qlam), and LD terms, and setup the design matrix Q.
dat <- sim18cfa1$dat
J <- ncol(dat) # no. of items
K <- 3 # no. of factors
sim18cfa1$qlam
sim18cfa1$LD # effect size = .3

Q<-matrix(-1,J,K); # -1 for unspecified items
Q[1:2,1]<-Q[7:8,2]<-Q[13:14,3]<-1 # 1 for specified items
Q
  1. E-step: Estimate with the PCFA-LI model (E-step) by setting LD=FALSE. Only a few loadings need to be specified in Q (e.g., 2 per factor). Some loading estimates are biased due to ignoring the LD. So do the eigenvalues.
m0 <- pcfa(dat = dat, Q = Q,LD = FALSE, burn = 10000, iter = 10000)
summary(m0)
summary(m0, what = 'qlambda')
summary(m0,what='eigen')

plot_eigen(m0) # trace
plot_eigen(m0, what='APSR')
  1. C-step: Reconfigure the Q matrix for the C-step with one specified loading per item based on results from the E-step. Estimate with the PCFA model by setting LD=TRUE (by default). The estimates are more accurate, and the LD terms can be largely recovered.
Q<-matrix(-1,J,K);
tmp<-summary(m0, what="qlambda")
cind<-apply(tmp,1,which.max)
Q[cbind(c(1:J),cind)]<-1
Q

m1 <- pcfa(dat = dat, Q = Q,burn = 10000, iter = 10000)
summary(m1)
summary(m1, what = 'qlambda')
summary(m1,what='eigen')
summary(m1, what = 'offpsx')
  1. CFA-LD: Configure the Q matrix for a CFA model with local dependence (i.e. without any unspecified loading) based on results from the C-step. Results are better than, but similar to the C-step.
Q<-summary(m1, what="qlambda")
Q[Q!=0]<-1
Q

m2 <- pcfa(dat = dat, Q = Q,burn = 10000, iter = 10000)
summary(m2)
summary(m2, what = 'qlambda') 
summary(m2,what='eigen')
summary(m2, what = 'offpsx')

par(mar = oldmar) #reset to old mar