Trong R, phân tích nhân tố khám phá (EFA) làm bằng gói psych, còn phân tích nhân tố khẳng định (CFA) và mô hình cấu trúc (SEM) làm bằng lavaan. Cú pháp mô hình lavaan dùng vài toán tử như =~, ~, ~~, đọc gần giống cách vẽ sơ đồ trong AMOS.
Ví dụ dưới đây dùng bộ dữ liệu HolzingerSwineford1939 đi kèm lavaan: 301 học sinh làm 9 bài trắc nghiệm năng lực, thường được dùng minh hoạ ba nhân tố thị giác, ngôn ngữ và tốc độ. Mọi con số trong bài là kết quả chạy thật trên bộ dữ liệu này với psych 2.6 và lavaan 0.7, để bạn chạy lại và so.
EFA bằng psych: từ kiểm tra dữ liệu tới ma trận tải
Dữ liệu có hợp để phân tích nhân tố không
psych::KMO(d) cho chỉ số KMO tổng và từng biến; trên bộ ví dụ, KMO tổng khoảng 0,75. psych::cortest.bartlett(cor(d), n = nrow(d)) kiểm ma trận tương quan có khác ma trận đơn vị không. Hai kiểm tra này chỉ nói dữ liệu có đáng phân tích hay không, không nói có bao nhiêu nhân tố.
Chọn số nhân tố
psych::fa.parallel(d, fm = 'ml', fa = 'fa') so trị riêng của dữ liệu thật với dữ liệu ngẫu nhiên cùng kích thước. Trên bộ ví dụ, hàm gợi ý 3 nhân tố, khớp với lý thuyết. Kết hợp với hình scree và ý nghĩa nội dung; đừng dùng riêng quy tắc trị riêng lớn hơn 1.
Trích và xoay
e <- psych::fa(d, nfactors = 3, rotate = 'oblimin', fm = 'ml'). Xoay xiên oblimin cho phép các nhân tố tương quan, thường hợp với khái niệm tâm lý và xã hội hơn xoay vuông góc varimax; xoay xiên cần gói GPArotation. In tải gọn bằng print(e$loadings, cutoff = 0.3). Trên bộ ví dụ, x9 tải chéo lên hai nhân tố (khoảng 0,37 và 0,46), một chi tiết sẽ gặp lại ở CFA.
Độ tin cậy: alpha và omega
psych::alpha(d[, c('x1', 'x2', 'x3')]) cho Cronbach alpha của một thang đo, kèm alpha nếu bỏ từng câu. Alpha giả định mọi câu có tải bằng nhau lên nhân tố, điều ít khi đúng. psych::omega(d, nfactors = 3) cho hệ số omega, được nhiều tạp chí tâm lý học khuyến khích báo cáo cùng hoặc thay alpha.
Nếu thang có câu nghịch, đảo mã trước khi tính. Hàm alpha() có tham số check.keys = TRUE tự phát hiện câu tương quan âm với tổng, nhưng nên đảo mã có chủ đích trong khâu làm sạch thay vì để hàm tự đoán.
Với câu Likert chỉ có bốn hoặc năm mức, tương quan Pearson giữa các câu bị kéo thấp. psych::fa() có tham số cor = 'poly' để dùng tương quan đa chuỗi (polychoric), thường hợp hơn cho dữ liệu thứ bậc; psych::polychoric() trả ma trận này nếu bạn muốn xem riêng. Ghi rõ trong bài là EFA dựa trên ma trận tương quan nào.
Cú pháp mô hình lavaan
Một mô hình lavaan là một chuỗi chữ, mỗi dòng một quan hệ:
| Toán tử | Nghĩa | Ví dụ |
|---|---|---|
=~ | Biến tiềm ẩn được đo bởi các biến quan sát | thi_giac =~ x1 + x2 + x3 |
~ | Hồi quy: vế trái phụ thuộc vế phải | toc_do ~ thi_giac + van_ban |
~~ | Hiệp phương sai hoặc phương sai | x7 ~~ x8 |
* | Gắn nhãn hoặc cố định tham số | van_ban ~ a*thi_giac |
:= | Định nghĩa tham số mới từ nhãn | gian_tiep := a*b |
Mặc định, cfa() và sem() cố định tải của biến quan sát đầu tiên bằng 1 để đặt thang cho biến tiềm ẩn, và cho các biến tiềm ẩn ngoại sinh tương quan với nhau.
CFA và SEM: chạy và đọc kết quả
Chạy CFA
mo <- 'thi_giac =~ x1 + x2 + x3 \n van_ban =~ x4 + x5 + x6 \n toc_do =~ x7 + x8 + x9' rồi f <- lavaan::cfa(mo, data = HolzingerSwineford1939, estimator = 'MLR'). Ước lượng MLR cho sai số chuẩn và chỉ số phù hợp bền với dữ liệu lệch chuẩn. Với câu Likert ít mức, khai ordered = TRUE hoặc liệt kê tên biến thứ bậc, lavaan chuyển sang WLSMV.
Đọc chỉ số phù hợp
summary(f, fit.measures = TRUE, standardized = TRUE) in tất cả. Lấy riêng: fitMeasures(f, c('cfi.robust', 'tli.robust', 'rmsea.robust', 'srmr')). Trên bộ ví dụ ra CFI bền khoảng 0,93, TLI 0,90, RMSEA bền 0,092, SRMR 0,065: mô hình ba nhân tố chưa thật khớp. Ngưỡng hay được trích là đề xuất của Hu và Bentler (1999), nhưng chính các tác giả và nhiều nghiên cứu sau lưu ý đó không phải luật cứng.
Chỉ số điều chỉnh
modindices(f, sort. = TRUE) liệt kê tham số nếu được giải phóng sẽ giảm chi bình phương bao nhiêu. Đứng đầu trên bộ ví dụ là tải thi_giac =~ x9 và hiệp phương sai x7 ~~ x8, đúng chỗ EFA đã báo tải chéo. Chỉ thêm khi có lý do nội dung, và ghi rõ trong bài là mô hình đã được điều chỉnh sau khi xem dữ liệu.
Từ CFA sang SEM
Thêm các dòng hồi quy giữa biến tiềm ẩn rồi gọi sem(). Tác động gián tiếp: gắn nhãn a, b cho hai đường rồi định nghĩa gian_tiep := a*b; chạy với se = 'bootstrap' để có khoảng tin cậy bootstrap.
So sánh giữa các nhóm: kiểm bất biến đo lường
Trước khi so điểm trung bình một thang đo giữa nam và nữ, giữa hai trường hay hai đợt khảo sát, cần biết thang đo có đo cùng một thứ ở các nhóm không. lavaan làm việc này bằng CFA đa nhóm: f1 <- cfa(mo, data = d, group = 'truong') cho phép mọi tham số khác nhau giữa nhóm, rồi f2 <- cfa(mo, data = d, group = 'truong', group.equal = 'loadings') ràng buộc tải bằng nhau. lavTestLRT(f1, f2) so hai mô hình.
Trên bộ ví dụ, chia theo cột school có sẵn, mô hình ràng buộc tải không kém mô hình tự do một cách có ý nghĩa (chênh chi bình phương khoảng 8,2 với 6 bậc tự do, p khoảng 0,22), nghĩa là có thể chấp nhận bất biến tải giữa hai trường. Bước tiếp theo thêm 'intercepts' vào group.equal; chỉ khi bất biến hệ số chặn được chấp nhận thì so trung bình biến tiềm ẩn mới có cơ sở.
Ngoài kiểm định chi bình phương, nhiều tác giả nhìn mức giảm CFI giữa hai mô hình liên tiếp. Ghi rõ tiêu chí đã chọn trước khi xem kết quả.
Báo cáo EFA, CFA, SEM cần đủ những gì?
Người phản biện hay hỏi lại những điểm sau, nên đưa sẵn vào bản thảo:
- Cỡ mẫu sau khi loại phiếu, cách xử lý giá trị thiếu, có chia mẫu cho EFA và CFA hay không.
- Với EFA: phương pháp trích, phép xoay, tiêu chí chọn số nhân tố, bảng tải đầy đủ (không chỉ tải lớn), tương quan giữa các nhân tố khi xoay xiên.
- Với CFA và SEM: ước lượng đã dùng, chi bình phương, bậc tự do, CFI, TLI, RMSEA kèm khoảng tin cậy, SRMR; tải chuẩn hoá của từng biến quan sát; độ tin cậy từng thang.
- Mọi điều chỉnh sau khi xem chỉ số điều chỉnh, kèm lý do nội dung.
- Mã lavaan đầy đủ trong tài liệu bổ sung, để người khác chạy lại.
Đối chiếu với phần mềm thương mại
Người chuyển từ AMOS hay SmartPLS sang hay hỏi kết quả có khớp không:
| Phần mềm | Họ phương pháp | Khác biệt cần biết |
|---|---|---|
| AMOS | SEM dựa trên hiệp phương sai, vẽ sơ đồ | Cùng họ với lavaan; cùng mô hình, cùng dữ liệu, ước lượng ML thì hệ số thường khớp; khác nhau ở mặc định xử lý dữ liệu thiếu và cách tính một số chỉ số |
| Mplus | SEM hiệp phương sai, mạnh với biến thứ bậc | lavaan có tham số mimic = 'Mplus' để gần với cách tính của Mplus |
| SmartPLS | PLS-SEM, dựa trên phương sai | Mục tiêu và chỉ số khác hẳn; không nên so trực tiếp hệ số với lavaan |
| SPSS | EFA trong menu Dimension Reduction | Mặc định trích thành phần chính và xoay varimax; khai rõ trong bài nếu dùng |
Khi báo cáo, ghi tên gói và phiên bản (lấy từ packageVersion('lavaan')), phương pháp ước lượng, cách xử lý giá trị thiếu, các chỉ số phù hợp kèm tên bản bền nếu dùng, và mọi điều chỉnh mô hình đã làm.
Câu hỏi thường gặp
Có nên làm EFA và CFA trên cùng một mẫu không?
Tốt nhất là không. Nếu cỡ mẫu đủ lớn, chia ngẫu nhiên làm hai nửa, EFA trên nửa đầu và CFA trên nửa sau. Làm cả hai trên cùng mẫu thì CFA dễ khớp vì mô hình đã được chọn theo dữ liệu đó.
lavaan xử lý giá trị thiếu thế nào?
Mặc định loại các dòng có thiếu. Với ước lượng ML hoặc MLR, khai missing = 'fiml' để dùng mọi thông tin có sẵn. Ghi cách xử lý vào phần phương pháp.
Cần cỡ mẫu bao nhiêu cho SEM?
Không có con số chung. Cỡ mẫu cần thiết phụ thuộc số tham số, độ lớn tải và độ phức tạp mô hình. Có thể ước lượng bằng mô phỏng, ví dụ dùng chính lavaan để sinh dữ liệu từ mô hình giả định.
Vẽ sơ đồ đường dẫn từ lavaan bằng gì?
Gói semPlot với hàm semPaths vẽ nhanh từ đối tượng lavaan. Với hình nộp tạp chí, nhiều người vẽ lại bằng phần mềm vẽ để chỉnh bố cục cho gọn.
Kết quả lavaan khác AMOS một chút thì có sao không?
Chênh nhỏ ở chữ số thập phân thường do mặc định khác nhau, như cách tính phương sai mẫu hay xử lý thiếu. Kiểm lại hai bên dùng cùng ước lượng, cùng dữ liệu và cùng ràng buộc.
Có cần báo cáo cả chi bình phương khi mẫu lớn không?
Nên báo cáo chi bình phương, bậc tự do và p cùng các chỉ số khác, dù với mẫu lớn kiểm định này gần như luôn có ý nghĩa. Người đọc cần các con số này để tự đánh giá.