Bài viết này giới thiệu cho các bạn phương pháp điều chỉnh mô hình độ phù hợp của mô hình CFA qua hàm modindices() trong gói lavaan.

Chúng ta sẽ sử dụng 1 hàm tự code, tên là funCFA_mi(), dựa trên hàm modindices() trong gói lavaans, để tự động tìm ra các mối cần nối của từng nhân tố tiềm ẩn. Các bạn sẽ sử dụng hàm funCFA_mi() nhiều lần với các model khác nhau đến khi đạt được mô hình hợp lý.

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)

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 hàm modindices()

? modindices

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

Đâ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), 29_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_mi <- function(modelCFA, cutoff_mi )
{
   # modelCFA: A CFA mode, after using cfa function in Lavaan
   # cutoff_mi: a positive value 
   #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() 
   }

   #to find items to connect
   Mi_Final <- list()
   for (i in   Varlatent$lhs)
   {
      i_var <-  VarItems[[i]]$rhs
      Mi_Final[[i]] <- modindices(modelCFA) %>% 
    filter(op == "~~" & mi > cutoff_mi & lhs %in% i_var  &rhs %in% i_var ) %>%
         select(lhs, op, rhs)
   }
   return(Mi_Final )
}

4. Áp dụng vào model CFA và giả sử cutoff_mi = 10

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)
mi_d2 <- funCFA_mi (cfa.d2, 15 )

Xem các cặp items cần nối

mi_d2
## $BEINTEN
##   lhs op rhs
## 1 BI2 ~~ BI3
## 2 BI3 ~~ BI6
## 3 BI5 ~~ BI6
## 
## $RELA
##    lhs op  rhs
## 1 REL1 ~~ REL2
## 2 REL1 ~~ REL3
## 3 REL1 ~~ REL4
## 4 REL2 ~~ REL4
## 5 REL3 ~~ REL4
## 
## $EDUC
##     lhs op  rhs
## 1  EDU1 ~~ EDU2
## 2  EDU2 ~~ EDU3
## 3  EDU2 ~~ EDU5
## 4  EDU2 ~~ EDU6
## 5  EDU2 ~~ EDU7
## 6  EDU2 ~~ EDU8
## 7  EDU3 ~~ EDU4
## 8  EDU3 ~~ EDU7
## 9  EDU3 ~~ EDU8
## 10 EDU5 ~~ EDU6
## 11 EDU6 ~~ EDU7
## 12 EDU7 ~~ EDU8
## 
## $GOVE
##    lhs op  rhs
## 1 GOV1 ~~ GOV2
## 2 GOV1 ~~ GOV4
## 3 GOV1 ~~ GOV5
## 4 GOV2 ~~ GOV5
## 5 GOV4 ~~ GOV5
## 
## $ENDO
##    lhs op  rhs
## 1 END1 ~~ END5
## 2 END2 ~~ END3
## 3 END2 ~~ END4
## 4 END4 ~~ END5

Các cặp items cần nối sẽ được đưa vào model CFA với mục # Covariance, tức sử dụng ~~.

  1. Áp dụng hàm funCFA_mi() cho model cfa.model3 đã có điều chỉnh
cfa.model3 <- ' 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  
#  Covariance
BI2 ~~ BI3
REL4  ~~ REL1 + REL3
EDU2 ~~ EDU1 + EDU3 + EDU6
EDU5 ~~ EDU6
EDU7 ~~ EDU8
GOV4 ~~ GOV5
END5 ~~ END1 + END4 ' 
cfa.d3 <- cfa(cfa.model3, data = d1)
mi_d3 <- funCFA_mi (cfa.d3, 15 )
mi_d3 
## $BEINTEN
## [1] lhs op  rhs
## <0 rows> (or 0-length row.names)
## 
## $RELA
##    lhs op  rhs
## 1 REL1 ~~ REL3
## 
## $EDUC
##    lhs op  rhs
## 1 EDU1 ~~ EDU3
## 2 EDU3 ~~ EDU4
## 
## $GOVE
##    lhs op  rhs
## 1 GOV1 ~~ GOV2
## 
## $ENDO
##    lhs op  rhs
## 1 END2 ~~ END4
## 2 END3 ~~ END4
  1. Áp dụng hàm funCFA_mi() cho model cfa.model4b đã có điều chỉnh
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)
mi_d4a <- funCFA_mi (cfa.d4a, 15 )
mi_d4a
## $BEINTEN
## [1] lhs op  rhs
## <0 rows> (or 0-length row.names)
## 
## $RELA
##    lhs op  rhs
## 1 REL1 ~~ REL3
## 
## $EDUC
##    lhs op  rhs
## 1 EDU1 ~~ EDU3
## 2 EDU3 ~~ EDU4
## 
## $GOVE
##    lhs op  rhs
## 1 GOV1 ~~ GOV2
## 
## $ENDO
## [1] lhs op  rhs
## <0 rows> (or 0-length row.names)

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