Bài viết này giới thiệu cho các bạn hàm sử dụng để tính BẢNG Các chỉ số về độ tin cậy tổng hợp, giá trị hội tụ và giá trị phân biệt của các biến của model CFA.

Chúng ta sẽ sử dụng 1 hàm tự code, tên là funCFA(), dựa trên hàm của gói lệnh semTools, require(semTools).

Hàm funCFA() được sử dụng nhiều lần mỗi khi chúng ta cần tính các chỉ số trên

Tài liệu phục vụ HỘI THẢO THỐNG KÊ TRONG KHOA HỌC XÃ HỘI VỚI PHẦN MỀM MÃ NGUỒN MỞ R Chi tiết tại: https://sites.google.com/view/tkud https://viasm.edu.vn/

GIỚI THIỆU

Dữ liệu sử dụng trong hướng dẫn này là của PGS.TS Trần Văn Trang (Đại học Thương mại).

Bài báo gốc lấy tại: http://tckhtm.tmu.edu.vn/vi/news/cac-so-tap-chi/tap-chi-khoa-hoc-thuong-mai-so-141-153.html

Dữ liệu tải tại google diver: https://drive.google.com/drive/folders/1Npip6h8WyZjI9JGf5wonnU_scBUYj4sP?usp=sharing

Load các gói cần thiết và nhập liệu

setwd("D:/Tap huan VIASM/HoiThao_KHXH_2021/Projects/Y_Dinh_Hanh_Vi")

library(foreign)
require(tidyverse)
require(lavaan)
require(semTools)
d <- read.spss("Case study Behavior Intention.sav",
               use.value.label=TRUE, to.data.frame=TRUE)

1. Lọc các biến quan sát (items)

d1 <-  d %>% select(-c("STT",  "FAM", "Formation",
                       "Work",  "Year",
                       "BI1",     "BIRecode", "BI4"))

2. Tìm hiểu các hàm trong gói semTools tại:

https://cran.r-project.org/web/packages/semTools/index.html

3. Giới thiệu hàm funCFA()

Đây là hàm tự viết code, không thuộc gói lệnh nào và được định nghĩa như dưới này.

Sử dụng: Hàm có hai tham số đầu vào là:

Định nghĩa hàm như dưới này

#----------------By Huong Trinh (TMU), 27_8_2021
# For: https://viasm.edu.vn/hdkh/hoi-thao-thong-ke-trong-khoa-hoc-xa-hoi-voi-phan-mem-ma-nguon-mo-r

funCFA <- function(modelCFA, ndigit )
{
  # modelCFA: A CFA mode, after using cfa function in Lavaan
 # ndigit: number of digits 
  #Find auto latents
 Varlatent <- standardizedSolution(modelCFA) %>% 
    filter(op == "=~") %>% 
    select(lhs) %>%
    unique()
 nVl <- length(Varlatent$lhs)
 # Find items 
 VarItems <- list()
 for ( i in Varlatent$lhs)
 {
   VarItems[[i]] <- standardizedSolution(modelCFA) %>%
                      filter(op == "=~" & lhs == i) %>% select(rhs) %>% unique() 
 }
 
 # Prepare table form
 TabMDF <- data.frame(Latent = Varlatent$lhs,
                      CR = rep(NA,  nVl),
                      AVE = rep(NA,  nVl),  MSV = rep(NA,  nVl))
 for ( i in Varlatent$lhs)
 {
   TabMDF[, i] <- NA
 }
 
#-----------------Fill cot CR
 sl <- standardizedSolution(modelCFA)
 sl <- sl$est.std[sl$op == "=~"] # estimated deviation
 names(sl) <- modelCFA@Model@ dimNames[[2]][[1]] # to take item's names of used model
 #Compute residual variance of each item
 re <- 1 - sl^2
 
 #CR for each latent
 
 for ( i in 1: length(Varlatent$lhs))
 {
   nlt <- Varlatent$lhs[i]
   vitems <- VarItems[[i]]$rhs
   TabMDF[TabMDF$Latent ==  nlt, "CR"] <- round(sum(sl[ vitems ])^2/(sum(sl[ vitems])^2 + sum(re[ vitems])), ndigit)
 } 
 
 
 #=======reliability and validity===============================================
 
 #Calculate reliability values of factors
 #AVE
 AVE <- semTools::reliability (modelCFA)
 
 AVE <- round(AVE["avevar", ],  ndigit)

 for ( i in 1: length(Varlatent$lhs))
 {
   nlt <- Varlatent$lhs[i]
   TabMDF[TabMDF$Latent ==  nlt, "AVE"] <-  AVE[ nlt ]
 } 

 #MSV
 
 MSV4a <- semTools::discriminantValidity (modelCFA) # He so tuong quan giua cac bien
 
 for ( i in 1: length(Varlatent$lhs))
 {
   nlt <- Varlatent$lhs[i]
   tempMSV <-  MSV4a %>% filter(lhs == nlt  |rhs== nlt ) %>% 
     select(est) %>% max()
   TabMDF[TabMDF$Latent ==  nlt, "MSV"] <- round(tempMSV^2, ndigit)
 }
 
 #MACOR
 MACOR <-  MSV4a %>%  select(c(lhs, op, rhs ,  est, 'Pr(>Chisq)'))
  pvalue <- ifelse(MACOR$'Pr(>Chisq)' <= 0.001, "***",
                        ifelse(MACOR$'Pr(>Chisq)' > 0.001 &MACOR$ 'Pr(>Chisq)'<0.01, "**", 
                               ifelse(MACOR$'Pr(>Chisq)' > 0.01 & MACOR$'Pr(>Chisq)'<0.05, "*", " ")))
 
 MACOR <- MACOR %>% mutate(estF = paste0(round(MACOR$est, ndigit), pvalue)) %>%
   select(lhs, op, rhs, estF)
 #MACOR
 
 for ( i in 1: length(Varlatent$lhs))
 {
   nlti <- Varlatent$lhs[i]
   for ( j in 1: length(Varlatent$lhs))
   {
     nltj <- Varlatent$lhs[j]
     
    MACORtempts <-  MACOR[ MACOR$lhs ==  nlti &   MACOR$rhs == nltj, "estF"] 
     TabMDF[TabMDF$Latent ==  nltj, nlti] <- 
       ifelse(i == j , round( sqrt(TabMDF[TabMDF$Latent ==  nlti, "AVE"]), ndigit ),  MACORtempts)
   }
 }
 
 return(TabMDF)
}

4. Áp dụng vào model CFA

cfa.model2 <- ' BEINTEN =~  BI2 + BI3 + BI5 + BI6 
              RELA =~ REL1 + REL2 + REL3+ REL4
              EDUC =~ EDU1 + EDU2 + EDU3 + EDU4 + EDU5 + EDU6 + EDU7  +  EDU8
              GOVE =~ GOV1 + GOV2 + GOV3 + GOV4 + GOV5
              ENDO =~  END1 + END2 + END3 + END4 + END5 ' #No END1 in the Trang (2020)
cfa.d2 <- cfa(cfa.model2, data = d1)

#=======reliability and validity by funCFA  ===============================================

Table.cfa.d2 <- funCFA(cfa.d2,  ndigit = 2)
## Some of the latent variable variances are estimated instead of fixed to 1. The model is re-estimated by scaling the latent variables by fixing their variances and freeing all factor loadings.
Table.cfa.d2 
##    Latent   CR  AVE  MSV  BEINTEN    RELA    EDUC    GOVE ENDO
## 1 BEINTEN 0.80 0.50 0.44     0.71    <NA>    <NA>    <NA> <NA>
## 2    RELA 0.82 0.55 0.44  0.67***    0.74    <NA>    <NA> <NA>
## 3    EDUC 0.91 0.57 0.32  0.38*** 0.47***    0.75    <NA> <NA>
## 4    GOVE 0.87 0.56 0.32  0.37*** 0.41*** 0.57***    0.75 <NA>
## 5    ENDO 0.84 0.51 0.08 -0.03*** 0.02*** 0.28*** 0.26*** 0.71
write.csv(Table.cfa.d2, file = "Table.cfa.d2.csv")

5. Áp dụng hàm CFA

cfa.model4a <- ' BEINTEN =~  BI2 + BI3 + BI5 + BI6 
              RELA =~ REL1 + REL2 + REL3+ REL4
              EDUC =~ EDU1 + EDU2 + EDU3 + EDU4 + EDU5 + EDU6 + EDU7  +  EDU8
              GOVE =~ GOV1 + GOV2 + GOV3 + GOV4 + GOV5
              ENDO =~   END2 + END3 + END4 + END5  
#  Covariance
BI2 ~~ BI3
REL4  ~~ REL1 + REL3
EDU2 ~~ EDU1 + EDU3 + EDU6
EDU5 ~~ EDU6
EDU7 ~~ EDU8
GOV4 ~~ GOV5
END5 ~~ END4 ' 
cfa.d4a <- cfa(cfa.model4a, data = d1)
#=======reliability and validity by funCFA  ===============================================

Table.cfa.d4a <- funCFA(cfa.d4a,  ndigit = 2)
## Some of the latent variable variances are estimated instead of fixed to 1. The model is re-estimated by scaling the latent variables by fixing their variances and freeing all factor loadings.
## Warning in lav_object_post_check(object): lavaan WARNING: covariance matrix of latent variables
##                 is not positive definite;
##                 use lavInspect(fit, "cov.lv") to investigate.
Table.cfa.d4a
##    Latent   CR  AVE  MSV  BEINTEN     RELA    EDUC    GOVE ENDO
## 1 BEINTEN 0.78 0.48 0.47     0.69     <NA>    <NA>    <NA> <NA>
## 2    RELA 0.82 0.55 0.47  0.69***     0.74    <NA>    <NA> <NA>
## 3    EDUC 0.91 0.55 0.34   0.4***  0.44***    0.74    <NA> <NA>
## 4    GOVE 0.86 0.55 0.34  0.36***  0.39*** 0.58***    0.74 <NA>
## 5    ENDO 0.82 0.52 0.06 -0.05*** -0.03*** 0.24*** 0.23*** 0.72
write.csv(Table.cfa.d4a, file = "Table.cfa.d4a.csv")

Trân trọng cảm ơn!