BÀI 1: KHỞI TẠO VÀ KHÁM PHÁ DỮ LIỆU

Nhập dữ liệu và kiểm tra giá trị khuyết

if(!require("pacman")) install.packages("pacman")
pacman::p_load(rio, tidyverse, gtsummary)
# Nhập dữ liệu
df <- rio::import("Day3_Cardio.csv")

# Kiểm tra tổng quan
glimpse(df)
## Rows: 500
## Columns: 10
## $ ID              <chr> "PT001", "PT002", "PT003", "PT004", "PT005", "PT006", …
## $ Age             <int> 60, 44, 56, 54, 48, 30, 48, 45, 56, 50, 51, 48, 53, 53…
## $ Gender          <chr> "Male", "Male", "Male", "Female", "Female", "Male", "M…
## $ Height_cm       <int> 171, 169, 170, 154, 154, 157, 176, 165, 161, 159, 156,…
## $ Weight_kg       <int> 61, 65, 68, 68, 56, 77, 76, 55, 45, 56, 54, 54, 66, 71…
## $ Smoking         <chr> "Yes", "No", "Yes", "No", "No", "No", "No", "No", "No"…
## $ Coffee_Cups     <int> 4, 0, 4, 0, 1, 2, 0, 1, 0, 1, 1, 2, 0, 1, 1, 4, 1, 2, …
## $ Knowledge_Score <dbl> 53.4, 69.9, 74.4, 73.6, 57.0, 54.8, 51.7, 68.8, 68.4, …
## $ Triglycerides   <dbl> 1.03, 1.65, 3.04, 1.32, 1.53, 2.19, NA, 0.56, 2.09, 1.…
## $ Systolic_BP     <int> 152, 136, 155, 149, 151, 145, 155, 131, 147, 151, 153,…
# Tính tổng giá trị khuyết của từng cột (NA)
colSums(is.na(df))
##              ID             Age          Gender       Height_cm       Weight_kg 
##               0               0               0               0               0 
##         Smoking     Coffee_Cups Knowledge_Score   Triglycerides     Systolic_BP 
##               0               0               0              25               0

[Tư duy] Tôi phát hiện biến Triglycerides có chứa các giá trị khuyết (NA). Theo tiêu chuẩn Q1, tôi không được phép tự ý lấy số Trung bình để điền vào ô khuyết này. Vì Triglycerides là một chỉ số sinh học thường có phân phối lệch (không chuẩn), có nhiều giá trị cực đoan (outliers). Việc dùng số Trung bình (Mean) để điền khuyết sẽ làm sai lệch bản chất dữ liệu, kéo giá trị trung tâm về phía các sai số, từ đó dẫn đến kết luận sai về nguy cơ tim mạch của bệnh nhân

BÀI 2: CHẨN ĐOÁN “SỨC KHỎE” BIẾN SỐ

Vẽ đồ thị Histogram, Q-Q Plot và kiểm định chuẩn

par(mfrow=c(2,2))

# Đối với Knowledge_Score
hist(df$Knowledge_Score, main="Histogram Knowledge_Score", col="lightblue", border="white")
abline(v = mean(df$Knowledge_Score, na.rm=T), col="red", lwd=2)
qqnorm(df$Knowledge_Score, main="Q-Q Plot Knowledge_Score")
qqline(df$Knowledge_Score, col="red")

# Đối với Triglycerides
hist(df$Triglycerides, main="Histogram Triglycerides", col="lightgreen", border="white")
abline(v = mean(df$Triglycerides, na.rm=T), col="red", lwd=2)
qqnorm(df$Triglycerides, main="Q-Q Plot Triglycerides")
qqline(df$Triglycerides, col="red")

par(mfrow=c(1,1))

# Kiểm định chuẩn
shapiro.test(df$Knowledge_Score)
## 
##  Shapiro-Wilk normality test
## 
## data:  df$Knowledge_Score
## W = 0.99823, p-value = 0.8943
shapiro.test(na.omit(df$Triglycerides))
## 
##  Shapiro-Wilk normality test
## 
## data:  na.omit(df$Triglycerides)
## W = 0.91515, p-value = 1.123e-15

[Tư duy] Quan sát Q-Q Plot, Ở biến Triglycerides, các chấm đen văng ra khỏi đường thẳng rất xa, đặc biệt là ở phần đuôi phía trên. -> Kết luận: Biến Triglycerides không tuân theo phân phối chuẩn. Ngược lại, Knowledge_Score có các chấm đen bám khá sát đường thẳng, thể hiện phân phối xấp xỉ chuẩn. Kết quả kiểm định Shapiro với p-value < 0.05 của Triglycerides cũng khẳng định điều này.

BÀI 3: PHẪU THUẬT DỮ LIỆU LỆCH

Biến đổi Logarit cơ số 10 và vẽ lại Q-Q Plot

df <- df %>% 
  mutate(Log10_Trig = log10(Triglycerides))

# Vẽ lại Q-Q plot để kiểm tra kết quả sau biến đổi
qqnorm(df$Log10_Trig, main="Q-Q Plot: Log10(Triglycerides)", col="darkblue")
qqline(df$Log10_Trig, col="red", lwd=2)

[Tư duy] Sau khi “phẫu thuật”, dữ liệu đã đủ điều kiện để chạy các kiểm định tham số (như T-test). Vì sau khi biến đổi Logarit, đồ thị Q-Q Plot cho thấy các điểm dữ liệu đã bám sát đường thẳng chuẩn, lỗi lệch phải (Right-skewed) ban đầu đã được khắc phục. Khi dữ liệu thỏa mãn giả định phân phối chuẩn (hoặc xấp xỉ chuẩn), các kiểm định tham số sẽ có độ tin cậy và sức mạnh thống kê cao nhất.

BÀI 4: SO SÁNH TRUNG BÌNH (T-TEST)

Thực hiện T-test

t.test(Knowledge_Score ~ Gender, data = df)
## 
##  Welch Two Sample t-test
## 
## data:  Knowledge_Score by Gender
## t = 0.32143, df = 490.44, p-value = 0.748
## alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
## 95 percent confidence interval:
##  -1.789442  2.489442
## sample estimates:
## mean in group Female   mean in group Male 
##                64.39                64.04

[Tư duy] Nếu Khoảng tin cậy 95% (95% CI) chứa giá trị 0, điều đó có nghĩa là sự khác biệt giữa hai nhóm không có ý nghĩa thống kê (p > 0.05). Trên thực tế sự khác biệt này là quá nhỏ (không có ý nghĩa lâm sàng). Tôi không cần đưa ra chương trình giáo dục riêng biệt cho từng giới tính. Việc áp dụng chung một chương trình đào tạo sẽ giúp tối ưu hóa nguồn lực y tế mà vẫn đảm bảo hiệu quả.

BÀI 5: KIỂM ĐỊNH TỶ LỆ (CHI-SQUARE)

Mối liên quan giữa Giới tính và Hút thuốc

# Bảng tần suất
table_smoke <- table(df$Gender, df$Smoking)
table_smoke
##         
##           No Yes
##   Female 264   6
##   Male   152  78
# Kiểm định Chi-square
chisq.test(table_smoke)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table_smoke
## X-squared = 86.986, df = 1, p-value < 2.2e-16

[Tư duy] Nếu P < 0.05, ta kết luận giới tính có liên quan đến hành vi hút thuốc. Tuy p-value có ý nghĩa thống kê, nhưng quan trọng nhất là nhìn vào tỷ lệ: Nếu Nam giới hút thuốc cao gấp nhiều lần Nữ giới, thì ý nghĩa thực tế là các chiến dịch truyền thông cai thuốc lá cần nhắm mục tiêu (Targeting) cụ thể vào Nam giới thay vì dàn trải nguồn lực cho cả hai giới.

BÀI 6: BẪY TƯƠNG QUAN VS SO SÁNH NHÓM (PDTR)

Kiểm định mối liên hệ giữa BMI và Triglycerides

# Tính chỉ số BMI
df <- df %>% 
  mutate(BMI = Weight_kg / (Height_cm / 100)^2)

# Cách 1: Tương quan (Dành cho 2 biến định lượng)
cor.test(df$BMI, df$Triglycerides, method = "spearman")
## 
##  Spearman's rank correlation rho
## 
## data:  df$BMI and df$Triglycerides
## S = 16826091, p-value = 0.2071
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##        rho 
## 0.05798988
# Cách 2: T-test (Bằng cách phân nhóm BMI)
df <- df %>% 
  mutate(BMI_Group = ifelse(BMI >= 25, "Overweight", "Normal"))

t.test(Log10_Trig ~ BMI_Group, data = df)
## 
##  Welch Two Sample t-test
## 
## data:  Log10_Trig by BMI_Group
## t = -0.92044, df = 444.51, p-value = 0.3578
## alternative hypothesis: true difference in means between group Normal and group Overweight is not equal to 0
## 95 percent confidence interval:
##  -0.04637122  0.01679014
## sample estimates:
##     mean in group Normal mean in group Overweight 
##                0.1566173                0.1714079

[Tư duy] Nên dùng Tương quan (Correlation) để đánh giá mối liên hệ vì cả BMI và Triglycerides đều là biến định lượng liên tụ và T-test yêu cầu một biến phải là định tính (nhóm). Nếu dùng T-test, ta buộc phải “cắt” BMI thành các nhóm, điều này làm mất đi thông tin chi tiết của dữ liệu gốc.

=> Giải pháp Tốt nhất là trình bày cả hai: Tương quan để thấy xu hướng chung, và T-test (sau khi phân nhóm BMI) để bác sĩ dễ dàng tư vấn cho bệnh nhân theo các ngưỡng lâm sàng (Ví dụ: Nhóm béo phì có mỡ máu cao hơn nhóm thường bao nhiêu).

BÀI 7: ĐÓNG GÓI TABLE 1 (CHUẨN QUỐC TẾ)

Tạo Table 1 phân tầng theo Smoking

df %>%
  select(Gender, Age, BMI, Knowledge_Score, Triglycerides, Smoking) %>%
  tbl_summary(
    by = Smoking,
    statistic = list(all_continuous() ~ "{mean} ({sd})",
                     all_categorical() ~ "{n} ({p}%)"),
    digits = list(
      all_continuous() ~ 1,
      all_categorical() ~ c(0, 1)
    )
  ) %>%
  add_p() %>%
  bold_labels()
Characteristic No
N = 416
1
Yes
N = 84
1
p-value2
Gender

<0.001
    Female 264 (63.5%) 6 (7.1%)
    Male 152 (36.5%) 78 (92.9%)
Age 55.1 (10.2) 56.6 (10.6) 0.2
BMI 24.4 (4.7) 24.7 (4.5) 0.5
Knowledge_Score 64.0 (12.2) 65.2 (11.8) 0.5
Triglycerides 1.6 (0.7) 1.6 (0.7) >0.9
    Unknown 18 7
1 n (%); Mean (SD)
2 Pearson’s Chi-squared test; Wilcoxon rank sum test

[Tư duy] Diễn giải kết quả:

  • Nghiên cứu ghi nhận sự khác biệt rõ rệt về phân bố giới tính giữa nhóm hút thuốc và không hút thuốc, với tỷ lệ nam giới hút thuốc cao hơn đáng kể (p < 0.001).

  • Các chỉ số nhân trắc học như tuổi và BMI có xu hướng tương đồng giữa hai nhóm, tuy nhiên mức Triglycerides ở nhóm hút thuốc ghi nhận giá trị trung bình cao hơn so với nhóm không hút thuốc.

  • Điểm kiến thức về sức khỏe tim mạch (Knowledge Score) không cho thấy sự khác biệt có ý nghĩa thống kê giữa nhóm hút thuốc và không hút thuốc (p > 0.05), cho thấy hành vi hút thuốc có thể không phụ thuộc vào mức độ hiểu biết của bệnh nhân.