1 1. Báo cáo này dùng để làm gì?

File này không chỉ in lại output từ SEMinR. Mục tiêu là giúp đọc kết quả theo đúng trình tự của một phân tích PLS-SEM.

Trình tự được dùng trong báo cáo:

  1. Kiểm tra dữ liệu.
  2. Đánh giá measurement model.
  3. Đánh giá structural model.
  4. Kiểm định H1–H15.
  5. Kiểm định mediation H16–H20.
  6. Đánh giá khả năng dự báo bằng PLSpredict và CVPAT.
  7. Tổng hợp cách viết kết quả vào luận văn.

Nguyên tắc quan trọng: chưa nên diễn giải các structural paths nếu measurement model chưa được chứng minh là đạt yêu cầu.


2 2. Cấu trúc mô hình nghiên cứu

Mô hình gồm 7 constructs phản xạ:

Construct Nội dung Indicators
SQ AI System Quality SQ1–SQ5
PP Perceived Personalization PP1–PP5
TR AI Transparency TR1–TR3
PU Perceived Usefulness PU1–PU4
PEOU Perceived Ease of Use PEOU1–PEOU4
BT Brand Trust BT1–BT4
PI Purchase Intention PI1–PI3

Phân tích structural model gồm:

  • 15 direct hypotheses H1–H15;
  • 5 mediation hypotheses H16–H20 thông qua Brand Trust.

3 3. Bước 1 – Kiểm tra chất lượng dữ liệu

3.1 3.1 Tại sao phải kiểm tra?

Trước khi chạy PLS-SEM cần xác nhận:

  • không có respondent ID bị duplicate;
  • không có missing scale item chưa xử lý;
  • câu trả lời Likert vẫn nằm trong khoảng hợp lệ;
  • data chạy PLS khớp với file SPSS final.

Điều này bảo đảm rằng phần descriptive và phần PLS-SEM không vô tình sử dụng hai bộ dữ liệu khác nhau.

3.2 3.2 Data quality của file PLS

show_table(
  data_quality,
  caption = "Kiểm tra chất lượng dữ liệu PLS"
)
Kiểm tra chất lượng dữ liệu PLS
Metric Value
Rows 534
Columns 29
Duplicate IDs 0
Missing cells in scale items 0
Cases with >=1 missing scale item 0
Out-of-range Likert responses 0

3.3 3.3 Đối chiếu SPSS và PLS

show_table(
  tieout,
  caption = "Đối chiếu file SPSS final và file PLS"
)
Đối chiếu file SPSS final và file PLS
Metric Value
SPSS unique IDs 534
PLS unique IDs 534
Common IDs 534
PLS IDs missing from SPSS 0
SPSS IDs missing from PLS 0
Scale-item mismatches 0

3.4 3.4 Cách kết luận

Có thể tiếp tục sang measurement model nếu:

  • duplicate ID = 0;
  • missing scale values = 0;
  • out-of-range = 0;
  • không có mismatch bất thường giữa SPSS và PLS.

4 4. Bước 2 – Outer loadings và indicator reliability

4.1 4.1 Outer loading là gì?

Với reflective measurement model, outer loading cho biết một indicator phản ánh construct của nó mạnh đến mức nào.

Ngưỡng tham khảo thường dùng:

  • Loading ≥ 0.708: đạt tốt;
  • 0.400–0.707: chưa được tự động xóa; phải xem thêm CR, AVE và content validity;
  • < 0.400: cần xem xét nghiêm túc.

Bình phương loading chính là indicator reliability.

Ví dụ:

\[ 0.708^2 \approx 0.50 \]

nghĩa là construct giải thích khoảng 50% phương sai của indicator đó.

4.2 4.2 Kết quả outer loadings

loading_report <- outer_loadings

if ("Loading" %in% names(loading_report)) {
  loading_report <- loading_report |>
    mutate(
      Loading_Decision = interpret_loading(abs(Loading))
    )
}

show_table(
  loading_report,
  caption = "Outer loadings và indicator reliability"
)
Outer loadings và indicator reliability
Indicator Construct Loading Indicator_Reliability Loading_Assessment Indicator_Reliability_Assessment Loading_Decision
SQ1 SQ 0.826 0.682 Recommended (>= 0.708) >= 0.50 Đạt
SQ2 SQ 0.768 0.590 Recommended (>= 0.708) >= 0.50 Đạt
SQ3 SQ 0.771 0.595 Recommended (>= 0.708) >= 0.50 Đạt
SQ4 SQ 0.832 0.693 Recommended (>= 0.708) >= 0.50 Đạt
SQ5 SQ 0.807 0.651 Recommended (>= 0.708) >= 0.50 Đạt
PP1 PP 0.820 0.672 Recommended (>= 0.708) >= 0.50 Đạt
PP2 PP 0.815 0.664 Recommended (>= 0.708) >= 0.50 Đạt
PP3 PP 0.803 0.645 Recommended (>= 0.708) >= 0.50 Đạt
PP4 PP 0.753 0.567 Recommended (>= 0.708) >= 0.50 Đạt
PP5 PP 0.802 0.643 Recommended (>= 0.708) >= 0.50 Đạt
TR1 TR 0.854 0.730 Recommended (>= 0.708) >= 0.50 Đạt
TR2 TR 0.861 0.742 Recommended (>= 0.708) >= 0.50 Đạt
TR3 TR 0.804 0.646 Recommended (>= 0.708) >= 0.50 Đạt
PEOU1 PEOU 0.844 0.713 Recommended (>= 0.708) >= 0.50 Đạt
PEOU2 PEOU 0.807 0.652 Recommended (>= 0.708) >= 0.50 Đạt
PEOU3 PEOU 0.860 0.740 Recommended (>= 0.708) >= 0.50 Đạt
PEOU4 PEOU 0.795 0.632 Recommended (>= 0.708) >= 0.50 Đạt
PU1 PU 0.844 0.713 Recommended (>= 0.708) >= 0.50 Đạt
PU2 PU 0.816 0.666 Recommended (>= 0.708) >= 0.50 Đạt
PU3 PU 0.862 0.743 Recommended (>= 0.708) >= 0.50 Đạt
PU4 PU 0.858 0.737 Recommended (>= 0.708) >= 0.50 Đạt
BT1 BT 0.833 0.694 Recommended (>= 0.708) >= 0.50 Đạt
BT2 BT 0.852 0.726 Recommended (>= 0.708) >= 0.50 Đạt
BT3 BT 0.839 0.705 Recommended (>= 0.708) >= 0.50 Đạt
BT4 BT 0.847 0.717 Recommended (>= 0.708) >= 0.50 Đạt
PI1 PI 0.849 0.721 Recommended (>= 0.708) >= 0.50 Đạt
PI2 PI 0.866 0.751 Recommended (>= 0.708) >= 0.50 Đạt
PI3 PI 0.836 0.698 Recommended (>= 0.708) >= 0.50 Đạt

4.3 4.3 Biểu đồ outer loadings

if (all(c("Indicator", "Construct", "Loading") %in% names(outer_loadings))) {

  ggplot(
    outer_loadings,
    aes(
      x = reorder(Indicator, Loading),
      y = Loading
    )
  ) +
    geom_col() +
    geom_hline(
      yintercept = 0.708,
      linetype = "dashed"
    ) +
    facet_wrap(
      ~ Construct,
      scales = "free_x"
    ) +
    coord_flip() +
    labs(
      title = "Outer Loadings theo từng Construct",
      subtitle = "Đường đứt = ngưỡng tham khảo 0.708",
      x = NULL,
      y = "Outer loading"
    ) +
    theme_minimal(base_size = 11)
}

4.4 4.4 R tự diễn giải kết quả

if ("Loading" %in% names(outer_loadings) && nrow(outer_loadings) > 0) {

  min_loading <- min(abs(outer_loadings$Loading), na.rm = TRUE)
  max_loading <- max(abs(outer_loadings$Loading), na.rm = TRUE)
  n_ge_708 <- sum(abs(outer_loadings$Loading) >= 0.708, na.rm = TRUE)
  n_indicators <- sum(!is.na(outer_loadings$Loading))

  cat(
    sprintf(
      "Mô hình có **%d indicators**. Outer loadings nằm trong khoảng **%.3f–%.3f**. ",
      n_indicators,
      min_loading,
      max_loading
    )
  )

  cat(
    sprintf(
      "Có **%d/%d indicators đạt loading ≥ 0.708**. ",
      n_ge_708,
      n_indicators
    )
  )

  if (n_ge_708 == n_indicators) {
    cat(
      "Do đó, indicator reliability đạt yêu cầu và không có lý do thống kê để loại item chỉ dựa trên outer loading.\n"
    )
  } else {
    cat(
      "Những item dưới 0.708 phải được đánh giá cùng CR, AVE và nội dung thang đo trước khi quyết định giữ hay loại.\n"
    )
  }
}

Mô hình có 28 indicators. Outer loadings nằm trong khoảng 0.753–0.866. Có 28/28 indicators đạt loading ≥ 0.708. Do đó, indicator reliability đạt yêu cầu và không có lý do thống kê để loại item chỉ dựa trên outer loading.


5 5. Bước 3 – Internal consistency reliability và convergent validity

5.1 5.1 Reliability cần xem những gì?

Ba chỉ số được dùng:

  • Cronbach’s alpha (α);
  • rho_A;
  • Composite Reliability (rho_C / CR).

Ngưỡng tham khảo:

  • ≥ 0.70: thường được xem là đạt;
  • CR quá cao, đặc biệt khoảng > 0.95, có thể gợi ý item bị redundant.

5.2 5.2 AVE dùng để làm gì?

Average Variance Extracted (AVE) đo convergent validity.

  • AVE ≥ 0.50: construct giải thích ít nhất 50% phương sai của indicators trung bình.

5.3 5.3 Kết quả

show_table(
  reliability_ave,
  caption = "Reliability và convergent validity"
)
Reliability và convergent validity
Construct alpha rhoA rhoC AVE Alpha_OK rhoA_OK rhoC_OK AVE_OK Overall_Assessment
SQ 0.860 0.865 0.900 0.642 TRUE TRUE TRUE TRUE Pass
PP 0.858 0.863 0.898 0.638 TRUE TRUE TRUE TRUE Pass
TR 0.793 0.806 0.878 0.706 TRUE TRUE TRUE TRUE Pass
PEOU 0.846 0.849 0.896 0.684 TRUE TRUE TRUE TRUE Pass
PU 0.867 0.868 0.909 0.715 TRUE TRUE TRUE TRUE Pass
BT 0.864 0.865 0.908 0.711 TRUE TRUE TRUE TRUE Pass
PI 0.809 0.814 0.887 0.724 TRUE TRUE TRUE TRUE Pass

5.4 5.4 R tự tóm tắt

if (nrow(reliability_ave) > 0) {

  if ("alpha" %in% names(reliability_ave)) {
    cat(
      sprintf(
        "- Cronbach's alpha: **%.3f–%.3f**.\n",
        min(reliability_ave$alpha, na.rm = TRUE),
        max(reliability_ave$alpha, na.rm = TRUE)
      )
    )
  }

  if ("rhoA" %in% names(reliability_ave)) {
    cat(
      sprintf(
        "- rho_A: **%.3f–%.3f**.\n",
        min(reliability_ave$rhoA, na.rm = TRUE),
        max(reliability_ave$rhoA, na.rm = TRUE)
      )
    )
  }

  if ("rhoC" %in% names(reliability_ave)) {
    cat(
      sprintf(
        "- Composite Reliability: **%.3f–%.3f**.\n",
        min(reliability_ave$rhoC, na.rm = TRUE),
        max(reliability_ave$rhoC, na.rm = TRUE)
      )
    )
  }

  if ("AVE" %in% names(reliability_ave)) {
    cat(
      sprintf(
        "- AVE: **%.3f–%.3f**.\n",
        min(reliability_ave$AVE, na.rm = TRUE),
        max(reliability_ave$AVE, na.rm = TRUE)
      )
    )
  }

  if (all(c("alpha", "rhoA", "rhoC", "AVE") %in% names(reliability_ave))) {

    all_pass <- all(
      reliability_ave$alpha >= 0.70 &
        reliability_ave$rhoA >= 0.70 &
        reliability_ave$rhoC >= 0.70 &
        reliability_ave$rhoC <= 0.95 &
        reliability_ave$AVE >= 0.50,
      na.rm = TRUE
    )

    if (all_pass) {
      cat(
        "\n**Kết luận:** toàn bộ constructs đạt internal consistency reliability và convergent validity theo các tiêu chuẩn được sử dụng.\n"
      )
    } else {
      cat(
        "\n**Kết luận:** có ít nhất một construct cần kiểm tra kỹ hơn trước khi chuyển sang structural model.\n"
      )
    }
  }
}
  • Cronbach’s alpha: 0.793–0.867.
  • rho_A: 0.806–0.868.
  • Composite Reliability: 0.878–0.909.
  • AVE: 0.638–0.724.

Kết luận: toàn bộ constructs đạt internal consistency reliability và convergent validity theo các tiêu chuẩn được sử dụng.


6 6. Bước 4 – Discriminant validity

Discriminant validity trả lời câu hỏi:

Các construct có thực sự khác nhau về mặt thực nghiệm hay chúng đang đo gần như cùng một khái niệm?

Trong báo cáo này, HTMT được ưu tiên. Fornell–Larcker và cross-loadings được dùng bổ sung.


6.1 6.1 HTMT

Ngưỡng tham khảo:

  • HTMT < 0.85: tiêu chuẩn bảo thủ;
  • HTMT < 0.90: tiêu chuẩn ít bảo thủ hơn.
show_table(
  htmt_long,
  caption = "HTMT"
)
HTMT
Construct_1 Construct_2 HTMT Pair_Key HTMT_085 HTMT_090
PP SQ 0.327 PP | SQ Pass Pass
TR SQ 0.222 SQ | TR Pass Pass
PEOU SQ 0.390 PEOU | SQ Pass Pass
PU SQ 0.441 PU | SQ Pass Pass
BT SQ 0.479 BT | SQ Pass Pass
PI SQ 0.318 PI | SQ Pass Pass
TR PP 0.245 PP | TR Pass Pass
PEOU PP 0.374 PEOU | PP Pass Pass
PU PP 0.414 PP | PU Pass Pass
BT PP 0.429 BT | PP Pass Pass
PI PP 0.233 PI | PP Pass Pass
PEOU TR 0.378 PEOU | TR Pass Pass
PU TR 0.383 PU | TR Pass Pass
BT TR 0.383 BT | TR Pass Pass
PI TR 0.267 PI | TR Pass Pass
PU PEOU 0.559 PEOU | PU Pass Pass
BT PEOU 0.494 BT | PEOU Pass Pass
PI PEOU 0.473 PEOU | PI Pass Pass
BT PU 0.525 BT | PU Pass Pass
PI PU 0.464 PI | PU Pass Pass
PI BT 0.575 BT | PI Pass Pass
if ("HTMT" %in% names(htmt_long) && nrow(htmt_long) > 0) {

  max_htmt <- max(htmt_long$HTMT, na.rm = TRUE)

  max_pair <- htmt_long |>
    filter(HTMT == max(HTMT, na.rm = TRUE)) |>
    slice(1)

  cat(
    sprintf(
      "HTMT lớn nhất = **%.3f**",
      max_htmt
    )
  )

  if (all(c("Construct_1", "Construct_2") %in% names(max_pair))) {
    cat(
      sprintf(
        ", giữa **%s và %s**",
        max_pair$Construct_1,
        max_pair$Construct_2
      )
    )
  }

  cat(". ")

  if (max_htmt < 0.85) {
    cat(
      "Giá trị này thấp hơn 0.85, vì vậy discriminant validity được hỗ trợ rõ ràng.\n"
    )
  } else if (max_htmt < 0.90) {
    cat(
      "Giá trị nằm giữa 0.85 và 0.90; cần diễn giải cùng mức độ tương đồng lý thuyết của hai constructs.\n"
    )
  } else {
    cat(
      "Giá trị này cần được xem xét kỹ vì có thể tồn tại vấn đề discriminant validity.\n"
    )
  }
}

HTMT lớn nhất = 0.575, giữa PI và BT. Giá trị này thấp hơn 0.85, vì vậy discriminant validity được hỗ trợ rõ ràng.

6.2 6.2 Heatmap HTMT

if (all(c("Construct_1", "Construct_2", "HTMT") %in% names(htmt_long))) {

  ggplot(
    htmt_long,
    aes(
      x = Construct_1,
      y = Construct_2,
      fill = HTMT
    )
  ) +
    geom_tile() +
    geom_text(
      aes(label = sprintf("%.3f", HTMT)),
      size = 3
    ) +
    labs(
      title = "HTMT Heatmap",
      x = NULL,
      y = NULL,
      fill = "HTMT"
    ) +
    theme_minimal(base_size = 11) +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1)
    )
}


6.3 6.3 Bootstrapped HTMT

show_table(
  htmt_boot,
  caption = "Bootstrapped HTMT confidence intervals"
)
Bootstrapped HTMT confidence intervals
Construct_Pair Original_Est Bootstrap_Mean Bootstrap_SD T_Stat CI_Lower CI_Upper Bootstrap_P HTMT_CI_below_0_85 HTMT_CI_below_0_90
SQ -> PP 0.327 0.326 0.044 15.150 0.251 0.398 0 TRUE TRUE
SQ -> TR 0.222 0.222 0.051 15.152 0.137 0.307 0 TRUE TRUE
SQ -> PEOU 0.390 0.390 0.046 13.283 0.313 0.465 0 TRUE TRUE
SQ -> PU 0.441 0.440 0.043 12.937 0.366 0.509 0 TRUE TRUE
SQ -> BT 0.479 0.478 0.041 12.719 0.411 0.546 0 TRUE TRUE
SQ -> PI 0.318 0.318 0.046 14.825 0.242 0.393 0 TRUE TRUE
PP -> TR 0.245 0.247 0.049 15.520 0.169 0.328 0 TRUE TRUE
PP -> PEOU 0.374 0.374 0.045 14.030 0.298 0.445 0 TRUE TRUE
PP -> PU 0.414 0.414 0.041 14.282 0.346 0.480 0 TRUE TRUE
PP -> BT 0.429 0.429 0.040 14.295 0.363 0.494 0 TRUE TRUE
PP -> PI 0.233 0.234 0.047 16.208 0.156 0.312 0 TRUE TRUE
TR -> PEOU 0.378 0.378 0.045 13.972 0.303 0.450 0 TRUE TRUE
TR -> PU 0.383 0.383 0.048 12.842 0.301 0.460 0 TRUE TRUE
TR -> BT 0.383 0.382 0.047 13.165 0.304 0.458 0 TRUE TRUE
TR -> PI 0.267 0.267 0.051 14.332 0.183 0.352 0 TRUE TRUE
PEOU -> PU 0.559 0.558 0.037 11.892 0.496 0.617 0 TRUE TRUE
PEOU -> BT 0.494 0.494 0.041 12.277 0.425 0.560 0 TRUE TRUE
PEOU -> PI 0.473 0.473 0.044 12.028 0.400 0.545 0 TRUE TRUE
PU -> BT 0.525 0.524 0.041 11.438 0.454 0.591 0 TRUE TRUE
PU -> PI 0.464 0.463 0.043 12.574 0.393 0.533 0 TRUE TRUE
BT -> PI 0.575 0.575 0.038 11.274 0.510 0.635 0 TRUE TRUE

Điểm cần nhớ:

  • HTMT 0.85/0.90 là descriptive guideline;
  • với inferential HTMT, điều quan trọng là confidence interval có tiến đến hoặc chứa 1.00 hay không.

Không nên nhầm hai loại tiêu chuẩn này.


6.4 6.4 Fornell–Larcker

show_table(
  fornell_larcker,
  caption = "Fornell–Larcker criterion"
)
Fornell–Larcker criterion
Row SQ PP TR PEOU PU BT PI
SQ 0.801 NA NA NA NA NA NA
PP 0.281 0.799 NA NA NA NA NA
TR 0.185 0.211 0.840 NA NA NA NA
PEOU 0.336 0.321 0.311 0.827 NA NA NA
PU 0.382 0.359 0.323 0.478 0.845 NA NA
BT 0.415 0.374 0.320 0.426 0.455 0.843 NA
PI 0.267 0.201 0.217 0.393 0.391 0.482 0.851

Logic:

  • căn bậc hai của AVE của một construct nên lớn hơn correlations giữa construct đó với các constructs khác.

Đây là diagnostic bổ sung. Khi HTMT đã được báo cáo, không nên chỉ dựa vào Fornell–Larcker để kết luận discriminant validity.


6.5 6.5 Cross-loadings

show_table(
  cross_loadings,
  caption = "Cross-loadings"
)
Cross-loadings
Row SQ PP TR PEOU PU BT PI
SQ1 0.826 0.229 0.174 0.312 0.341 0.359 0.218
SQ2 0.768 0.210 0.132 0.230 0.273 0.304 0.201
SQ3 0.771 0.244 0.158 0.220 0.304 0.324 0.235
SQ4 0.832 0.252 0.130 0.283 0.324 0.326 0.198
SQ5 0.807 0.190 0.146 0.293 0.284 0.346 0.217
PP1 0.254 0.820 0.127 0.278 0.302 0.296 0.167
PP2 0.216 0.815 0.181 0.253 0.303 0.316 0.184
PP3 0.208 0.803 0.203 0.271 0.299 0.309 0.215
PP4 0.213 0.753 0.113 0.219 0.240 0.226 0.080
PP5 0.229 0.802 0.209 0.255 0.284 0.335 0.140
TR1 0.148 0.185 0.854 0.291 0.272 0.291 0.184
TR2 0.181 0.227 0.861 0.250 0.329 0.283 0.212
TR3 0.135 0.105 0.804 0.241 0.199 0.227 0.145
PU1 0.322 0.332 0.284 0.420 0.844 0.357 0.290
PU2 0.307 0.272 0.258 0.383 0.816 0.382 0.309
PU3 0.303 0.331 0.282 0.419 0.862 0.385 0.367
PU4 0.359 0.281 0.270 0.396 0.858 0.414 0.354
PEOU1 0.305 0.217 0.219 0.844 0.402 0.338 0.316
PEOU2 0.278 0.274 0.250 0.807 0.385 0.346 0.318
PEOU3 0.303 0.295 0.277 0.860 0.395 0.430 0.349
PEOU4 0.224 0.271 0.282 0.795 0.402 0.285 0.317
BT1 0.292 0.294 0.254 0.358 0.367 0.833 0.405
BT2 0.393 0.355 0.270 0.367 0.386 0.852 0.428
BT3 0.380 0.294 0.278 0.351 0.395 0.839 0.394
BT4 0.329 0.315 0.277 0.359 0.386 0.847 0.398
PI1 0.195 0.162 0.214 0.310 0.349 0.403 0.849
PI2 0.264 0.214 0.181 0.368 0.361 0.438 0.866
PI3 0.218 0.130 0.159 0.324 0.285 0.386 0.836

Một indicator nên có loading lớn nhất trên chính construct mà nó được thiết kế để đo.


7 7. Bước 5 – Structural VIF

7.1 7.1 Tại sao cần VIF?

Trước khi đọc path coefficients, cần xác nhận rằng các predictor constructs không bị collinearity quá cao.

Ngưỡng tham khảo:

  • VIF < 3: tốt theo tiêu chuẩn bảo thủ;
  • 3–5: cần xem xét;
  • ≥ 5: có khả năng problematic collinearity.

7.2 7.2 Kết quả

show_table(
  structural_vif,
  caption = "Structural VIF"
)
Structural VIF
Outcome Predictor VIF VIF_Assessment
PU SQ 1.177 < 3 (conservative criterion met)
PU PP 1.172 < 3 (conservative criterion met)
PU TR 1.130 < 3 (conservative criterion met)
PU PEOU 1.275 < 3 (conservative criterion met)
PEOU SQ 1.105 < 3 (conservative criterion met)
PEOU PP 1.117 < 3 (conservative criterion met)
PEOU TR 1.066 < 3 (conservative criterion met)
BT SQ 1.239 < 3 (conservative criterion met)
BT PP 1.216 < 3 (conservative criterion met)
BT TR 1.165 < 3 (conservative criterion met)
BT PU 1.505 < 3 (conservative criterion met)
BT PEOU 1.417 < 3 (conservative criterion met)
PI PU 1.441 < 3 (conservative criterion met)
PI PEOU 1.395 < 3 (conservative criterion met)
PI BT 1.358 < 3 (conservative criterion met)
if ("VIF" %in% names(structural_vif) && nrow(structural_vif) > 0) {

  min_vif <- min(structural_vif$VIF, na.rm = TRUE)
  max_vif <- max(structural_vif$VIF, na.rm = TRUE)

  cat(
    sprintf(
      "Structural VIF nằm trong khoảng **%.3f–%.3f**. ",
      min_vif,
      max_vif
    )
  )

  if (max_vif < 3) {
    cat(
      "Toàn bộ VIF < 3, do đó không có dấu hiệu structural collinearity đáng kể.\n"
    )
  } else if (max_vif < 5) {
    cat(
      "Có VIF lớn hơn 3 nhưng vẫn dưới 5; cần kiểm tra predictor set tương ứng.\n"
    )
  } else {
    cat(
      "Có VIF ≥ 5, vì vậy cần xem xét collinearity trước khi diễn giải paths.\n"
    )
  }
}

Structural VIF nằm trong khoảng 1.066–1.505. Toàn bộ VIF < 3, do đó không có dấu hiệu structural collinearity đáng kể.


8 8. Bước 6 – R²: khả năng giải thích

8.1 8.1 R² là gì?

R² cho biết tỷ lệ variance của một endogenous construct được giải thích bởi các predictors trong model.

Ví dụ:

\[ R^2 = 0.30 \]

nghĩa là model giải thích khoảng 30% variance của endogenous construct đó.

Các mức 0.25 / 0.50 / 0.75 đôi khi được dùng làm heuristic, nhưng không phải ngưỡng pass/fail phổ quát.

8.2 8.2 Kết quả

show_table(
  r2_table,
  caption = "R² và Adjusted R²"
)
R² và Adjusted R²
Construct R^2 AdjR^2 R2_Heuristic
PU 0.336 0.331 Weak
PEOU 0.216 0.211 Very weak / context dependent
BT 0.351 0.345 Weak
PI 0.292 0.288 Weak
if (all(c("Construct", "R^2") %in% names(r2_table))) {

  ggplot(
    r2_table,
    aes(
      x = reorder(Construct, `R^2`),
      y = `R^2`
    )
  ) +
    geom_col() +
    coord_flip() +
    scale_y_continuous(
      limits = c(0, 1),
      labels = percent_format(accuracy = 1)
    ) +
    labs(
      title = "Explained Variance",
      x = NULL,
      y = expression(R^2)
    ) +
    theme_minimal(base_size = 11)
}

8.3 8.3 R tự diễn giải từng construct

if (all(c("Construct", "R^2") %in% names(r2_table))) {

  for (i in seq_len(nrow(r2_table))) {
    cat(
      sprintf(
        "- **%s:** R² = %.3f → model giải thích khoảng **%.1f%%** variance.\n",
        r2_table$Construct[i],
        r2_table$`R^2`[i],
        100 * r2_table$`R^2`[i]
      )
    )
  }

  cat(
    "\nKhi viết luận văn, nên diễn giải các giá trị này theo bối cảnh nghiên cứu hành vi người tiêu dùng, không gắn nhãn 'tốt/xấu' một cách cơ học.\n"
  )
}
  • PU: R² = 0.336 → model giải thích khoảng 33.6% variance.
  • PEOU: R² = 0.216 → model giải thích khoảng 21.6% variance.
  • BT: R² = 0.351 → model giải thích khoảng 35.1% variance.
  • PI: R² = 0.292 → model giải thích khoảng 29.2% variance.

Khi viết luận văn, nên diễn giải các giá trị này theo bối cảnh nghiên cứu hành vi người tiêu dùng, không gắn nhãn ‘tốt/xấu’ một cách cơ học.


9 9. Bước 7 – f²: effect size của từng predictor

9.1 9.1 f² khác p-value như thế nào?

  • p-value/t-statistic: cho biết bằng chứng về statistical significance;
  • f²: cho biết mức đóng góp cục bộ của một predictor vào R².

Một path có thể:

p < .001 nhưng f² vẫn nhỏ.

Ngưỡng heuristic:

  • 0.02 = small;
  • 0.15 = medium;
  • 0.35 = large.

9.2 9.2 Kết quả

f2_report <- f2_table

if ("f2" %in% names(f2_report)) {
  f2_report <- f2_report |>
    mutate(
      Effect_Size_Recomputed = interpret_f2(f2)
    )
}

show_table(
  f2_report,
  caption = "f² effect sizes"
)
f² effect sizes
From To f2 Effect_Size Effect_Size_Recomputed
SQ PEOU 0.064 Small Small
PP PEOU 0.049 Small Small
TR PEOU 0.060 Small Small
SQ PU 0.052 Small Small
PP PU 0.038 Small Small
TR PU 0.032 Small Small
PEOU PU 0.111 Small Small
SQ BT 0.058 Small Small
PP BT 0.034 Small Small
TR BT 0.023 Small Small
PEOU BT 0.031 Small Small
PU BT 0.037 Small Small
PEOU PI 0.031 Small Small
PU PI 0.023 Small Small
BT PI 0.118 Small Small
if ("f2" %in% names(f2_table) && nrow(f2_table) > 0) {

  cat(
    sprintf(
      "f² nằm trong khoảng **%.3f–%.3f**.\n\n",
      min(f2_table$f2, na.rm = TRUE),
      max(f2_table$f2, na.rm = TRUE)
    )
  )

  f2_counts <- tibble(
    Muc = c("Negligible", "Small", "Medium", "Large"),
    So_path = c(
      sum(f2_table$f2 < 0.02, na.rm = TRUE),
      sum(f2_table$f2 >= 0.02 & f2_table$f2 < 0.15, na.rm = TRUE),
      sum(f2_table$f2 >= 0.15 & f2_table$f2 < 0.35, na.rm = TRUE),
      sum(f2_table$f2 >= 0.35, na.rm = TRUE)
    )
  )

  print(
    knitr::kable(
      f2_counts,
      caption = "Phân loại f²"
    )
  )
}

f² nằm trong khoảng 0.023–0.118.

Phân loại f²
Muc So_path
Negligible 0
Small 15
Medium 0
Large 0

10 10. Bước 8 – Kiểm định direct hypotheses H1–H15

10.1 10.1 Đọc bảng hypothesis như thế nào?

Với một positive hypothesis, cần xem:

  1. β / Original_Est có đúng chiều kỳ vọng không;
  2. t statistic;
  3. bootstrap p-value;
  4. 95% bootstrap CI có chứa 0 không.

Nếu CI không chứa 0 và p < 0.05, relationship có bằng chứng statistical significance ở mức 5%.

10.2 10.2 Bảng H1–H15

direct_report <- direct_results |>
  mutate(
    P_Reported = if ("Bootstrap_P" %in% names(direct_results)) {
      format_p(Bootstrap_P)
    } else NA_character_
  )

show_table(
  direct_report |>
    select(
      any_of(c(
        "Hypothesis",
        "From",
        "To",
        "Original_Est",
        "T_Stat",
        "P_Reported",
        "CI_Lower",
        "CI_Upper",
        "Decision"
      ))
    ),
  caption = "Kết quả H1–H15"
)
Kết quả H1–H15
Hypothesis From To Original_Est T_Stat P_Reported CI_Lower CI_Upper Decision
H1 SQ PU 0.202 5.170 < .001 0.124 0.277 Supported
H2 SQ PEOU 0.237 5.861 < .001 0.158 0.316 Supported
H3 SQ BT 0.215 5.543 < .001 0.140 0.292 Supported
H4 PP PU 0.172 4.532 < .001 0.098 0.247 Supported
H5 PP PEOU 0.207 5.303 < .001 0.132 0.283 Supported
H6 PP BT 0.163 4.411 < .001 0.092 0.236 Supported
H7 TR PU 0.154 4.094 < .001 0.080 0.228 Supported
H8 TR PEOU 0.223 5.820 < .001 0.147 0.298 Supported
H9 TR BT 0.132 3.548 < .001 0.059 0.204 Supported
H10 PEOU PU 0.307 8.084 < .001 0.231 0.380 Supported
H11 PU BT 0.191 4.141 < .001 0.098 0.279 Supported
H12 PEOU BT 0.169 4.023 < .001 0.086 0.251 Supported
H13 PU PI 0.154 3.562 < .001 0.068 0.238 Supported
H14 PEOU PI 0.177 4.133 < .001 0.092 0.260 Supported
H15 BT PI 0.337 8.367 < .001 0.257 0.416 Supported

10.3 10.3 Biểu đồ β và confidence interval

if (all(
  c(
    "Hypothesis",
    "Original_Est",
    "CI_Lower",
    "CI_Upper"
  ) %in% names(direct_results)
)) {

  plot_direct <- direct_results |>
    mutate(
      Label = if (
        all(c("From", "To") %in% names(direct_results))
      ) {
        paste0(Hypothesis, ": ", From, " → ", To)
      } else {
        Hypothesis
      }
    )

  ggplot(
    plot_direct,
    aes(
      x = reorder(Label, Original_Est),
      y = Original_Est
    )
  ) +
    geom_point(size = 2.5) +
    geom_errorbar(
      aes(
        ymin = CI_Lower,
        ymax = CI_Upper
      ),
      width = 0.15
    ) +
    geom_hline(
      yintercept = 0,
      linetype = "dashed"
    ) +
    coord_flip() +
    labs(
      title = "Direct Structural Effects",
      subtitle = "β và 95% bootstrap CI",
      x = NULL,
      y = expression(beta)
    ) +
    theme_minimal(base_size = 11)
}

10.4 10.4 Tự động tóm tắt

if (!is.na(n_direct_supported)) {
  cat(
    sprintf(
      "**Có %d/%d direct hypotheses được hỗ trợ.**\n\n",
      n_direct_supported,
      n_direct_total
    )
  )
}

Có 15/15 direct hypotheses được hỗ trợ.

if (
  all(c("Original_Est", "From", "To") %in% names(direct_results)) &&
    nrow(direct_results) > 0
) {

  strongest_direct <- direct_results |>
    arrange(desc(abs(Original_Est))) |>
    slice(1)

  cat(
    sprintf(
      "Path có |β| lớn nhất là **%s → %s (β = %.3f)**. ",
      strongest_direct$From,
      strongest_direct$To,
      strongest_direct$Original_Est
    )
  )

  cat(
    "Đây là direct standardized relationship lớn nhất trong model, nhưng vẫn cần đọc cùng f² và lý thuyết.\n"
  )
}

Path có |β| lớn nhất là BT → PI (β = 0.337). Đây là direct standardized relationship lớn nhất trong model, nhưng vẫn cần đọc cùng f² và lý thuyết.

10.4.1 Lưu ý p-value

Nếu output hiển thị:

Bootstrap_P = 0

thì trong luận văn viết:

p < .001

không viết:

p = .000


11 11. Bước 9 – Mediation H16–H20 qua Brand Trust

11.1 11.1 Mediation đang kiểm tra điều gì?

Mediation xem xét liệu X có ảnh hưởng đến Purchase Intention thông qua Brand Trust hay không:

\[ X \rightarrow BT \rightarrow PI \]

Specific indirect effect được xem là statistically significant nếu bootstrap confidence interval không chứa 0.

Các giả thuyết:

  • H16: SQ → BT → PI
  • H17: PP → BT → PI
  • H18: TR → BT → PI
  • H19: PU → BT → PI
  • H20: PEOU → BT → PI

11.2 11.2 Bảng mediation

mediation_report <- mediation_results |>
  mutate(
    P_Reported = if ("Bootstrap_P" %in% names(mediation_results)) {
      format_p(Bootstrap_P)
    } else NA_character_
  )

show_table(
  mediation_report |>
    select(
      any_of(c(
        "Hypothesis",
        "From",
        "Through",
        "To",
        "Original_Est",
        "T_Stat",
        "P_Reported",
        "CI_Lower",
        "CI_Upper",
        "Decision",
        "Mediation_Interpretation"
      ))
    ),
  caption = "Specific indirect effects qua Brand Trust"
)
Specific indirect effects qua Brand Trust
Hypothesis From Through To Original_Est T_Stat P_Reported CI_Lower CI_Upper Decision Mediation_Interpretation
H16 SQ BT PI 0.073 4.530 < .001 0.044 0.106 Supported Significant specific indirect effect; direct X->PI path not specified in canonical model
H17 PP BT PI 0.055 3.963 < .001 0.030 0.084 Supported Significant specific indirect effect; direct X->PI path not specified in canonical model
H18 TR BT PI 0.044 3.158 < .001 0.019 0.073 Supported Significant specific indirect effect; direct X->PI path not specified in canonical model
H19 PU BT PI 0.064 3.558 < .001 0.031 0.102 Supported Complementary mediation
H20 PEOU BT PI 0.057 3.687 < .001 0.028 0.089 Supported Complementary mediation

11.3 11.3 Biểu đồ indirect effects

if (all(
  c(
    "Hypothesis",
    "Original_Est",
    "CI_Lower",
    "CI_Upper"
  ) %in% names(mediation_results)
)) {

  plot_med <- mediation_results |>
    mutate(
      Label = if (
        all(c("From", "Through", "To") %in% names(mediation_results))
      ) {
        paste0(
          Hypothesis,
          ": ",
          From,
          " → ",
          Through,
          " → ",
          To
        )
      } else {
        Hypothesis
      }
    )

  ggplot(
    plot_med,
    aes(
      x = reorder(Label, Original_Est),
      y = Original_Est
    )
  ) +
    geom_point(size = 2.5) +
    geom_errorbar(
      aes(
        ymin = CI_Lower,
        ymax = CI_Upper
      ),
      width = 0.15
    ) +
    geom_hline(
      yintercept = 0,
      linetype = "dashed"
    ) +
    coord_flip() +
    labs(
      title = "Specific Indirect Effects qua Brand Trust",
      subtitle = "Indirect effect và 95% bootstrap CI",
      x = NULL,
      y = "Specific indirect effect"
    ) +
    theme_minimal(base_size = 11)
}

11.4 11.4 Tự động tóm tắt

if (!is.na(n_med_supported)) {
  cat(
    sprintf(
      "**Có %d/%d mediation hypotheses được hỗ trợ.**\n\n",
      n_med_supported,
      n_med_total
    )
  )
}

Có 5/5 mediation hypotheses được hỗ trợ.

if (
  all(c("From", "Mediation_Interpretation") %in% names(mediation_results)) &&
    nrow(mediation_results) > 0
) {

  print(
    knitr::kable(
      mediation_results |>
        select(
          any_of(c(
            "Hypothesis",
            "From",
            "Through",
            "To",
            "Mediation_Interpretation"
          ))
        ),
      caption = "Phân loại mediation"
    )
  )
}
Phân loại mediation
Hypothesis From Through To Mediation_Interpretation
H16 SQ BT PI Significant specific indirect effect; direct X->PI path not specified in canonical model
H17 PP BT PI Significant specific indirect effect; direct X->PI path not specified in canonical model
H18 TR BT PI Significant specific indirect effect; direct X->PI path not specified in canonical model
H19 PU BT PI Complementary mediation
H20 PEOU BT PI Complementary mediation

11.5 11.5 Điểm rất quan trọng với H16–H18

Nếu canonical model không estimate:

  • SQ → PI
  • PP → PI
  • TR → PI

thì không nên tự động gọi H16–H18 là:

  • full mediation;
  • partial mediation.

Kết luận chính xác hơn là:

Specific indirect effect through Brand Trust is significant.

Với H19 và H20, vì model có direct paths PU → PI và PEOU → PI, có thể phân loại mediation dựa trên direct và indirect effects.


12 12. Bước 10 – Supplementary serial indirect effects

Ngoài 5 mediation hypotheses chính, model còn tạo ra các chuỗi gián tiếp dài hơn, ví dụ:

\[ SQ \rightarrow PEOU \rightarrow PU \rightarrow BT \rightarrow PI \]

show_table(
  serial_indirect,
  caption = "Supplementary serial indirect effects"
)
Supplementary serial indirect effects
From Through To Effect Original_Est Bootstrap_Mean Bootstrap_SD T_Stat CI_Lower CI_Upper Bootstrap_P Significant
SQ PU PI SQ->PU->PI 0.031 0.031 0.011 2.938 0.012 0.054 0.001 TRUE
SQ PEOU PI SQ->PEOU->PI 0.042 0.042 0.013 3.317 0.020 0.069 0.000 TRUE
SQ PU -> BT PI SQ->PU->BT->PI 0.013 0.013 0.005 2.889 0.005 0.023 0.000 TRUE
SQ PEOU -> BT PI SQ->PEOU->BT->PI 0.013 0.014 0.004 3.018 0.006 0.024 0.000 TRUE
SQ PEOU -> PU PI SQ->PEOU->PU->PI 0.011 0.011 0.004 2.782 0.004 0.020 0.001 TRUE
SQ PEOU -> PU -> BT PI SQ->PEOU->PU->BT->PI 0.005 0.005 0.002 2.849 0.002 0.008 0.000 TRUE
PP PU PI PP->PU->PI 0.026 0.026 0.009 2.879 0.010 0.046 0.001 TRUE
PP PEOU PI PP->PEOU->PI 0.037 0.037 0.011 3.361 0.017 0.060 0.000 TRUE
PP PU -> BT PI PP->PU->BT->PI 0.011 0.011 0.004 2.712 0.004 0.020 0.000 TRUE
PP PEOU -> BT PI PP->PEOU->BT->PI 0.012 0.012 0.004 3.016 0.005 0.020 0.000 TRUE
PP PEOU -> PU PI PP->PEOU->PU->PI 0.010 0.010 0.004 2.600 0.004 0.018 0.001 TRUE
PP PEOU -> PU -> BT PI PP->PEOU->PU->BT->PI 0.004 0.004 0.002 2.728 0.002 0.007 0.000 TRUE
TR PU PI TR->PU->PI 0.024 0.024 0.009 2.632 0.008 0.043 0.001 TRUE
TR PEOU PI TR->PEOU->PI 0.039 0.040 0.012 3.228 0.018 0.066 0.000 TRUE
TR PU -> BT PI TR->PU->BT->PI 0.010 0.010 0.004 2.570 0.004 0.019 0.000 TRUE
TR PEOU -> BT PI TR->PEOU->BT->PI 0.013 0.013 0.004 3.074 0.006 0.022 0.000 TRUE
TR PEOU -> PU PI TR->PEOU->PU->PI 0.011 0.011 0.004 2.811 0.004 0.019 0.001 TRUE
TR PEOU -> PU -> BT PI TR->PEOU->PU->BT->PI 0.004 0.004 0.002 2.862 0.002 0.008 0.000 TRUE
PEOU PU PI PEOU->PU->PI 0.047 0.047 0.015 3.197 0.020 0.078 0.001 TRUE
PEOU PU -> BT PI PEOU->PU->BT->PI 0.020 0.020 0.006 3.332 0.009 0.033 0.000 TRUE

Các paths này nên được xem là:

  • supplementary analysis;
  • dùng cho discussion hoặc appendix;

trừ khi chúng đã được đặt giả thuyết từ trước.

Không nên nhìn thấy significant rồi mới biến chúng thành hypotheses chính.


13 13. Bước 11 – PLSpredict

13.1 13.1 Tại sao cần prediction?

R² là in-sample explanatory power.

PLSpredict hỏi một câu khác:

Model dự báo các observations chưa được dùng để estimate training fold tốt đến đâu?

Vì vậy không được kết luận model có predictive power chỉ vì:

  • R² cao;
  • nhiều path significant.

13.2 13.2 PLS out-of-sample errors

show_table(
  predict_pls_out,
  caption = "PLSpredict – PLS out-of-sample"
)
PLSpredict – PLS out-of-sample
Row PU1 PU2 PU3 PU4 PEOU1 PEOU2 PEOU3 PEOU4 BT1 BT2 BT3 BT4 PI1 PI2 PI3
RMSE 1.058 1.108 1.088 1.072 1.165 1.181 1.152 1.164 1.114 1.069 1.048 1.096 1.152 1.097 1.169
MAE 0.883 0.934 0.894 0.881 0.982 0.993 0.951 0.962 0.926 0.866 0.866 0.899 0.945 0.916 0.984

13.3 13.3 Linear-model benchmark

show_table(
  predict_lm_out,
  caption = "PLSpredict – Linear Model benchmark"
)
PLSpredict – Linear Model benchmark
Row PU1 PU2 PU3 PU4 PEOU1 PEOU2 PEOU3 PEOU4 BT1 BT2 BT3 BT4 PI1 PI2 PI3
RMSE 1.081 1.123 1.106 1.091 1.167 1.200 1.165 1.172 1.120 1.069 1.056 1.101 1.167 1.112 1.183
MAE 0.895 0.944 0.902 0.895 0.988 0.997 0.963 0.969 0.936 0.863 0.867 0.902 0.957 0.923 0.998

13.4 13.4 Construct-level result

show_table(
  predict_construct,
  caption = "PLSpredict – construct-level assessment"
)
PLSpredict – construct-level assessment
Row PU PEOU BT PI
IS_MSE 0.662 0.782 0.646 0.706
IS_MAE 0.672 0.731 0.650 0.696
OOS_MSE 0.671 0.796 0.661 0.714
OOS_MAE 0.677 0.737 0.658 0.700
overfit 0.014 0.018 0.023 0.011

13.5 13.5 Cách đọc

Với cùng một error metric:

  • RMSE càng thấp càng tốt;
  • MAE càng thấp càng tốt.

Nếu PLS có RMSE/MAE thấp hơn benchmark ở phần lớn indicators quan trọng, điều đó hỗ trợ predictive performance.


14 14. Bước 12 – CVPAT

14.1 14.1 CVPAT để làm gì?

PLSpredict cho phép so sánh prediction error.

CVPAT đi thêm một bước: kiểm định xem chênh lệch predictive loss giữa PLS và benchmark có đủ lớn về mặt thống kê hay không.


14.2 14.2 PLS so với Linear Model

show_table(
  cvpat_lm,
  caption = "CVPAT – PLS versus Linear Model"
)
CVPAT – PLS versus Linear Model
Row PLS Loss LM Loss Diff Boot T value Boot P Value
PU 1.170 1.211 -0.041 3.095 0.001
PEOU 1.358 1.383 -0.025 2.099 0.018
BT 1.171 1.181 -0.010 0.620 0.268
PI 1.299 1.333 -0.034 3.132 0.001
Overall 1.250 1.277 -0.027 4.170 0.000

14.3 14.3 PLS so với Indicator Average

show_table(
  cvpat_ia,
  caption = "CVPAT – PLS versus Indicator Average"
)
CVPAT – PLS versus Indicator Average
Row PLS Loss IA Loss Diff Boot T value Boot P Value
PU 1.170 1.520 -0.350 7.587 0
PEOU 1.358 1.570 -0.212 5.474 0
BT 1.171 1.532 -0.361 7.648 0
PI 1.299 1.626 -0.327 6.947 0
Overall 1.250 1.562 -0.313 9.984 0

14.4 14.4 Cách đọc

Trong output của pipeline hiện tại:

  • Difference < 0 → PLS có prediction loss thấp hơn benchmark;
  • sau đó xem p-value để biết improvement có statistically significant hay không.

Cần đọc riêng:

  1. từng endogenous construct;
  2. overall model.

Model có thể outperform benchmark ở overall level nhưng một construct riêng lẻ vẫn không significant.


15 15. Tổng hợp toàn bộ logic phân tích

summary_table <- tibble(
  Buoc = c(
    "1. Data quality",
    "2. Indicator reliability",
    "3. Internal consistency",
    "4. Convergent validity",
    "5. Discriminant validity",
    "6. Structural collinearity",
    "7. Explanatory power",
    "8. Effect size",
    "9. Direct hypotheses",
    "10. Mediation",
    "11. Prediction"
  ),
  Chi_so_chinh = c(
    "Missing, duplicate, range, SPSS–PLS tie-out",
    "Outer loadings",
    "Cronbach's alpha, rho_A, rho_C",
    "AVE",
    "HTMT + bootstrapped HTMT",
    "Structural VIF",
    "R², Adjusted R²",
    "f²",
    "β, t, p, bootstrap CI",
    "Specific indirect effect, bootstrap CI",
    "PLSpredict + CVPAT"
  ),
  Cau_hoi = c(
    "Data có sạch và nhất quán không?",
    "Indicators có phản ánh construct tốt không?",
    "Construct có reliability tốt không?",
    "Construct có convergent validity không?",
    "Các constructs có phân biệt nhau không?",
    "Predictors có bị collinearity không?",
    "Model giải thích được bao nhiêu variance?",
    "Từng predictor đóng góp lớn tới đâu?",
    "H1–H15 có được hỗ trợ không?",
    "Brand Trust có vai trò trung gian không?",
    "Model dự báo out-of-sample tốt không?"
  )
)

show_table(
  summary_table,
  caption = "Trình tự đánh giá PLS-SEM"
)
Trình tự đánh giá PLS-SEM
Buoc Chi_so_chinh Cau_hoi
1. Data quality Missing, duplicate, range, SPSS–PLS tie-out Data có sạch và nhất quán không?
2. Indicator reliability Outer loadings Indicators có phản ánh construct tốt không?
3. Internal consistency Cronbach’s alpha, rho_A, rho_C Construct có reliability tốt không?
4. Convergent validity AVE Construct có convergent validity không?
5. Discriminant validity HTMT + bootstrapped HTMT Các constructs có phân biệt nhau không?
6. Structural collinearity Structural VIF Predictors có bị collinearity không?
7. Explanatory power R², Adjusted R² Model giải thích được bao nhiêu variance?
8. Effect size Từng predictor đóng góp lớn tới đâu?
9. Direct hypotheses β, t, p, bootstrap CI H1–H15 có được hỗ trợ không?
10. Mediation Specific indirect effect, bootstrap CI Brand Trust có vai trò trung gian không?
11. Prediction PLSpredict + CVPAT Model dự báo out-of-sample tốt không?

16 16. Cách chuyển kết quả thành phần Results của luận văn

16.1 16.1 Measurement model

Thứ tự nên viết:

  1. Outer loadings.
  2. Cronbach’s alpha, rho_A, CR.
  3. AVE.
  4. HTMT.
  5. Bootstrapped HTMT.
  6. Kết luận measurement model đạt hay không.

Không cần đọc lại toàn bộ số trong bảng bằng prose.

Ví dụ, thay vì viết 28 loading một lần nữa, chỉ cần:

Outer loadings ranged from X to Y, and all indicators exceeded the recommended reference value of 0.708.

Sau đó bảng sẽ chứa chi tiết.


16.2 16.2 Structural model

Thứ tự:

  1. VIF.
  2. R².
  3. f².
  4. H1–H15.
  5. Nhấn mạnh các paths quan trọng về mặt lý thuyết.

Không nên viết:

“Path này rất mạnh vì p < .001.”

p-value không cho biết magnitude của effect.


16.3 16.3 Mediation

Mỗi hypothesis nên báo cáo:

  • indirect effect;
  • t;
  • p;
  • 95% CI;
  • supported/not supported;
  • mediation interpretation nếu đủ điều kiện.

Cấu trúc câu:

Brand Trust significantly mediated the relationship between X and Purchase Intention (indirect effect = …, t = …, p < …, 95% CI […, …]). Therefore, Hxx was supported.


16.4 16.4 Prediction

Prediction nên nằm sau structural model và mediation:

  1. PLSpredict;
  2. benchmark comparison;
  3. CVPAT;
  4. overall predictive conclusion.

Không được dùng R² thay thế cho predictive assessment.


17 17. Những lỗi cần tránh khi báo cáo

  1. Không xóa item chỉ vì loading thấp hơn 0.708 mà chưa xem CR, AVE và content validity.
  2. Không chỉnh model chỉ để làm hypotheses significant hơn.
  3. Không ghi p = .000; dùng p < .001.
  4. Không đồng nhất statistical significance với effect size.
  5. Không gọi R² là “strong” chỉ dựa vào một heuristic chung.
  6. Không gọi H16–H18 full/partial mediation nếu direct X → PI không được estimate.
  7. Không biến supplementary significant paths thành hypotheses sau khi đã xem kết quả.
  8. Nếu dataset hoặc model thay đổi, phải chạy lại toàn bộ report.

18 18. Reproducibility

cat("Workbook kết quả:", normalizePath(RESULT_FILE), "\n\n")
## Workbook kết quả: D:\Research\ai_home_appliance\data_analysis\ai_appliance_rpubs\R_results\02_pls_sem_results.xlsx
cat("R version:", R.version.string, "\n\n")
## R version: R version 4.6.1 (2026-06-24 ucrt)
cat("Thời điểm tạo report:", format(Sys.time()), "\n\n")
## Thời điểm tạo report: 2026-08-26 14:06:35
sessionInfo()
## R version 4.6.1 (2026-06-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8 
## [2] LC_CTYPE=English_United Kingdom.utf8   
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C                           
## [5] LC_TIME=English_United Kingdom.utf8    
## 
## time zone: Asia/Bangkok
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] tibble_3.3.1  scales_1.4.0  stringr_1.6.0 knitr_1.51    ggplot2_4.0.3
## [6] tidyr_1.3.2   dplyr_1.2.1   readxl_1.5.0 
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.6.1     tidyselect_1.2.1  
##  [5] jquerylib_0.1.4    yaml_2.3.12        fastmap_1.2.0      R6_2.6.1          
##  [9] labeling_0.4.3     generics_0.1.4     bslib_0.11.0       pillar_1.11.1     
## [13] RColorBrewer_1.1-3 rlang_1.2.0        stringi_1.8.7      cachem_1.1.0      
## [17] xfun_0.59          sass_0.4.10        S7_0.2.2           otel_0.2.0        
## [21] cli_3.6.6          withr_3.0.3        magrittr_2.0.5     digest_0.6.39     
## [25] grid_4.6.1         rstudioapi_0.19.0  lifecycle_1.0.5    vctrs_0.7.3       
## [29] evaluate_1.0.5     glue_1.8.1         farver_2.1.2       cellranger_1.1.0  
## [33] rmarkdown_2.31     purrr_1.2.2        tools_4.6.1        pkgconfig_2.0.3   
## [37] htmltools_0.5.9

19 Tài liệu phương pháp nên tham khảo

  • Hair, J. F., Hult, G. T. M., Ringle, C. M., & Sarstedt, M. A Primer on Partial Least Squares Structural Equation Modeling (PLS-SEM).
  • Hair, J. F., Risher, J. J., Sarstedt, M., & Ringle, C. M. Hướng dẫn đánh giá kết quả PLS-SEM.
  • Henseler, J., Ringle, C. M., & Sarstedt, M. Nghiên cứu về HTMT và discriminant validity.
  • Shmueli, G., Sarstedt, M., Hair, J. F., et al. Nghiên cứu về predictive assessment trong PLS-SEM.
  • Zhao, X., Lynch, J. G., & Chen, Q. Nghiên cứu về cách diễn giải mediation.