Bài Tập Buổi 05 — So sánh hai tỷ lệ & Kiểm định độc lập Chi-square

Author

Đỗ Nguyễn Nhật Minh — 2321000336

Published

June 2, 2026

1 BÀI TẬP BUỔI 05 — SO SÁNH HAI TỶ LỆ & KIỂM ĐỊNH ĐỘC LẬP CHI-SQUARE

1.1 Yêu cầu chung và mục tiêu phân tích

Bài phân tích sử dụng bộ dữ liệu hành khách Titanic để đánh giá sự khác biệt về tỷ lệ sống sót theo giới tính (Sex) và hạng vé (Pclass). Bài thực hiện đúng quy trình phân tích dữ liệu định tính: nạp và chuẩn bị dữ liệu, lập bảng chéo, kiểm định độc lập Chi-square, so sánh hai tỷ lệ, đo lường độ mạnh mối liên hệ bằng Cramér’s V, kiểm soát biến phân tầng bằng kiểm định Mantel–Haenszel và trực quan hóa tỷ lệ.

2 Phần A — Thiết lập Quarto Project (CLO2)

2.1 1. Thiết lập chunk toàn cục và nạp thư viện

library(tidyverse)
library(gmodels)
library(vcd)
library(knitr)

3 Phần B — Nạp và Khám phá Dữ liệu (CLO1, CLO2)

3.1 2. Đọc dữ liệu Titanic bằng hai cách

Theo yêu cầu bài tập, dữ liệu có thể được đọc online hoặc offline. Đoạn code dưới đây ưu tiên đường dẫn tương đối offline đúng chuẩn Quarto nếu file titanic.csv đã được đặt trong thư mục Data; nếu không tìm thấy file offline, bài sẽ tự đọc từ nguồn online được đề cung cấp. Đoạn code không sử dụng đường dẫn tuyệt đối gắn với máy cá nhân.

# Cách 1 (Online): nguồn dữ liệu được đề bài cung cấp
online_url <- "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
  df <- read.csv(online_url)
cat("Số dòng:", nrow(df), "- Số biến:", ncol(df), "\n")
Số dòng: 891 - Số biến: 12 

Bộ dữ liệu Titanic có 891 hành khách và 12 biến.

3.2 3. Kiểm tra cấu trúc dữ liệu tổng quát

str(df)
'data.frame':   891 obs. of  12 variables:
 $ PassengerId: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Survived   : int  0 1 1 1 0 0 0 0 1 1 ...
 $ Pclass     : int  3 1 3 1 3 3 1 3 3 2 ...
 $ Name       : chr  "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
 $ Sex        : chr  "male" "female" "female" "female" ...
 $ Age        : num  22 38 26 35 35 NA 54 2 27 14 ...
 $ SibSp      : int  1 1 0 1 0 0 0 3 0 1 ...
 $ Parch      : int  0 0 0 0 0 0 0 1 2 0 ...
 $ Ticket     : chr  "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
 $ Fare       : num  7.25 71.28 7.92 53.1 8.05 ...
 $ Cabin      : chr  "" "C85" "" "C123" ...
 $ Embarked   : chr  "S" "C" "S" "S" ...
glimpse(df)
Rows: 891
Columns: 12
$ PassengerId <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
$ Survived    <int> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1…
$ Pclass      <int> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2, 3, 3…
$ Name        <chr> "Braund, Mr. Owen Harris", "Cumings, Mrs. John Bradley (Fl…
$ Sex         <chr> "male", "female", "female", "female", "male", "male", "mal…
$ Age         <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39, 14, …
$ SibSp       <int> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0…
$ Parch       <int> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0, 0, 0…
$ Ticket      <chr> "A/5 21171", "PC 17599", "STON/O2. 3101282", "113803", "37…
$ Fare        <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51.8625,…
$ Cabin       <chr> "", "C85", "", "C123", "", "", "E46", "", "", "", "G6", "C…
$ Embarked    <chr> "S", "C", "S", "S", "S", "Q", "S", "S", "S", "C", "S", "S"…

3.3 4. Xác định các biến định tính quan trọng

categorical_variables <- data.frame(
  Bien = c("Survived", "Sex", "Pclass"),
  Phan_loai = c("Định tính nhị phân", "Định tính định danh", "Định tính thứ bậc"),
  Y_nghia = c(
    "Tình trạng sống sót: 0 = không sống sót, 1 = sống sót",
    "Giới tính hành khách: female/male",
    "Hạng vé: 1 = hạng nhất, 2 = hạng hai, 3 = hạng ba"
  )
)

kable(categorical_variables, caption = "Các biến định tính sử dụng trong phân tích")
Các biến định tính sử dụng trong phân tích
Bien Phan_loai Y_nghia
Survived Định tính nhị phân Tình trạng sống sót: 0 = không sống sót, 1 = sống sót
Sex Định tính định danh Giới tính hành khách: female/male
Pclass Định tính thứ bậc Hạng vé: 1 = hạng nhất, 2 = hạng hai, 3 = hạng ba

Mặc dù SurvivedPclass được lưu dưới dạng số trong dữ liệu gốc, các con số này là mã nhóm chứ không đại diện cho đại lượng đo lường liên tục. Do đó, cần chuyển hai biến này sang factor trước khi lập bảng chéo và kiểm định.

3.4 5. Kiểm tra và xử lý giá trị thiếu

missing_all <- data.frame(
  Variable = names(df),
  Missing = colSums(is.na(df))
) |>
  arrange(desc(Missing))

kable(
  missing_all |> filter(Missing > 0),
  caption = "Các biến có giá trị thiếu trong dữ liệu gốc"
)
Các biến có giá trị thiếu trong dữ liệu gốc
Variable Missing
Age Age 177
missing_analysis <- data.frame(
  Variable = c("Survived", "Sex", "Pclass"),
  Missing = colSums(is.na(df[c("Survived", "Sex", "Pclass")]))
)

kable(
  missing_analysis,
  caption = "Giá trị thiếu ở ba biến tham gia phân tích chính"
)
Giá trị thiếu ở ba biến tham gia phân tích chính
Variable Missing
Survived Survived 0
Sex Sex 0
Pclass Pclass 0
df_analysis <- df |>
  drop_na(Survived, Sex, Pclass)

cat("Số quan sát trước xử lý:", nrow(df), "\n")
Số quan sát trước xử lý: 891 
cat("Số quan sát dùng phân tích:", nrow(df_analysis), "\n")
Số quan sát dùng phân tích: 891 

Trong dữ liệu gốc, Age, CabinEmbarked có giá trị thiếu. Tuy nhiên, ba biến dùng cho phân tích chính (Survived, Sex, Pclass) không có giá trị thiếu, nên phân tích giữ nguyên toàn bộ 891 quan sát. Việc không xóa các dòng thiếu ở biến không liên quan giúp bảo toàn cỡ mẫu cho câu hỏi nghiên cứu.

3.5 6. Chuyển đổi các biến phân loại thành factor

df_analysis <- df_analysis |>
  mutate(
    Survived = factor(
      Survived,
      levels = c(1, 0),
      labels = c("Survived", "Not Survived")
    ),
    Sex = factor(Sex, levels = c("female", "male"), labels = c("Female", "Male")),
    Pclass = factor(
      Pclass,
      levels = c(1, 2, 3),
      labels = c("First Class", "Second Class", "Third Class"),
      ordered = TRUE
    )
  )

str(df_analysis[c("Survived", "Sex", "Pclass")])
'data.frame':   891 obs. of  3 variables:
 $ Survived: Factor w/ 2 levels "Survived","Not Survived": 2 1 1 1 2 2 2 2 1 1 ...
 $ Sex     : Factor w/ 2 levels "Female","Male": 2 1 1 1 2 2 2 2 1 1 ...
 $ Pclass  : Ord.factor w/ 3 levels "First Class"<..: 3 1 3 1 3 3 1 3 3 2 ...

3.6 7. Thống kê mô tả cơ bản và bảng tần số

summary(df_analysis)
  PassengerId            Survived            Pclass        Name          
 Min.   :  1.0   Survived    :342   First Class :216   Length:891        
 1st Qu.:223.5   Not Survived:549   Second Class:184   Class :character  
 Median :446.0                      Third Class :491   Mode  :character  
 Mean   :446.0                                                           
 3rd Qu.:668.5                                                           
 Max.   :891.0                                                           
                                                                         
     Sex           Age            SibSp           Parch       
 Female:314   Min.   : 0.42   Min.   :0.000   Min.   :0.0000  
 Male  :577   1st Qu.:20.12   1st Qu.:0.000   1st Qu.:0.0000  
              Median :28.00   Median :0.000   Median :0.0000  
              Mean   :29.70   Mean   :0.523   Mean   :0.3816  
              3rd Qu.:38.00   3rd Qu.:1.000   3rd Qu.:0.0000  
              Max.   :80.00   Max.   :8.000   Max.   :6.0000  
              NA's   :177                                     
    Ticket               Fare           Cabin             Embarked        
 Length:891         Min.   :  0.00   Length:891         Length:891        
 Class :character   1st Qu.:  7.91   Class :character   Class :character  
 Mode  :character   Median : 14.45   Mode  :character   Mode  :character  
                    Mean   : 32.20                                        
                    3rd Qu.: 31.00                                        
                    Max.   :512.33                                        
                                                                          
survived_frequency <- table(df_analysis$Survived)
sex_frequency <- table(df_analysis$Sex)
pclass_frequency <- table(df_analysis$Pclass)

kable(addmargins(survived_frequency), caption = "Bảng tần số tình trạng sống sót")
Bảng tần số tình trạng sống sót
Var1 Freq
Survived 342
Not Survived 549
Sum 891
kable(addmargins(sex_frequency), caption = "Bảng tần số giới tính")
Bảng tần số giới tính
Var1 Freq
Female 314
Male 577
Sum 891
kable(addmargins(pclass_frequency), caption = "Bảng tần số hạng vé")
Bảng tần số hạng vé
Var1 Freq
First Class 216
Second Class 184
Third Class 491
Sum 891

4 Phần C — Phân tích Thống kê Chính (CLO2, CLO5)

4.1 8. Bảng chéo giữa giới tính và tình trạng sống sót

sex_survived_table <- table(df_analysis$Sex, df_analysis$Survived)

kable(
  addmargins(sex_survived_table),
  caption = "Bảng chéo giữa giới tính và tình trạng sống sót"
)
Bảng chéo giữa giới tính và tình trạng sống sót
Survived Not Survived Sum
Female 233 81 314
Male 109 468 577
Sum 342 549 891
sex_survival_rate <- prop.table(sex_survived_table, margin = 1) * 100

kable(
  round(sex_survival_rate, 2),
  caption = "Tỷ lệ sống sót theo giới tính (%)"
)
Tỷ lệ sống sót theo giới tính (%)
Survived Not Survived
Female 74.20 25.80
Male 18.89 81.11

Kết quả mô tả cho thấy tỷ lệ sống sót ở nữ là 74,20%, trong khi tỷ lệ sống sót ở nam chỉ là 18,89%. Chênh lệch tỷ lệ sống sót quan sát được là khoảng 55,31 điểm phần trăm.

4.2 9. Kiểm định Chi-square độc lập cho Sex × Survived

4.2.1 Giả thuyết kiểm định

  • (H_0): Giới tính và tình trạng sống sót độc lập với nhau.
  • (H_1): Giới tính và tình trạng sống sót có mối liên hệ với nhau.
# Vì đây là bảng 2x2, chisq.test() mặc định áp dụng hiệu chỉnh liên tục Yates.
sex_chisq <- chisq.test(sex_survived_table)
sex_chisq

    Pearson's Chi-squared test with Yates' continuity correction

data:  sex_survived_table
X-squared = 260.72, df = 1, p-value < 2.2e-16

Kết quả kiểm định cho thấy (^2 ,72), (df = 1) và (p < 2.2 ^{-16}). Do P-value nhỏ hơn mức ý nghĩa 5%, bác bỏ (H_0). Như vậy, giới tính và tình trạng sống sót không độc lập trong dữ liệu Titanic.

4.3 10. Kiểm tra điều kiện áp dụng Chi-square

sex_expected <- sex_chisq$expected

kable(
  round(sex_expected, 2),
  caption = "Tần số kỳ vọng cho bảng Sex × Survived"
)
Tần số kỳ vọng cho bảng Sex × Survived
Survived Not Survived
Female 120.53 193.47
Male 221.47 355.53
cat("Tần số kỳ vọng nhỏ nhất =", round(min(sex_expected), 2), "\n")
Tần số kỳ vọng nhỏ nhất = 120.53 
cat("Tất cả tần số kỳ vọng đều >= 5:", all(sex_expected >= 5), "\n")
Tất cả tần số kỳ vọng đều >= 5: TRUE 

Tần số kỳ vọng nhỏ nhất là 120,53, lớn hơn 5 rất nhiều. Do đó, điều kiện sử dụng xấp xỉ Chi-square được đáp ứng tốt, không cần thay thế bằng Fisher’s Exact Test cho bảng phân tích này.

4.4 11. So sánh hai tỷ lệ sống sót giữa nam và nữ bằng prop.test()

4.4.1 Giả thuyết kiểm định

  • (H_0): (p_{Female} = p_{Male}), tỷ lệ sống sót của nữ và nam bằng nhau.
  • (H_1): (p_{Female} p_{Male}), tỷ lệ sống sót của nữ và nam khác nhau.
survived_by_sex <- sex_survived_table[, "Survived"]
total_by_sex <- rowSums(sex_survived_table)

two_prop_test <- prop.test(
  x = survived_by_sex,
  n = total_by_sex,
  alternative = "two.sided",
  conf.level = 0.95
)

two_prop_test

    2-sample test for equality of proportions with continuity correction

data:  survived_by_sex out of total_by_sex
X-squared = 260.72, df = 1, p-value < 2.2e-16
alternative hypothesis: two.sided
95 percent confidence interval:
 0.4926894 0.6135708
sample estimates:
   prop 1    prop 2 
0.7420382 0.1889081 
survival_comparison <- data.frame(
  Gioi_tinh = names(survived_by_sex),
  So_song_sot = as.numeric(survived_by_sex),
  Tong_hanh_khach = as.numeric(total_by_sex),
  Ty_le_song_sot = as.numeric(survived_by_sex / total_by_sex)
) |>
  mutate(Ty_le_song_sot = scales::percent(Ty_le_song_sot, accuracy = 0.01))

kable(
  survival_comparison,
  caption = "So sánh tỷ lệ sống sót giữa nữ và nam"
)
So sánh tỷ lệ sống sót giữa nữ và nam
Gioi_tinh So_song_sot Tong_hanh_khach Ty_le_song_sot
Female 233 314 74.20%
Male 109 577 18.89%

Kết quả prop.test() cho P-value rất nhỏ hơn 0,05, cho thấy tỷ lệ sống sót giữa nữ và nam khác nhau có ý nghĩa thống kê. Về quy mô thực tế, tỷ lệ nữ sống sót cao hơn tỷ lệ nam khoảng 55,31 điểm phần trăm, đây là mức chênh lệch lớn chứ không chỉ là khác biệt do cỡ mẫu.

4.5 12. Tính Cramér’s V cho mối liên hệ Sex × Survived

sex_assoc <- assocstats(sex_survived_table)
sex_assoc
                    X^2 df P(> X^2)
Likelihood Ratio 268.85  1        0
Pearson          263.05  1        0

Phi-Coefficient   : 0.543 
Contingency Coeff.: 0.477 
Cramer's V        : 0.543 
sex_cramers_v <- as.numeric(sex_assoc$cramer)
cat("Cramér's V =", round(sex_cramers_v, 4), "\n")
Cramér's V = 0.5434 

Cramér’s V xấp xỉ 0,5434, cho thấy mối liên hệ giữa giới tính và tình trạng sống sót có độ mạnh đáng kể. Giá trị này bổ sung cho P-value: không chỉ có bằng chứng thống kê về sự khác biệt, mà độ lớn mối liên hệ cũng quan trọng về mặt thực tế.

4.6 13. Phân tích hạng vé và tình trạng sống sót

Mặc dù yêu cầu trọng tâm là kiểm định Sex × Survived và phân tầng theo Pclass, việc kiểm định thêm Pclass × Survived giúp trả lời trực tiếp câu hỏi liệu hạng vé có liên hệ với khả năng sống sót hay không.

pclass_survived_table <- table(df_analysis$Pclass, df_analysis$Survived)

kable(
  addmargins(pclass_survived_table),
  caption = "Bảng chéo giữa hạng vé và tình trạng sống sót"
)
Bảng chéo giữa hạng vé và tình trạng sống sót
Survived Not Survived Sum
First Class 136 80 216
Second Class 87 97 184
Third Class 119 372 491
Sum 342 549 891
pclass_survival_rate <- prop.table(pclass_survived_table, margin = 1) * 100

kable(
  round(pclass_survival_rate, 2),
  caption = "Tỷ lệ sống sót theo hạng vé (%)"
)
Tỷ lệ sống sót theo hạng vé (%)
Survived Not Survived
First Class 62.96 37.04
Second Class 47.28 52.72
Third Class 24.24 75.76
pclass_chisq <- chisq.test(pclass_survived_table)
pclass_chisq

    Pearson's Chi-squared test

data:  pclass_survived_table
X-squared = 102.89, df = 2, p-value < 2.2e-16
kable(
  round(pclass_chisq$expected, 2),
  caption = "Tần số kỳ vọng cho bảng Pclass × Survived"
)
Tần số kỳ vọng cho bảng Pclass × Survived
Survived Not Survived
First Class 82.91 133.09
Second Class 70.63 113.37
Third Class 188.46 302.54
cat("Tần số kỳ vọng nhỏ nhất =", round(min(pclass_chisq$expected), 2), "\n")
Tần số kỳ vọng nhỏ nhất = 70.63 
cat("Tất cả tần số kỳ vọng đều >= 5:", all(pclass_chisq$expected >= 5), "\n")
Tất cả tần số kỳ vọng đều >= 5: TRUE 
pclass_assoc <- assocstats(pclass_survived_table)
cat("Cramér's V cho Pclass × Survived =", round(as.numeric(pclass_assoc$cramer), 4), "\n")
Cramér's V cho Pclass × Survived = 0.3398 

Tỷ lệ sống sót giảm dần theo hạng vé: 62,96% ở hạng nhất, 47,28% ở hạng hai và 24,24% ở hạng ba. Kiểm định Chi-square cho kết quả (p < 2.2 ^{-16}), do đó hạng vé cũng có mối liên hệ có ý nghĩa thống kê với tình trạng sống sót. Cramér’s V xấp xỉ 0,3398, thể hiện mối liên hệ ở mức vừa và thấp hơn mối liên hệ giữa giới tính với sống sót.

4.7 14. Phân tích phân tầng Mantel–Haenszel: Sex × Survived, phân tầng theo Pclass

4.7.1 Giả thuyết kiểm định

  • (H_0): Sau khi kiểm soát theo hạng vé, không có mối liên hệ chung giữa giới tính và tình trạng sống sót; common odds ratio bằng 1.
  • (H_1): Sau khi kiểm soát theo hạng vé, vẫn tồn tại mối liên hệ chung giữa giới tính và tình trạng sống sót; common odds ratio khác 1.
stratified_table <- xtabs(~ Sex + Survived + Pclass, data = df_analysis)

stratified_table
, , Pclass = First Class

        Survived
Sex      Survived Not Survived
  Female       91            3
  Male         45           77

, , Pclass = Second Class

        Survived
Sex      Survived Not Survived
  Female       70            6
  Male         17           91

, , Pclass = Third Class

        Survived
Sex      Survived Not Survived
  Female       72           72
  Male         47          300
# Bỏ hiệu chỉnh liên tục để báo cáo thống kê Mantel-Haenszel Pearson nhất quán.
mh_test <- mantelhaen.test(stratified_table, correct = FALSE)
mh_test

    Mantel-Haenszel chi-squared test without continuity correction

data:  stratified_table
Mantel-Haenszel X-squared = 250.45, df = 1, p-value < 2.2e-16
alternative hypothesis: true common odds ratio is not equal to 1
95 percent confidence interval:
  9.59290 19.73325
sample estimates:
common odds ratio 
          13.7586 

Kết quả Mantel–Haenszel cho thấy (M^2 ,45), (df = 1), (p < 2.2 ^{-16}). Như vậy, ngay cả khi đã kiểm soát theo hạng vé, giới tính vẫn có mối liên hệ có ý nghĩa thống kê với tình trạng sống sót. Do thứ tự cột của bảng là Survived trước Not Survived, ước lượng common odds ratio xấp xỉ 13,76, hàm ý odds sống sót của nữ cao hơn odds sống sót của nam sau khi điều chỉnh theo hạng vé.

5 Phần D — Trực quan hóa và Báo cáo (CLO2, CLO5)

5.1 15. Biểu đồ cột chồng tỷ lệ sống sót theo giới tính

ggplot(df_analysis, aes(x = Sex, fill = Survived)) +
  geom_bar(position = "fill") +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_fill_manual(
    values = c("Survived" = "#2A9D8F", "Not Survived" = "#E76F51"),
    name = "Tình trạng"
  ) +
  labs(
    title = "Tỷ lệ sống sót của hành khách Titanic theo giới tính",
    subtitle = "So sánh tỷ lệ trong từng nhóm giới tính",
    x = "Giới tính",
    y = "Tỷ lệ hành khách"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold"),
    legend.position = "top"
  )

5.2 16. Diễn giải kết quả phân tích thống kê và đồ thị

Kết quả phân tích cho thấy cơ hội sống sót trên tàu Titanic có sự khác biệt rõ rệt theo cả giới tính và hạng vé. Tỷ lệ sống sót của hành khách nữ đạt 74,20%, trong khi tỷ lệ này ở hành khách nam chỉ là 18,89%. Kiểm định Chi-square và kiểm định so sánh hai tỷ lệ đều cho P-value nhỏ hơn 0,05, cho phép kết luận giới tính có mối liên hệ có ý nghĩa thống kê với tình trạng sống sót. Quan trọng hơn, Cramér’s V của quan hệ Sex × Survived đạt khoảng 0,5434, cho thấy đây không chỉ là khác biệt thống kê mà còn là khác biệt lớn về mặt thực tế. Bên cạnh đó, tỷ lệ sống sót của hành khách hạng nhất cao hơn đáng kể so với hạng ba, và kiểm định Pclass × Survived cũng có ý nghĩa thống kê. Kiểm định Mantel–Haenszel tiếp tục xác nhận rằng sau khi đã kiểm soát theo hạng vé, sự khác biệt theo giới tính vẫn còn tồn tại rất rõ. Trong bối cảnh an toàn và quản trị rủi ro vận tải hành khách, kết quả gợi ý quy trình sơ tán trong sự kiện này đã ưu tiên phụ nữ, đồng thời khả năng tiếp cận vị trí cứu hộ có thể khác biệt theo hạng vé.

6 Phần E — Prompt AI Nâng cao

6.1 Prompt 1 — Tình huống thực tế theo ngành

Prompt đã sử dụng:

Tôi đang học So sánh hai tỷ lệ và Kiểm định độc lập Chi-square trong môn Phân tích Dữ liệu Định tính bằng R.
Hãy tạo cho tôi một bài toán thực tế trong lĩnh vực Bảo hiểm có sử dụng Kiểm định Chi-square độc lập. Bài toán phải có: (1) mô tả tình huống, (2) dữ liệu giả định dạng bảng 2x2, (3) câu hỏi phân tích cụ thể, (4) gợi ý code R để giải quyết.

Tóm tắt trả lời của AI:

Một công ty bảo hiểm xe cơ giới muốn đánh giá liệu loại gói bảo hiểm có liên hệ với việc phát sinh yêu cầu bồi thường trong năm hay không. Dữ liệu giả định:

Loại gói bảo hiểm Không yêu cầu bồi thường Có yêu cầu bồi thường Tổng
Cơ bản 180 70 250
Toàn diện 260 40 300
Tổng 440 110 550

Câu hỏi phân tích là: tỷ lệ yêu cầu bồi thường có độc lập với loại gói bảo hiểm hay không? Nếu P-value nhỏ hơn 0,05, công ty có bằng chứng rằng rủi ro bồi thường khác nhau theo loại gói. Tuy nhiên, để ra quyết định định phí, cần xem thêm Cramér’s V và quy mô chênh lệch tỷ lệ, không chỉ dựa vào P-value.

insurance_table <- matrix(
  c(180, 70,
    260, 40),
  nrow = 2,
  byrow = TRUE,
  dimnames = list(
    Goi_bao_hiem = c("Co ban", "Toan dien"),
    Boi_thuong = c("Khong", "Co")
  )
)

insurance_test <- chisq.test(insurance_table)
insurance_test
insurance_test$expected
vcd::assocstats(insurance_table)

6.2 Prompt 2 — Phản biện kỹ thuật và lỗi thường gặp

Prompt đã sử dụng:

Trong R, khi tôi chạy chisq.test(), tôi nhận được cảnh báo: 'Chi-squared approximation may be incorrect'. Hãy giải thích:
(1) Nguyên nhân của cảnh báo này là gì?
(2) Điều kiện nào bị vi phạm?
(3) Cách khắc phục hoặc lựa chọn phương pháp thay thế phù hợp hơn (ví dụ Fisher's Exact Test)?

Tóm tắt trả lời của AI:

Cảnh báo xuất hiện khi xấp xỉ phân phối Chi-square không đáng tin cậy, thường do một hoặc nhiều ô có tần số kỳ vọng quá nhỏ, đặc biệt là nhỏ hơn 5. Khi điều kiện này bị vi phạm, P-value của chisq.test() có thể không phản ánh chính xác bằng chứng thống kê. Cách xử lý là trích xuất test$expected để kiểm tra; với bảng 2x2 có tần số kỳ vọng nhỏ, có thể dùng fisher.test() vì đây là kiểm định chính xác. Trong bài Titanic, tần số kỳ vọng nhỏ nhất của bảng Sex × Survived lớn hơn 5 rất nhiều, nên việc dùng Chi-square là phù hợp.

7 Phần F — AI-Grader Prompt và Tự đánh giá

7.1 Prompt đánh giá đã hoàn thiện với code và output thực tế

Tôi vừa hoàn thành bài tập R về Kiểm định Chi-square và So sánh hai tỷ lệ. Hãy đánh giá code và kết quả của tôi theo 4 tiêu chí sau (thang điểm 10):

1. Tính đúng đắn thống kê (CLO2/CLO3): Hàm R được dùng có đúng với phương pháp không? Kết quả có hợp lý không?
2. Chất lượng diễn giải (CLO5): Có giải thích kết quả bằng ngôn ngữ kinh tế–tài chính chứ không chỉ đọc số liệu không?
3. Chuẩn đường dẫn Quarto (CLO2): Có dùng đường dẫn tương đối đúng chuẩn không?
4. Xử lý lỗi & cảnh báo (CLO4): Có kiểm tra điều kiện áp dụng phương pháp không (tần số kỳ vọng)?

CODE R VÀ OUTPUT CỦA BÀI LÀM:

1. Nạp dữ liệu bằng đường dẫn đúng chuẩn

Code R:

online_url <- "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"

  df <- read.csv(online_url)

cat("Số dòng:", nrow(df), "- Số biến:", ncol(df), "\n")

Output chính:

Số dòng: 891 - Số biến: 12


2. Kiểm tra và chuyển đổi biến phân loại

Code R:

df_analysis <- df |>
  drop_na(Survived, Sex, Pclass) |>
  mutate(
    Survived = factor(Survived, levels = c(1, 0),
                      labels = c("Survived", "Not Survived")),
    Sex = factor(Sex, levels = c("female", "male"),
                 labels = c("Female", "Male")),
    Pclass = factor(Pclass, levels = c(1, 2, 3),
                    labels = c("First Class", "Second Class", "Third Class"),
                    ordered = TRUE)
  )

Output chính:

Số quan sát dùng phân tích: 891
Không có NA ở Survived, Sex và Pclass.


3. Lập bảng chéo Sex × Survived và tỷ lệ theo hàng

Code R:

sex_survived_table <- table(df_analysis$Sex, df_analysis$Survived)
sex_survival_rate <- prop.table(sex_survived_table, margin = 1) * 100

Output:

        Survived  Not Survived
Female       233            81
Male         109           468

        Survived  Not Survived
Female     74.20         25.80
Male       18.89         81.11


4. Chạy kiểm định Chi-square và kiểm tra điều kiện

Code R:

sex_chisq <- chisq.test(sex_survived_table)
sex_chisq
sex_chisq$expected
min(sex_chisq$expected)
all(sex_chisq$expected >= 5)

Output:

Pearson's Chi-squared test with Yates' continuity correction
X-squared = 260.72, df = 1, p-value < 2.2e-16

        Survived  Not Survived
Female    120.53        193.47
Male      221.47        355.53

Tần số kỳ vọng nhỏ nhất = 120.53
Tất cả tần số kỳ vọng đều >= 5: TRUE


5. So sánh hai tỷ lệ sống sót

Code R:

survived_by_sex <- sex_survived_table[, "Survived"]
total_by_sex <- rowSums(sex_survived_table)
two_prop_test <- prop.test(x = survived_by_sex, n = total_by_sex)
two_prop_test

Output chính:

Tỷ lệ sống sót Female = 74.20%
Tỷ lệ sống sót Male = 18.89%
Chênh lệch = 55.31 điểm phần trăm
p-value < 2.2e-16


6. Tính Cramér's V

Code R:

sex_assoc <- assocstats(sex_survived_table)
sex_assoc$cramer

Output:

Cramér's V cho Sex × Survived = 0.5434


7. Phân tích Pclass × Survived

Code R:

pclass_survived_table <- table(df_analysis$Pclass, df_analysis$Survived)
pclass_survival_rate <- prop.table(pclass_survived_table, margin = 1) * 100
pclass_chisq <- chisq.test(pclass_survived_table)
pclass_assoc <- assocstats(pclass_survived_table)

Output chính:

Tỷ lệ sống sót:
First Class = 62.96%
Second Class = 47.28%
Third Class = 24.24%

Chi-square: X-squared = 102.89, df = 2, p-value < 2.2e-16
Cramér's V = 0.3398


8. Phân tích phân tầng Mantel-Haenszel

Code R:

stratified_table <- xtabs(~ Sex + Survived + Pclass, data = df_analysis)
mh_test <- mantelhaen.test(stratified_table, correct = FALSE)
mh_test

Output chính:

Mantel-Haenszel X-squared = 250.45, df = 1, p-value < 2.2e-16
Common odds ratio = 13.76


9. Trực quan hóa tỷ lệ sống sót

Code R:

ggplot(df_analysis, aes(x = Sex, fill = Survived)) +
  geom_bar(position = "fill") +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "Tỷ lệ sống sót của hành khách Titanic theo giới tính",
    x = "Giới tính",
    y = "Tỷ lệ hành khách",
    fill = "Tình trạng"
  ) +
  theme_minimal()

Nhận xét:

Bài đã dùng đúng bảng chéo, kiểm định Chi-square, prop.test(), assocstats() và mantelhaen.test() cho từng mục tiêu phân tích. Điều kiện Chi-square được kiểm tra bằng tần số kỳ vọng và đều thỏa mãn. Đường dẫn offline được trình bày dưới dạng tương đối ../../Data/titanic.csv và bài có thể dùng nguồn online khi file offline chưa có. Kết quả không chỉ diễn giải P-value mà còn sử dụng Cramér's V để đánh giá độ mạnh của mối liên hệ.

7.2 Tự đánh giá theo rubric

Tiêu chí Minh chứng trong bài Điểm tự đánh giá
Tính đúng đắn thống kê Sử dụng đúng table(), chisq.test(), prop.test(), assocstats()mantelhaen.test() theo từng câu hỏi phân tích. 2.5/2.5
Chất lượng diễn giải Phân biệt ý nghĩa thống kê và độ mạnh mối liên hệ; diễn giải cơ hội sống sót theo giới tính và hạng vé trong bối cảnh an toàn hành khách. 2.5/2.5
Chuẩn đường dẫn Quarto Có đường dẫn tương đối ../../Data/titanic.csv; không sử dụng đường dẫn tuyệt đối phụ thuộc máy cá nhân; có fallback online đúng nguồn đề cung cấp. 2.5/2.5
Xử lý lỗi và cảnh báo Kiểm tra NA ở biến phân tích; trích xuất tần số kỳ vọng và xác nhận tất cả ô đều lớn hơn 5 trước khi kết luận. 2.5/2.5
Tổng điểm tự đánh giá Bài hoàn thành đầy đủ quy trình được đề yêu cầu. 10.0/10.0

8 Kết luận chung

Bằng quy trình phân tích dữ liệu định tính, bài làm cho thấy tỷ lệ sống sót trên Titanic liên hệ mạnh với giới tính và liên hệ vừa với hạng vé. Nữ giới có tỷ lệ sống sót cao hơn nam giới rõ rệt, và sự khác biệt này vẫn tồn tại sau khi phân tầng theo hạng vé. Việc kiểm tra điều kiện Chi-square, kết hợp P-value với Cramér’s V và sử dụng Mantel–Haenszel giúp kết luận vừa đúng về mặt thống kê, vừa có ý nghĩa thực tiễn.