# 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