library(janitor)
library(kableExtra)
library(tidyverse)
library(readxl)
library(scales)
library(epitools)
library(nortest)
library(pROC)
library(caret)
library(ggplot2)Đột quỵ là một bệnh lý nguy hiểm và phổ biến, được Tổ chức Y tế Thế giới (WHO) xếp vào nhóm nguyên nhân gây tử vong và tàn tật hàng đầu trên toàn cầu. Bản chất của đột quỵ là tình trạng rối loạn cấp tính tuần hoàn não, gây chết tế bào não do thiếu oxy và dưỡng chất. Bệnh có thể khởi phát đột ngột với nhiều biểu hiện như liệt nửa người, mất khả năng nói, giảm thị lực hoặc chóng mặt, và để lại di chứng nặng nề về thể chất lẫn tinh thần nếu không được điều trị kịp thời. Đặc biệt, những yếu tố nguy cơ như tăng huyết áp, tiểu đường, mức đường huyết, hút thuốc lá, béo phì đã được chứng minh có mối liên hệ chặt chẽ với khả năng xuất hiện đột quỵ. Vì vậy, việc phân tích các tác động của các yếu tố nguy cơ là điều kiện để xây dựng kế hoạch phòng và phác đồ hiệu quả.
Trong thời đại dữ liệu lớn và khoa học dữ liệu phát triển mạnh mẽ, việc ứng dụng các kỹ thuật phân tích định lượng để khai thác dữ liệu y tế đang mở ra nhiều cơ hội trong lĩnh vực chăm sóc sức khỏe. Bộ dữ liệu được sử dụng trong nghiên cứu này bao gồm các thông tin y học quan trọng như tuổi, giới tính, chỉ số BMI, mức đường huyết trung bình, tiền sử bệnh lý và hành vi sức khỏe của bệnh nhân. Việc phân tích bộ dữ liệu này sẽ giúp khám phá các mối quan hệ tiềm ẩn giữa các yếu tố nguy cơ và khả năng mắc đột quỵ, đồng thời hỗ trợ xây dựng các mô hình dự đoán có giá trị ứng dụng thực tiễn trong nghiên cứu lâm sàng và quản lý y tế cộng đồng. Chính vì vậy, đề tài “Phân tích các nguy cơ ảnh hưởng đến đột quỵ” được lựa chọn nhằm đáp ứng nhu cầu cấp thiết về dự báo và phòng ngừa căn bệnh này trong bối cảnh hiện nay.
Nghiên cứu này nhằm xác định và phân tích các yếu tố nguy cơ có liên quan đến khả năng mắc đột quỵ thông qua dữ liệu bệnh nhân thực tế. Mục tiêu trọng tâm là nhận diện những yếu tố có tác động dương mạnh nhất đến xác suất xảy ra đột quỵ, từ đó đề xuất các giải pháp phòng ngừa và can thiệp hiệu quả. Đồng thời, nghiên cứu cũng hướng đến việc phát hiện những yếu tố có tác động âm – tức là làm giảm nguy cơ – nhằm khai thác và tăng cường các yếu tố bảo vệ sức khỏe. Bên cạnh đó, nghiên cứu còn so sánh mức độ ảnh hưởng tương đối giữa các nguy cơ, từ các đặc điểm nhân khẩu học (tuổi, giới tính) đến hành vi sức khỏe (hút thuốc, béo phì) và bệnh lý nền (tăng huyết áp, tiểu đường, bệnh tim). Thông qua mô hình hồi quy nhị phân (Logit và Probit), nghiên cứu kỳ vọng cung cấp bằng chứng định lượng hỗ trợ công tác sàng lọc, dự báo nguy cơ và xây dựng chiến lược kiểm soát đột quỵ trong cộng đồng.
Đối tượng nghiên cứu của đề tài là các cá nhân có hồ sơ sức khỏe được ghi nhận trong bộ dữ liệu liên quan đến đột quỵ. Mỗi cá nhân được mô tả thông qua các biến đặc trưng về nhân khẩu học, chỉ số sinh học, bệnh lý nền và hành vi sức khỏe như tuổi, giới tính, mức đường huyết trung bình, BMI, tình trạng tăng huyết áp, tiểu đường, hút thuốc và địa vị xã hội. Những thông tin này được sử dụng để phân tích mối liên hệ giữa các yếu tố nguy cơ và khả năng mắc đột quỵ.
Nghiên cứu sử dụng phương pháp phân tích định lượng trên bộ dữ liệu bệnh nhân nhằm khám phá mối liên hệ giữa các yếu tố nguy cơ và khả năng mắc đột quỵ. Ở phân tích đơn biến, các biến định tính được phân tích thông qua bảng tần số, bảng tỷ lệ và biểu đồ cột, trong khi các biến định lượng được mô tả bằng thống kê mô tả (trung bình, trung vị, độ lệch chuẩn, tứ phân vị),biểu đồ histogram kết hợp mật độ ,biểu đồ boxplot và kiểm định phân phối chuẩn là Anderson-Darling.
Ở phân tích hai biến, các cặp biến định tính–định tính được trình bày qua bảng chéo tần số, biểu đồ cột chồng theo tỷ lệ, và kiểm định Chi-squared đồng thời tính toán Odds Ratio (OR) và Relative Risk (RR) nhằm sự tác động. Với cặp biến định tính–định lượng, nghiên cứu sử dụng biểu đồ histogram kết hợp mật độ, boxplot phân nhóm theo biến định tính, và kiểm định sự khác biệt trung bình giữa hai nhóm bằng t-test (nếu phân phối chuẩn) hoặc Wilcoxon rank-sum test (nếu không chuẩn).
Cuối cùng, mô hình hồi quy nhị phân Logit và Probit được ước lượng nhằm xác định các yếu tố nguy cơ ảnh hưởng có ý nghĩa đến xác suất xảy ra đột quỵ, đồng thời so sánh mức độ tác động tương đối của từng biến giải thích trong việc dự báo biến phụ thuộc.
## tibble [10,000 × 10] (S3: tbl_df/tbl/data.frame)
## $ Age : num [1:10000] 66.8 86.4 76.2 72.5 59.9 ...
## $ Gender : chr [1:10000] "Male" "Female" "Female" "Female" ...
## $ SES : chr [1:10000] "Medium" "Medium" "Medium" "Low" ...
## $ Hypertension : num [1:10000] 1 1 1 0 0 1 1 1 1 1 ...
## $ Heart_Disease : num [1:10000] 0 1 0 1 0 0 0 0 0 0 ...
## $ BMI : num [1:10000] 25.8 32.5 40.7 33 26.1 ...
## $ Avg_Glucose : num [1:10000] 96.4 133.4 111.5 125.7 123.2 ...
## $ Diabetes : num [1:10000] 1 0 0 0 1 0 0 0 0 0 ...
## $ Smoking_Status: chr [1:10000] "Current" "Never" "Never" "Former" ...
## $ Stroke : num [1:10000] 1 1 0 0 1 0 1 1 0 0 ...
Đây là bộ dữ liệu tập hợp hồ sơ sức khoẻ của các bệnh nhân dùng để phân tích các yếu tố liên quan đến đột quỵ. Bộ dữ liệu này bao gồm các chỉ số về tình trạng y tế, thói quen sinh hoạt và các thông tin cá nhân.Mục tiêu chính của bộ dữ liệu là xây dựng lên mô hình có thể dự đoán đột quỵ và nghiên cứu mối tương quan giữa các yếu tố lối sống, sinh trắc học với nguy cơ mắc bệnh.
Trong bộ dữ liệu bao gồm các biến như sau:
Biến định lượng
Biến định tính
Biến phụ thuộc
Relative Risk là một chỉ số thống kê dùng để so sánh xác suất xảy ra một sự kiện giữa hai nhóm khác nhau, thường là nhóm phơi nhiễm và nhóm không phơi nhiễm. Trong nghiên cứu y sinh học và dịch tễ học, RR thường được sử dụng để đánh giá mức độ liên quan giữa một yếu tố nguy cơ và khả năng xảy ra bệnh. RR được tính bằng tỷ số giữa xác suất xảy ra sự kiện trong phạm trù đang xét chia cho xác suất xảy ra sự kiện trong phạm trù cơ sở, theo công thức:
\[ RR=\frac{P(Y=1|X=x_1)}{P(Y=1|X=x_0)}\]
Trong đó:
Diễn giải và ý nghĩa của Relative Risk
Relative Risk được diễn giải như sau: Tỷ lệ sự kiện xảy ra ở phạm trù đang xét gấp RR lần tỷ lệ sự kiện xảy ra ở phạm trù cơ sở.
Odds còn gọi là tỷ lệ cược một cách khác đo lường tỷ lệ xảy ra của một sự kiện là một chỉ số đo lường tỷ lệ tương đối của một sự kiện xảy ra so với không xảy ra.
\[ Odds = \frac{P(Y=1)}{1-P(Y=1)}\]
Odds Ratio (OR) là tỷ số giữa odds của một sự kiện xảy ra trong phạm trù đang xét và odds của sự kiện đó trong phạm trù cơ sở, được tính theo công thức:
\[ OR=\frac{Odds(Y=1|X=x_1)}{Odds(Y=1|X=x_0)}\] Diễn giải và ý nghĩa của Odds ratio
Odds ratio được diễn giải như sau: Odds ở phạm trù đang xét gấp OR lần Odds ở phạm trù cơ sở.
Kiểm định Chi-squared được sử dụng với mục tiêu kiểm tra tính độc lập hai biến định tính trong tổng thể. Ý nghĩa của kiểm định này là giúp xác định xem sự phân bố của một biến có bị ảnh hưởng bởi biến còn lại hay không, từ đó hỗ trợ việc khám phá các mối quan hệ tiềm ẩn giữa các yếu tố định tính trong dữ liệu. Ngược lại, nếu không có bằng chứng đủ mạnh để bác bỏ giả thuyết độc lập, ta coi hai biến là độc lập với nhau. Giả thuyết kiểm định được phát biểu như sau:
\(H_0\): Hai biến định tính độc lập với nhau
\(H_1\): Hai biến định tính có mối quan hệ với nhau.
Kiểm định Anderson-Darling là kiểm định thống kê được sử dụng để đánh giá xem một mẫu dữ liệu có tuân theo một phân phối lý thuyết, cụ thể trong bài là phân phối chuẩn (normality test). Đây là một kiểm định phi tham số, có độ nhạy cao ở cả phần đuôi của phân phối, do đó thường được ưu tiên khi muốn kiểm tra sự phù hợp với phân phối chuẩn một cách nghiêm ngặt hơn so với kiểm định Shapiro-Wilk. Giá trị thống kê càng lớn cho thấy dữ liệu càng lệch khỏi phân phối chuẩn. Mục tiêu của kiểm định này là giúp cho việc lựa chọn phương pháp kiểm định mối quan hệ giữa định tính và định lượng phù hợp hơn, nếu như dữ liệu tuân theo phân phối chuẩn thì sử dụng t.test và nếu không tuân theo phân phối chuẩn thì sử dụng Wilcoxon test. Giả thuyết kiểm định như sau:
\(H_0\): Dữ liệu tuân theo phân phối chuẩn
\(H_1\): Dữ liệu không tuân theo phân phối chuẩn
Kiểm định t (t-test) là một phương pháp thống kê dùng để so sánh trung bình của hai nhóm độc lập nhằm đánh giá xem sự khác biệt giữa chúng có ý nghĩa thống kê hay không. T-test thường được sử dụng trong các tình huống mà biến phản hồi là định lượng, và biến phân nhóm là định tính nhị phân. Một giả định quan trọng của kiểm định t là dữ liệu trong mỗi nhóm phải tuân theo phân phối chuẩn và có phương sai đồng đều (trong trường hợp t-test chuẩn). Khi giả định phân phối chuẩn không thỏa mãn, nên sử dụng kiểm định phi tham số thay thế như Wilcoxon rank-sum test. Giả thuyết kiểm định như sau:
\(H_0\): Trung bình hai nhóm bằng nhau (\(\mu_1=\mu_2\))
\(H_1\): Trung bình hai nhóm khác nhau (\(\mu_1 \neq \mu_2\))
Kiểm định Wilcoxon rank-sum test là một kiểm định phi tham số được sử dụng để so sánh phân phối trung tâm của hai nhóm độc lập khi giả định phân phối chuẩn không được thỏa mãn. Thay vì so sánh trung bình như kiểm định t, Wilcoxon so sánh thứ hạng của các giá trị giữa hai nhóm, do đó phù hợp với dữ liệu định lượng không chuẩn hoặc có ngoại lệ. Đây là một phương pháp mạnh mẽ và phổ biến trong các tình huống thực nghiệm với mẫu nhỏ hoặc dữ liệu lệch.
\(H_0\): Hai nhóm có trung vị giống nhau
\(H_1\): Hai nhóm có trung vị khác nhau
Hồi quy Logistic (Logit) là một mô hình hồi quy nhị phân được sử dụng để phân tích mối quan hệ giữa một biến phụ thuộc dạng nhị phân (binary outcome) và một hoặc nhiều biến độc lập (có thể là định tính hoặc định lượng). Mô hình này đặc biệt hữu ích trong các lĩnh vực như y học, khoa học xã hội và tài chính, nơi mà biến phụ thuộc chỉ có hai trạng thái.
Trong hồi quy Logistic, xác suất xảy ra sự kiện \(Y=1\) được mô hình hóa thông qua hàm logit , là log của tỷ số odds. Hàm liên kết logit đảm bảo xác suất đầu ra luôn nằm trong khoảng \((0,1)\). \[ logit(p)=log(\frac{p}{1-p})=\beta_0 + \beta_1X_1 + \beta_2X_2 +... + \beta_nX_n \] Trong đây thì \(p = P(Y=1|X)\).
Hệ số hồi quy \(\beta_j\) đại diện cho sự thay đổi của log-odds của biến phụ thuộc khi biến độc lập tương ứng thay đổi một đơn vị. Vì \(\beta_j\) không thể diễn giải trực tiếp, chúng ta cần chuyển đổi nó bằng cách lấy lũy thừa \(e^{\beta_j}\) để nhận được Odds Ratio.Do đó, giá trị \(e^{\beta_j}\) cho biết tỷ lệ cược của sự kiện tăng (hoặc giảm) \(e^{\beta_j}\) lần khi biến độc lập \(X_j\) tăng thêm một đơn vị, với giả định các biến độc lập khác được giữ nguyên.
Trong mô hình Probit, xác suất xảy ra sự kiện được liên kết với tổ hợp tuyến tính của các biến độc lập thông qua hàm phân phối tích lũy chuẩn (standard normal cumulative distribution function – CDF): \[ P(Y=1|X)=\Phi(\beta_0 + \beta_1X_1 + \beta_2X_2 +... + \beta_nX_n) \] Mô hình Probit giả định rằng một biến liên tục không thể quan sát được tuân theo phân phối chuẩn. Sự kiện mà ta quan sát xảy ra khi biến tiềm ẩn này vượt qua một ngưỡng cố định. Do đó, hàm Probit liên kết xác suất của kết quả nhị phân với một biến liên tục ẩn, thông qua hàm phân phối tích lũy chuẩn.
Hệ số hồi quy trong mô hình Probit cho biết mức độ thay đổi của Z-score (hay biến tiềm ẩn) khi biến độc lập tương ứng tăng thêm một đơn vị. Cụ thể,\(\beta_j\) đại diện cho sự thay đổi về độ lệch chuẩn trong biến tiềm ẩn, từ đó làm tăng hoặc giảm xác suất sự kiện xảy ra. Vì không có cách diễn giải đơn giản về tỷ lệ cược như Logit, chúng ta thường sử dụng \(\beta_j\) để xác định hướng và mức độ ảnh hưởng của biến độc lập đối với xác suất, thay vì diễn giải trực tiếp dưới dạng “lần”.
AIC (Akaike Information Criterion) là một tiêu chí thống kê dùng để so sánh và lựa chọn mô hình trong trường hợp có nhiều mô hình dự đoán cùng một biến phụ thuộc. AIC đánh giá sự cân bằng giữa độ phù hợp của mô hình (goodness of fit) và độ phức tạp của mô hình (số lượng tham số). Công thức của AIC là: \[ AIC =-2log(L)+2k \] trong đó \(L\) là hàm hợp lý và \(k\) là số tham số ước lượng. Mô hình có AIC nhỏ hơn được ưu tiên chọn, vì nó cho thấy mô hình vừa khớp tốt với dữ liệu, vừa tránh được tình trạng overfitting.
Đường cong ROC là đồ thị thể hiện mối quan hệ giữa tỷ lệ dương tính thật (True Positive Rate) và tỷ lệ dương tính giả (False Positive Rate) tại các ngưỡng phân loại khác nhau. ROC cho phép đánh giá khả năng phân biệt giữa hai lớp của mô hình. Đường cong càng lệch về phía góc trên bên trái thì mô hình càng tốt.
AUC là diện tích dưới đường cong ROC, đại diện cho khả năng phân biệt đúng giữa hai lớp. Giá trị AUC nằm trong khoảng từ 0 đến 1, trong đó AUC = 0.5 tương đương với mô hình ngẫu nhiên, và AUC gần 1 cho thấy mô hình phân loại rất tốt. AUC giúp so sánh hiệu quả giữa nhiều mô hình.
Ma trận nhầm lẫn là bảng 2x2 thể hiện số lượng dự đoán đúng và sai của mô hình, chia theo từng lớp (Positive/Negative). Nó bao gồm: True Positive, True Negative, False Positive và False Negative. Từ đó có thể tính các chỉ số đánh giá như: Độ chính xác (Accuracy), Độ nhạy (Sensitivity), Độ đặc hiệu (Specificity) và F1-score, giúp hiểu rõ hiệu quả mô hình trên từng mặt.
df$Stroke <- factor(df$Stroke,levels = c(0,1),labels = c("No","Yes"))
tab_result <- tabyl(df$Stroke)
colnames(tab_result) <- c("Tình trạng đột quỵ", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ của biến Stroke", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;")| Tình trạng đột quỵ | Tần số | Tỷ lệ (%) |
|---|---|---|
| No | 7022 | 0.7022 |
| Yes | 2978 | 0.2978 |
plot_data <- df %>%
count(Stroke) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Stroke), y = percentage, fill = Stroke)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ bệnh nhân bị đột quỵ và không bị đột quỵ",
x = "Bị Đột Quỵ",
y = "Tỷ lệ",
fill = "Bị Đột Quỵ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Dữ liệu cho thấy có sự mất cân bằng giữa hai nhóm cụ thể thì bệnh nhân chưa từng bị đột quỵ chiếm 70.22%, trong khi nhóm đã bị đột quỵ là 29.78% cho thấy rằng số bệnh nhân bị đột quỵ chỉ gần một nửa số bệnh nhân không bị đột quỵ . Mặc dù đây là một bộ dữ liệu không cân bằng, nhưng số lượng ca bị đột quỵ là 2,978 vẫn đủ lớn để kết quả phân tích có ý nghĩa thống kê.
tab_summary <- df %>%
summarise(
Min = min(Age, na.rm = TRUE),
Q1 = quantile(Age, 0.25, na.rm = TRUE),
Median = median(Age, na.rm = TRUE),
Mean = mean(Age, na.rm = TRUE),
Q3 = quantile(Age, 0.75, na.rm = TRUE),
Max = max(Age, na.rm = TRUE),
SD = sd(Age, na.rm = TRUE)
)
# Hiển thị bảng thống kê
knitr::kable(tab_summary, caption = "Bảng mô tả thống kê biến độ tuổi", align = "c")| Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|
| 27.70656 | 63.12857 | 69.79604 | 69.75785 | 76.40288 | 99.41745 | 9.869468 |
ggplot(df, aes(x = Age)) +
geom_histogram(aes(y = after_stat(density)), binwidth = 1, fill = "skyblue", color = "white", alpha = 0.7) +
geom_density(color = "blue", linewidth = 1) +
labs(
title = "Phân phối tuổi của bệnh nhân",
x = "Tuổi (năm)",
y = "Mật độ"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))##
## Anderson-Darling normality test
##
## data: df$Age
## A = 0.29563, p-value = 0.5952
Kết quả phân tích thống kê mô tả cho thấy độ tuổi của bệnh nhân có phân phối gần đối xứng, với giá trị trung vị (69.79) và trung bình (69.76) gần như tương đương. Độ lệch chuẩn (9.87) và khoảng tứ phân vị là 13.27 tương đối nhỏ, cho thấy phần lớn dữ liệu tuổi tập trung chặt chẽ quanh giá trị trung bình. Mặc dù độ biến thiên khá rộng từ 27.71 đến 99.42, điều này không làm sai lệch đáng kể phân phối tổng thể. Hơn nữa, với kết quả kiểm định Anderson-Darling cho p-value là 0.5952>0.05 chúng ta có thể kết luẩn rằng Age tuân theo phân phối chuẩn. Vì thế sẽ dùng kiểm định t đối với Age
ggplot(df, aes(y = Age)) +
geom_boxplot(fill = "lightgreen", color = "darkgreen") +
labs(
title = "Boxplot của tuổi",
y = "Tuổi (năm)"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))count_outliers <- function(x, side = c("both", "upper", "lower")) {
side <- match.arg(side) # Kiểm tra đối số hợp lệ
# Loại bỏ NA
x <- x[!is.na(x)]
# Tính IQR
Q1 <- quantile(x, 0.25)
Q3 <- quantile(x, 0.75)
IQR_value <- Q3 - Q1
# Ngưỡng dưới và trên
lower_bound <- Q1 - 1.5 * IQR_value
upper_bound <- Q3 + 1.5 * IQR_value
# Đếm số lượng theo hướng
if (side == "lower") {
return(sum(x < lower_bound))
} else if (side == "upper") {
return(sum(x > upper_bound))
} else if (side == "both") {
return(sum(x < lower_bound | x > upper_bound))
}
}
cat("Giá trị ngoại lai phía trên: ", count_outliers(df$Age,"upper"),"\n")## Giá trị ngoại lai phía trên: 23
## Giá trị ngoại lai phía dưới: 29
Ở đây thì cho thấy có 23 giá trị ngoại lai ở phía trên và 29 giá trị ngoại lai ở phía dưới, nhưng các giá trị này không làm thay đổi đáng kể phân phối tổng thể. Sự hiện diện của chúng cho thấy có một số ít bệnh nhân rất trẻ cụ thế là dưới 40 hoặc rất già cụ thế là hơn 95 tuổi xuất hiện trong mẫu, tuy nhiên kết quả kiểm định chuẩn vẫn cho phép chúng ta coi biến Age tuân theo phân phối chuẩn.
df$Gender <- factor(df$Gender,levels = c("Female","Male"))
tab_result <- tabyl(df$Gender)
colnames(tab_result) <- c("Giới tính", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ giới tính ", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Giới tính | Tần số | Tỷ lệ (%) |
|---|---|---|
| Female | 5037 | 0.5037 |
| Male | 4963 | 0.4963 |
plot_data <- df %>%
count(Gender) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Gender), y = percentage, fill = Gender)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ giới tính bệnh nhân ",
x = "Giới tính",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Kết quả phân tích cho thấy sự cân bằng gần như hoàn hảo về giới tính trong bộ dữ liệu, với 50.37% là nữ và 49.63% là nam. Tỷ lệ này rất lý tưởng để tiến hành phân tích, đảm bảo rằng mọi kết quả liên quan đến giới tính sẽ không bị sai lệch do sự mất cân bằng trong mẫu.
df$SES <- factor(df$SES,levels = c("Low","Medium","High"))
tab_result <- tabyl(df$SES)
colnames(tab_result) <- c("Địa vị", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ địa vị xã hội ", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Địa vị | Tần số | Tỷ lệ (%) |
|---|---|---|
| Low | 2870 | 0.2870 |
| Medium | 5106 | 0.5106 |
| High | 2024 | 0.2024 |
plot_data <- df %>%
count(SES) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(SES), y = percentage, fill = SES)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ địa vị xã hội của bệnh nhân ",
x = "Địa vị",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Kết quả cho thấy hơn một nửa bệnh nhân thuộc nhóm có địa vị xã hội Trung bình (51.06%). Trong khi đó, nhóm Thấp và Cao lần lượt chiếm 28.70% và 20.24%. Sự phân bố này cho phép chúng ta khám phá mối liên hệ tiềm tàng giữa tình trạng kinh tế xã hội và nguy cơ đột quỵ, đặc biệt là so sánh nhóm có địa vị xã hội thấp hơn với các nhóm còn lại.
df$Hypertension <- factor(df$Hypertension,levels = c(0,1),labels = c("No","Yes"))
tab_result <- tabyl(df$Hypertension)
colnames(tab_result) <- c("Tình trạng", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ cao huyết áp ", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng | Tần số | Tỷ lệ (%) |
|---|---|---|
| No | 3942 | 0.3942 |
| Yes | 6058 | 0.6058 |
plot_data <- df %>%
count(Hypertension) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Hypertension), y = percentage, fill = Hypertension)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ cao huyết áp của bệnh nhân ",
x = "Tình trạng",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Kết quả phân tích cho thấy phần lớn bệnh nhân trong mẫu nghiên cứu có tiền sử cao huyết áp, chiếm 60.58%. Đây là một phát hiện quan trọng, cho thấy huyết áp cao là một yếu tố phổ biến và có thể đóng vai trò then chốt trong việc giải thích mối liên hệ với đột quỵ. Tỷ lệ này cũng giúp củng cố giả thuyết rằng bệnh cao huyết áp là một yếu tố nguy cơ đáng kể trong quần thể này.
df$Heart_Disease <- factor(df$Heart_Disease,levels = c(0,1),labels = c("No","Yes"))
tab_result <- tabyl(df$Heart_Disease)
colnames(tab_result) <- c("Tình trạng", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ bệnh tim ", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng | Tần số | Tỷ lệ (%) |
|---|---|---|
| No | 6972 | 0.6972 |
| Yes | 3028 | 0.3028 |
plot_data <- df %>%
count(Heart_Disease) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Heart_Disease), y = percentage, fill = Heart_Disease)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ bệnh tim của bệnh nhân ",
x = "Tình trạng",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Kết quả cho thấy có 30.28% bệnh nhân trong mẫu nghiên cứu mắc bệnh tim, một tỷ lệ gần tương đương với tỷ lệ bệnh nhân bị đột quỵ (29.78%). Điều này gợi mở rằng có thể có một mối liên hệ chặt chẽ giữa hai tình trạng này. Tỷ lệ cao của cả bệnh tim và đột quỵ trong cùng một quần thể củng cố giả thuyết rằng bệnh tim mạch là một yếu tố nguy cơ đáng kể gây ra đột quỵ.
tab_summary <- df %>%
summarise(
Min = min(BMI, na.rm = TRUE),
Q1 = quantile(BMI, 0.25, na.rm = TRUE),
Median = median(BMI, na.rm = TRUE),
Mean = mean(BMI, na.rm = TRUE),
Q3 = quantile(BMI, 0.75, na.rm = TRUE),
Max = max(BMI, na.rm = TRUE),
SD = sd(BMI, na.rm = TRUE)
)
# Hiển thị bảng thống kê
knitr::kable(tab_summary, caption = "Bảng mô tả thống kê biến độ chỉ số khối", align = "c")| Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|
| 15.03799 | 24.66079 | 28.06693 | 28.04225 | 31.39017 | 47.49596 | 4.901424 |
ggplot(df, aes(x = BMI)) +
geom_histogram(aes(y = after_stat(density)), binwidth = 1, fill = "blue", color = "white", alpha = 0.7) +
geom_density(color = "green", linewidth = 1) +
labs(
title = "Phân phối chỉ số khối của bệnh nhân",
x = "Tuổi (năm)",
y = "Mật độ"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))##
## Anderson-Darling normality test
##
## data: df$BMI
## A = 0.81573, p-value = 0.03504
Phân tích cho thấy chỉ số BMI có giá trị trung bình là 28.04 và trung vị là 28.07 gần bằng nhau, nhưng kết quả kiểm định Anderson-Darling lại cho p-value là 0.03504<0.05, bác bỏ giả thuyết phân phối chuẩn. Với khoảng tứ phân vị 6.73 tương đối rộng và độ lệch chuẩn là 4.90, dữ liệu BMI có vẻ phân bố không hoàn toàn đối xứng. Do không tuân theo phân phối chuẩn, các phân tích sau sẽ sử dụng các kiểm định phi tham số, chẳng hạn như kiểm định Wilcoxon, để so sánh BMI giữa các nhóm.
ggplot(df, aes(y = BMI)) +
geom_boxplot(fill = "lightgreen", color = "darkgreen") +
labs(
title = "Boxplot của chỉ số khối",
y = "BMI "
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))cat(" Giá trị ngoại lai phía trên: ",count_outliers(df$BMI,side = "upper"),"\n",
"Giá trị ngoại lai phía dưới: ",count_outliers(df$BMI,side = "lower"))## Giá trị ngoại lai phía trên: 25
## Giá trị ngoại lai phía dưới: 0
Boxplot cho thấy có 25 giá trị ngoại lai ở phía trên, đại diện cho những bệnh nhân có chỉ số BMI rất cao, nằm ngoài phạm vi bình thường. Không có sự hiện diện của các giá trị ngoại lai ở phía dưới cho thấy không có bệnh nhân nào có chỉ số BMI quá thấp bất thường.
age_summary <- df %>%
summarise(
Min = min(Avg_Glucose, na.rm = TRUE),
Q1 = quantile(Avg_Glucose, 0.25, na.rm = TRUE),
Median = median(Avg_Glucose, na.rm = TRUE),
Mean = mean(Avg_Glucose, na.rm = TRUE),
Q3 = quantile(Avg_Glucose, 0.75, na.rm = TRUE),
Max = max(Avg_Glucose, na.rm = TRUE),
SD = sd(Avg_Glucose, na.rm = TRUE)
)
# Hiển thị bảng thống kê
knitr::kable(age_summary, caption = "Bảng mô tả thống kê đường huyết trung bình", align = "c")| Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|
| 45.56914 | 98.18835 | 109.0222 | 109.1159 | 120.3412 | 176.1807 | 16.42114 |
ggplot(df, aes(x = Avg_Glucose)) +
geom_histogram(aes(y = after_stat(density)), binwidth = 1, fill = "blue", color = "white", alpha = 0.7) +
geom_density(color = "green", linewidth = 1) +
labs(
title = "Phân phối đường huyết trung bình của bệnh nhân",
x = "Tuổi (năm)",
y = "Mật độ"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))##
## Anderson-Darling normality test
##
## data: df$Avg_Glucose
## A = 0.24306, p-value = 0.767
Phân tích cho thấy chỉ số đường huyết trung bình có phân phối đối xứng, với giá trị trung bình 109.12 và trung vị 109.02 rất gần nhau. Với độ lệch chuẩn 16.42 và khoảng tứ phân vị 22.15 tương đối nhỏ, phần lớn dữ liệu tập trung chặt chẽ quanh giá trị trung bình. Hơn nữa, kết quả kiểm định Anderson-Darling cho p-value là 0.767>0.05, cho thấy chúng ta có đủ cơ sở để kết luận rằng biến Avg_Glucose tuân theo phân phối chuẩn.
ggplot(df, aes(y = Avg_Glucose)) +
geom_boxplot(fill = "lightgreen", color = "darkgreen") +
labs(
title = "Boxplot của đường huyết trung bình",
y = "Avg_Glucose "
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))cat(" Giá trị ngoại lai phía trên: ",count_outliers(df$Avg_Glucose,side = "upper"),"\n",
"Giá trị ngoại lai phía dưới: ",count_outliers(df$Avg_Glucose,side = "lower"))## Giá trị ngoại lai phía trên: 28
## Giá trị ngoại lai phía dưới: 41
Biểu đồ boxplot cho thấy chỉ số đường huyết trung bình có 28 giá trị ngoại lai ở phía trên và 41 giá trị ngoại lai ở phía dưới. Sự hiện diện của những giá trị này cho thấy có một số lượng đáng kể bệnh nhân có chỉ số đường huyết bất thường, bao gồm cả những người có đường huyết rất thấp hoặc rất cao. Đường huyết bất thường là một dấu hiệu cảnh báo sức khỏe nghiêm trọng. Đường huyết quá cao là nguyên nhân chính gây ra bệnh tiểu đường và các biến chứng tim mạch. Ngược lại, đường huyết quá thấp có thể dẫn đến các vấn đề nghiêm trọng như chóng mặt, ngất xỉu, và thậm chí là hôn mê.
df$Diabetes <- factor(df$Diabetes,levels = c(0,1),labels = c("No","Yes"))
tab_result <- tabyl(df$Diabetes)
colnames(tab_result) <- c("Tình trạng", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng tiểu đường", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng | Tần số | Tỷ lệ (%) |
|---|---|---|
| No | 8040 | 0.804 |
| Yes | 1960 | 0.196 |
plot_data <- df %>%
count(Diabetes) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Diabetes), y = percentage, fill = Diabetes)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ tình trạng tiểu đường của bệnh nhân ",
x = "Tình trạng",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Dựa trên phân tích, phần lớn bệnh nhân trong mẫu nghiên cứu không mắc bệnh tiểu đường, chiếm 80.4%. Tuy nhiên, tỷ lệ bệnh nhân có tiểu đường cũng chiếm một phần năm trong mẫu cụ thế là 19.6%. Tỷ lệ này cho thấy tiểu đường là một vấn đề sức khỏe phổ biến trong nhóm mẫu, củng cố giả thuyết rằng đây có thể là một trong những yếu tố nguy cơ quan trọng cần được xem xét trong mô hình dự đoán đột quỵ.
df$Smoking_Status <- factor(df$Smoking_Status,levels = c("Never","Current","Former"))
tab_result <- tabyl(df$Smoking_Status)
colnames(tab_result) <- c("Tình trạng", "Tần số", "Tỷ lệ (%)")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng hút thuốc", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng | Tần số | Tỷ lệ (%) |
|---|---|---|
| Never | 5951 | 0.5951 |
| Current | 2062 | 0.2062 |
| Former | 1987 | 0.1987 |
plot_data <- df %>%
count(Smoking_Status) %>%
mutate(
percentage = n / sum(n),
label = scales::percent(percentage,accuracy = 0.001)
)
ggplot(plot_data, aes(x = as.factor(Smoking_Status), y = percentage, fill = Smoking_Status)) +
geom_bar(stat = "identity") +
geom_text(aes(label = label), vjust = 1, size = 5) +
labs(
title = "Tỷ lệ tình trạng hút thuốc của bệnh nhân ",
x = "Tình trạng",
y = "Tỷ lệ"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "none"
)Phân tích cho thấy phần lớn bệnh nhân trong mẫu nghiên cứu chưa bao giờ hút thuốc, chiếm tỷ lệ cao nhất là 59.51%. Trong khi đó, nhóm đang hút thuốc và đã từng hút thuốc có tỷ lệ gần tương đương nhau, lần lượt là 20.62% và 19.87%. Sự phân bố này cho phép chúng ta so sánh rõ ràng nguy cơ đột quỵ giữa ba nhóm thói quen hút thuốc khác nhau.
Sau khi khám phá đặc điểm của từng biến riêng lẻ, chúng ta sẽ đi sâu vào mối quan hệ giữa các biến độc lập và biến phụ thuộc (Stroke). Phần phân tích này nhằm mục đích xác định các yếu tố nguy cơ tiềm năng, lựa chọn những biến phù hợp cho việc xây dựng các mô hình dự đoán.
table_summary <- df %>%
group_by(Stroke) %>%
summarise(
Min = min(Age, na.rm = TRUE),
Q1 = quantile(Age, 0.25, na.rm = TRUE),
Median = median(Age, na.rm = TRUE),
Mean = mean(Age, na.rm = TRUE),
Q3 = quantile(Age, 0.75, na.rm = TRUE),
Max = max(Age, na.rm = TRUE),
SD = sd(Age, na.rm = TRUE)
)
# Hiển thị bảng đẹp
kable(table_summary,
caption = "Bảng mô tả thống kê tuổi theo tình trạng đột quỵ",
align = "c",
digits = 2)%>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(table_summary), bold = TRUE, extra_css = "text-align: center;") | Stroke | Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|---|
| No | 27.71 | 61.22 | 67.60 | 67.43 | 73.70 | 99.04 | 9.27 |
| Yes | 44.47 | 69.07 | 75.28 | 75.25 | 81.53 | 99.42 | 9.04 |
Dựa trên bảng thống kê, có sự khác biệt rõ rệt về độ tuổi trung bình giữa hai nhóm. Bệnh nhân bị đột quỵ có độ tuổi trung bình 75.25 cao hơn so với nhóm không bị đột quỵ 67.43. Cả hai nhóm đều có phân phối độ tuổi tương đối đối xứng, với giá trị trung vị gần bằng trung bình. Điều này cho thấy tuổi tác là một yếu tố có mối liên hệ chặt chẽ với nguy cơ đột quỵ, củng cố giả thuyết rằng tuổi cao làm tăng nguy cơ mắc bệnh.
ggplot(df, aes(x = Stroke, y = Age, fill = Stroke)) +
geom_boxplot(outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
labs(
title = "Biểu đồ Boxplot tuổi theo tình trạng đột quỵ",
x = "Tình trạng đột quỵ ",
y = "Tuổi"
) +
theme_minimal() +
scale_fill_discrete(name = "Đột quỵ")mean_line <- df %>%
group_by(Stroke) %>%
summarise(mean_line = mean(Age, na.rm = TRUE)) %>%
mutate(Stroke = as.factor(Stroke)) # đảm bảo khớp kiểu dữ liệu
ggplot(df, aes(x = Age, color = as.factor(Stroke), fill = as.factor(Stroke))) +
geom_density(alpha = 0.5) +
geom_vline(data = mean_line,
aes(xintercept = mean_line, color = Stroke),
linetype = "dashed", size = 1) +
labs(
title = "Biểu đồ mật độ của tuổi theo tình trạng đột quỵ",
x = "Tuổi",
fill = "Đột quỵ",
color = "Đột quỵ"
) +
theme_minimal()## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
df %>%
group_by(Stroke) %>%
summarise(
ad_statistic = ad.test(Age)$statistic,
p_value = ad.test(Age)$p.value
)## # A tibble: 2 × 3
## Stroke ad_statistic p_value
## <fct> <dbl> <dbl>
## 1 No 0.497 0.213
## 2 Yes 0.682 0.0750
##
## Welch Two Sample t-test
##
## data: Age by Stroke
## t = -39.291, df = 5740.5, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group No and group Yes is not equal to 0
## 95 percent confidence interval:
## -8.213907 -7.433220
## sample estimates:
## mean in group No mean in group Yes
## 67.42799 75.25155
Kết quả kiểm định t cho thấy một sự khác biệt có ý nghĩa thống kê về độ tuổi trung bình giữa nhóm bệnh nhân bị đột quỵ và không bị đột quỵ. Cụ thể, với p-value rất nhỏ (<2.2e−16), chúng ta có thể bác bỏ giả thuyết không có sự khác biệt. Khoảng tin cậy 95% ([−8.21,−7.43]) không chứa số 0, xác nhận rằng tuổi trung bình của nhóm đột quỵ (75.25) cao hơn đáng kể so với nhóm không đột quỵ (67.43). Phân tích boxplot cho thấy có giá trị ngoại lai ở cả hai đầu của nhóm không đột quỵ, nhưng chỉ có ở phía dưới đối với nhóm đột quỵ. Điều này cho thấy có một số ít bệnh nhân rất trẻ bị đột quỵ, nhưng đa số bệnh nhân đột quỵ lại ở độ tuổi cao.
tab <- table(df$Gender,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Giới tính")
kable(tab_result, caption = "Bảng tần số và tỷ lệ giới tính theo tình trạng đột quỵ", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Giới tính | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| Female | 3548 | 1489 | 70.44% | 29.56% |
| Male | 3474 | 1489 | 70.00% | 30.00% |
df_percent <- df %>%
group_by(Stroke, Smoking_Status) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Smoking_Status) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = Smoking_Status, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ bị đột quỵ theo tình trạng hút thuốc",
y = "Tỷ lệ (%)", x = "Hút thuốc", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## Female 1.00000 NA NA
## Male 1.01491 0.9556228 1.077876
## two-sided
## midp.exact fisher.exact chi.square
## Female NA NA NA
## Male 0.6299362 0.6305196 0.6298623
## odds ratio with 95% C.I.
## estimate lower upper
## Female 1.000000 NA NA
## Male 1.021299 0.9373929 1.112752
## two-sided
## midp.exact fisher.exact chi.square
## Female NA NA NA
## Male 0.6299362 0.6305196 0.6298623
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab
## X-squared = 0.21165, df = 1, p-value = 0.6455
Kết quả phân tích cho thấy không có sự khác biệt nào về tỷ lệ đột quỵ giữa nam và nữ. Cụ thể, tỷ lệ đột quỵ ở nam giới là 30.00%, chỉ cao hơn một chút so với nữ giới là 29.56%. Tương ứng, Relative Risk (RR) cho thấy nguy cơ đột quỵ ở nam giới cao hơn nữ giới khoảng 1.5%, nhưng giá trị này không có ý nghĩa thống kê. Điều này được xác nhận bởi cả kiểm định Chi-squared và các kiểm định khác, với p-value >0.6 đều lớn hơn nhiều so với ngưỡng 0.05. Tương tự, Odds Ratio (OR) cũng cho thấy tỷ lệ cược đột quỵ ở nam giới cao hơn 2.1% so với nữ, nhưng khoảng tin cậy của OR [0.937,1.113] chứa số 1, khẳng định sự khác biệt này không có ý nghĩa thống kê.
tab <- table(df$SES,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Địa vị")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng đột quỵ theo địa vị xã hội", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Địa vị | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| Low | 2071 | 799 | 72.16% | 27.84% |
| Medium | 3543 | 1563 | 69.39% | 30.61% |
| High | 1408 | 616 | 69.57% | 30.43% |
df_percent <- df %>%
group_by(Stroke, SES) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(SES) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = SES, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ bị đột quỵ theo địa vị xã hội",
y = "Tỷ lệ (%)", x = "Địa vị", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## Low 1.000000 NA NA
## Medium 1.099546 1.023227 1.181557
## High 1.093214 1.000762 1.194207
## two-sided
## midp.exact fisher.exact chi.square
## Low NA NA NA
## Medium 0.009133705 0.009854671 0.009271768
## High 0.048951886 0.050848363 0.048602625
## odds ratio with 95% C.I.
## estimate lower upper
## Low 1.000000 NA NA
## Medium 1.143370 1.033766 1.265201
## High 1.133997 1.000563 1.284896
## two-sided
## midp.exact fisher.exact chi.square
## Low NA NA NA
## Medium 0.009133705 0.009854671 0.009271768
## High 0.048951886 0.050848363 0.048602625
##
## Pearson's Chi-squared test
##
## data: tab
## X-squared = 7.2681, df = 2, p-value = 0.02641
Kết quả phân tích cho thấy có sự khác biệt có ý nghĩa thống kê về tỷ lệ đột quỵ giữa các nhóm địa vị xã hội. Cụ thể, kiểm định Chi-squared có p-value = 0.02641, nhỏ hơn ngưỡng 0.05, cho phép chúng ta bác bỏ giả thuyết không có mối liên hệ. Phân tích RR và OR cho thấy nguy cơ và tỷ lệ cược đột quỵ của nhóm địa vị Trung bình và Cao đều cao hơn so với nhóm Thấp. Cụ thể, nguy cơ đột quỵ ở nhóm Trung bình cao hơn 1.1 lần (RR = 1.099) và nhóm Cao cao hơn 1.09 lần (RR = 1.093) so với nhóm Thấp. Tương tự, tỷ số chênh (OR) của hai nhóm này cũng cao hơn đáng kể so với nhóm tham chiếu. Mặc dù sự khác biệt này có ý nghĩa thống kê, nhưng nó không cho thấy một xu hướng tăng tuyến tính, khi mà nhóm có địa vị cao không có nguy cơ lớn hơn nhóm trung bình.
tab <- table(df$Hypertension,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Cao huyết áp")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng đột quỵ theo tình trạng cao huyết áp",
align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Cao huyết áp | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| No | 3637 | 305 | 92.26% | 7.74% |
| Yes | 3385 | 2673 | 55.88% | 44.12% |
df_percent <- df %>%
group_by(Stroke, Hypertension) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Hypertension) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = Hypertension, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ đột quỵ theo tình trạng cao huyết áp ",
y = "Tỷ lệ (%)", x = "Tình trạng", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## No 1.000000 NA NA
## Yes 5.702778 5.101287 6.375191
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 0 0
## odds ratio with 95% C.I.
## estimate lower upper
## No 1.000000 NA NA
## Yes 9.410503 8.297965 10.70661
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 0 0
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab
## X-squared = 1510.2, df = 1, p-value < 2.2e-16
Kết quả cho thấy mối liên hệ mạnh mẽ và có ý nghĩa thống kê giữa tình trạng cao huyết áp và đột quỵ. Cụ thể, kiểm định Chi-squared có p-value rất nhỏ (<2.2e−16), cho phép chúng ta bác bỏ giả thuyết không và khẳng định có mối liên hệ. Tỷ lệ đột quỵ ở nhóm có cao huyết áp là 44.12%, cao hơn rất nhiều so với nhóm không có cao huyết áp chỉ 7.74%. Phân tích Relative Risk (RR = 5.70) cho thấy nguy cơ đột quỵ ở bệnh nhân có cao huyết áp cao gấp 5.7 lần so với nhóm không có. Tương tự, Odds Ratio (OR = 9.41) khẳng định tỷ lệ cược đột quỵ ở nhóm có cao huyết áp cao gấp 9.4 lần. Cả hai chỉ số này đều có khoảng tin cậy không chứa số 1, cùng với p-value rất nhỏ, xác nhận rằng cao huyết áp là một trong những yếu tố nguy cơ quan trọng nhất gây ra đột quỵ trong bộ dữ liệu này.
tab <- table(df$Heart_Disease,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Tình trạng")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng đột quỵ theo tình trạng bệnh tim", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| No | 5472 | 1500 | 78.49% | 21.51% |
| Yes | 1550 | 1478 | 51.19% | 48.81% |
df_percent <- df %>%
group_by(Stroke, Heart_Disease) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Heart_Disease) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = Heart_Disease, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ tình trạng đột quỵ theo tình trạng bệnh tim",
y = "Tỷ lệ (%)", x = "Tình trạng", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## No 1.00000 NA NA
## Yes 2.26874 2.141332 2.403728
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 3.731689e-159 1.325279e-165
## odds ratio with 95% C.I.
## estimate lower upper
## No 1.000000 NA NA
## Yes 3.477951 3.17468 3.811347
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 3.731689e-159 1.325279e-165
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab
## X-squared = 750.91, df = 1, p-value < 2.2e-16
Kết quả phân tích cho thấy một mối liên hệ mạnh mẽ và có ý nghĩa thống kê giữa việc mắc bệnh tim và nguy cơ đột quỵ. Kiểm định Chi-squared có p-value rất nhỏ (<2.2e−16), cho phép chúng ta bác bỏ giả thuyết không và khẳng định có mối liên hệ như phân tích ở đơn biến. Tỷ lệ đột quỵ ở bệnh nhân có bệnh tim là 48.81%, cao hơn gấp đôi so với nhóm không có bệnh tim chỉ 21.51%. Phân tích Relative Risk (RR = 2.27) cho thấy nguy cơ đột quỵ ở bệnh nhân có bệnh tim cao gấp 2.27 lần so với nhóm không mắc. Tương tự, Odds Ratio (OR = 3.48) cho thấy tỷ lệ cược đột quỵ của nhóm có bệnh tim cao gấp 3.48 lần. Cả hai chỉ số này đều có khoảng tin cậy không chứa số 1 và p-value cực nhỏ, khẳng định rằng bệnh tim là một yếu tố nguy cơ rất đáng kể đối với đột quỵ.
table_summary <- df %>%
group_by(Stroke) %>%
summarise(
Min = min(BMI, na.rm = TRUE),
Q1 = quantile(BMI, 0.25, na.rm = TRUE),
Median = median(BMI, na.rm = TRUE),
Mean = mean(BMI, na.rm = TRUE),
Q3 = quantile(BMI, 0.75, na.rm = TRUE),
Max = max(BMI, na.rm = TRUE),
SD = sd(BMI, na.rm = TRUE)
)
# Hiển thị bảng đẹp
kable(table_summary,
caption = "Bảng mô tả thống kê chỉ số khối theo tình trạng đột quỵ",
align = "c",
digits = 2)%>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(table_summary), bold = TRUE, extra_css = "text-align: center;") | Stroke | Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|---|
| No | 15.04 | 24.47 | 27.79 | 27.78 | 31.06 | 47.50 | 4.86 |
| Yes | 15.22 | 25.21 | 28.80 | 28.67 | 32.03 | 45.97 | 4.93 |
Dựa trên bảng thống kê, có sự khác biệt rõ ràng về chỉ số BMI trung bình giữa hai nhóm. Nhóm bệnh nhân bị đột quỵ (Yes) có BMI trung bình (28.67) cao hơn một chút so với nhóm không bị đột quỵ (No) (27.78). Cả hai nhóm đều có giá trị trung bình và trung vị gần bằng nhau, cho thấy phân phối không bị lệch nhiều. Tuy nhiên, chỉ số BMI của nhóm đột quỵ có vẻ cao hơn, gợi ý rằng béo phì có thể là một yếu tố nguy cơ.
ggplot(df, aes(x = Stroke, y = BMI, fill = Stroke)) +
geom_boxplot(outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
labs(
title = "Biểu đồ Boxplot chỉ số khối theo tình trạng đột quỵ",
x = "Tình trạng đột quỵ ",
y = "Chỉ số khối"
) +
theme_minimal() +
scale_fill_discrete(name = "Đột quỵ")median_line <- df %>%
group_by(Stroke) %>%
summarise(median_line = median(BMI, na.rm = TRUE)) %>%
mutate(Stroke = as.factor(Stroke)) # đảm bảo khớp kiểu dữ liệu
ggplot(df, aes(x = BMI, color = as.factor(Stroke), fill = as.factor(Stroke))) +
geom_density(alpha = 0.5) +
geom_vline(data = median_line,
aes(xintercept = median_line, color = Stroke),
linetype = "dashed", size = 1) +
labs(
title = "Biểu đồ mật độ của chỉ số khối theo tình trạng đột quỵ",
x = "Chỉ số khối",
fill = "Đột quỵ",
color = "Đột quỵ"
) +
theme_minimal()df %>%
group_by(Stroke) %>%
summarise(
ad_statistic = ad.test(BMI)$statistic,
p_value = ad.test(BMI)$p.value
)## # A tibble: 2 × 3
## Stroke ad_statistic p_value
## <fct> <dbl> <dbl>
## 1 No 0.520 0.186
## 2 Yes 0.596 0.120
##
## Welch Two Sample t-test
##
## data: BMI by Stroke
## t = -8.3041, df = 5536.1, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group No and group Yes is not equal to 0
## 95 percent confidence interval:
## -1.1029266 -0.6816343
## sample estimates:
## mean in group No mean in group Yes
## 27.77653 28.66881
Kết quả kiểm định Wilcoxon cho thấy sự khác biệt có ý nghĩa thống kê về chỉ số BMI giữa hai nhóm bệnh nhân. Với p-value rất nhỏ (9.546e−16), chúng ta có thể bác bỏ giả thuyết không và khẳng định có sự khác biệt. Điều này xác nhận rằng chỉ số BMI của nhóm đột quỵ cao hơn đáng kể so với nhóm không đột quỵ. Phân tích boxplot cho thấy cả hai nhóm đều có giá trị ngoại lai phía trên, cho thấy cả hai nhóm đều có những cá nhân béo phì. Tuy nhiên, sự khác biệt về BMI trung vị vẫn đủ lớn để khẳng định BMI là một yếu tố nguy cơ ảnh hưởng đến đột quỵ.
table_summary <- df %>%
group_by(Stroke) %>%
summarise(
Min = min(Avg_Glucose, na.rm = TRUE),
Q1 = quantile(Avg_Glucose, 0.25, na.rm = TRUE),
Median = median(Avg_Glucose, na.rm = TRUE),
Mean = mean(Avg_Glucose, na.rm = TRUE),
Q3 = quantile(Avg_Glucose, 0.75, na.rm = TRUE),
Max = max(Avg_Glucose, na.rm = TRUE),
SD = sd(Avg_Glucose, na.rm = TRUE)
)
# Hiển thị bảng đẹp
kable(table_summary,
caption = "Bảng mô tả thống kê đường huyết trung bình theo tình trạng đột quỵ",
align = "c",
digits = 2)%>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE, # Bảng chiếm toàn bộ chiều ngang
font_size = 14,
position = "center" # Căn giữa bảng
) %>%
column_spec(1:ncol(table_summary), bold = TRUE, extra_css = "text-align: center;") | Stroke | Min | Q1 | Median | Mean | Q3 | Max | SD |
|---|---|---|---|---|---|---|---|
| No | 45.57 | 95.91 | 106.80 | 106.76 | 117.57 | 161.03 | 16.04 |
| Yes | 61.03 | 103.69 | 114.82 | 114.68 | 125.69 | 176.18 | 15.97 |
Dựa trên bảng thống kê, có sự khác biệt rõ rệt về mức đường huyết trung bình giữa hai nhóm. Bệnh nhân bị đột quỵ có đường huyết trung bình (114.68) và trung vị (114.82) cao hơn nhiều so với nhóm không bị đột quỵ (106.76 và 106.80). Độ lệch chuẩn của cả hai nhóm đều tương đối thấp, cho thấy dữ liệu tập trung chặt chẽ quanh giá trị trung bình. Sự khác biệt này gợi ý rằng đường huyết cao là một yếu tố nguy cơ đáng kể của đột quỵ.
ggplot(df, aes(x = Stroke, y = Avg_Glucose, fill = Stroke)) +
geom_boxplot(outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
labs(
title = "Biểu đồ Boxplot đường huyết trung bình theo tình trạng đột quỵ",
x = "Tình trạng đột quỵ ",
y = "Đường huyết trung bình"
) +
theme_minimal() +
scale_fill_discrete(name = "Đột quỵ")mean_line <- df %>%
group_by(Stroke) %>%
summarise(mean_line = mean(Avg_Glucose, na.rm = TRUE)) %>%
mutate(Stroke = as.factor(Stroke))
ggplot(df, aes(x = Avg_Glucose, color = as.factor(Stroke), fill = as.factor(Stroke))) +
geom_density(alpha = 0.5) +
geom_vline(data = mean_line,
aes(xintercept = mean_line, color = Stroke),
linetype = "dashed", size = 1) +
labs(
title = "Biểu đồ mật độ đường huyết trung bình theo tình trạng đột quỵ",
x = "Tuổi",
fill = "Đột quỵ",
color = "Đột quỵ"
) +
theme_minimal()df %>%
group_by(Stroke) %>%
summarise(
ad_statistic = ad.test(Avg_Glucose)$statistic,
p_value = ad.test(Avg_Glucose)$p.value
)## # A tibble: 2 × 3
## Stroke ad_statistic p_value
## <fct> <dbl> <dbl>
## 1 No 0.182 0.912
## 2 Yes 0.487 0.224
##
## Welch Two Sample t-test
##
## data: Avg_Glucose by Stroke
## t = -22.658, df = 5632.3, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group No and group Yes is not equal to 0
## 95 percent confidence interval:
## -8.607533 -7.236683
## sample estimates:
## mean in group No mean in group Yes
## 106.7567 114.6788
Kết quả kiểm định t cho thấy sự khác biệt có ý nghĩa thống kê về đường huyết trung bình giữa hai nhóm bệnh nhân. Với p-value rất nhỏ (<2.2e−16), chúng ta bác bỏ giả thuyết không và khẳng định có sự khác biệt. Khoảng tin cậy 95% không chứa số 0, xác nhận rằng đường huyết trung bình của nhóm đột quỵ (114.68) cao hơn đáng kể so với nhóm không đột quỵ (106.76). Phân tích boxplot cho thấy cả hai nhóm đều có giá trị ngoại lai ở cả hai đầu, nhưng đáng chú ý là giá trị ngoại lai phía dưới của nhóm đột quỵ lại cao hơn nhóm không đột quỵ. Điều này củng cố giả thuyết rằng đường huyết cao là một yếu tố nguy cơ của đột quỵ.
tab <- table(df$Diabetes,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Tình trạng tiểu đường")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng đột quỵ theo tình trạng tiểu đường", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng tiểu đường | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| No | 6096 | 1944 | 75.82% | 24.18% |
| Yes | 926 | 1034 | 47.24% | 52.76% |
df_percent <- df %>%
group_by(Stroke, Diabetes) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Diabetes) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = Diabetes, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ bị đột quỵ theo tình trạng tiểu đường",
y = "Tỷ lệ (%)", x = "Tình trạng tiểu đường", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## No 1.000000 NA NA
## Yes 2.181847 2.060879 2.309916
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 9.202261e-127 7.636659e-136
## odds ratio with 95% C.I.
## estimate lower upper
## No 1.000000 NA NA
## Yes 3.500922 3.160691 3.878516
## two-sided
## midp.exact fisher.exact chi.square
## No NA NA NA
## Yes 0 9.202261e-127 7.636659e-136
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab
## X-squared = 613.99, df = 1, p-value < 2.2e-16
Kết quả phân tích cho thấy một mối liên hệ mạnh mẽ và có ý nghĩa thống kê giữa tình trạng tiểu đường và đột quỵ. Kiểm định Chi-squared có p-value cực nhỏ (<2.2e−16), cho phép chúng ta bác bỏ giả thuyết không có mối liên hệ. Tỷ lệ đột quỵ ở bệnh nhân tiểu đường là 52.76%, cao hơn gấp đôi so với nhóm không mắc bệnh tiểu đường chỉ 24.18%. Phân tích Relative Risk (RR = 2.18) cho thấy nguy cơ đột quỵ ở bệnh nhân tiểu đường cao gấp 2.18 lần so với nhóm không mắc bệnh. Tương tự, Odds Ratio (OR = 3.50) cho thấy tỷ lệ cược đột quỵ của nhóm có bệnh tiểu đường cao gấp 3.5 lần. Cả hai chỉ số này đều có khoảng tin cậy không chứa số 1 và p-value rất nhỏ, khẳng định rằng tiểu đường là một yếu tố nguy cơ đáng kể của đột quỵ.
tab <- table(df$Smoking_Status,df$Stroke)
proptab <- prop.table(tab, margin = 1)
freq_df <- as.data.frame.matrix(tab)
prop_df <- as.data.frame.matrix(proptab)
colnames(freq_df) <- paste("Tần số", colnames(freq_df))
colnames(prop_df) <- paste("Tỷ lệ", colnames(prop_df))
tab_result <- cbind(freq_df, prop_df)
tab_result <- tab_result %>%
mutate(across(starts_with("Tỷ lệ"), ~ percent(.x, 0.01)))
tab_result <- tab_result %>%
rownames_to_column("Tình trạng hút thuốc")
kable(tab_result, caption = "Bảng tần số và tỷ lệ tình trạng đột quỵ theo tình trạng hút thuốc", align = "c") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = TRUE,
font_size = 14,
position = "center"
) %>%
column_spec(1:ncol(tab_result), bold = TRUE, extra_css = "text-align: center;") | Tình trạng hút thuốc | Tần số No | Tần số Yes | Tỷ lệ No | Tỷ lệ Yes |
|---|---|---|---|---|
| Never | 4263 | 1688 | 71.64% | 28.36% |
| Current | 1300 | 762 | 63.05% | 36.95% |
| Former | 1459 | 528 | 73.43% | 26.57% |
df_percent <- df %>%
group_by(Stroke, Smoking_Status) %>%
summarise(Count = n(), .groups = "drop") %>%
group_by(Smoking_Status) %>%
mutate(Percent = Count / sum(Count))
ggplot(df_percent, aes(x = Smoking_Status, y = Percent, fill = Stroke)) +
geom_col(position = "stack") +
geom_text(aes(label = scales::percent(Percent, accuracy = 0.01)),
position = position_stack(vjust = 0.5), color = "white") +
scale_y_continuous(labels = scales::percent_format()) +
labs(
title = "Tỷ lệ bị đột quỵ theo tình trạng hút thuốc",
y = "Tỷ lệ (%)", x = "Tình trạng hút thuốc", fill = "Tình trạng"
) +
theme_minimal()## risk ratio with 95% C.I.
## estimate lower upper
## Never 1.0000000 NA NA
## Current 1.3028182 1.2155372 1.396366
## Former 0.9368144 0.8617663 1.018398
## two-sided
## midp.exact fisher.exact chi.square
## Never NA NA NA
## Current 5.382361e-13 6.267566e-13 2.972286e-13
## Former 1.224893e-01 1.259125e-01 1.230677e-01
## odds ratio with 95% C.I.
## estimate lower upper
## Never 1.0000000 NA NA
## Current 1.4803110 1.3315383 1.645093
## Former 0.9140847 0.8148156 1.024357
## two-sided
## midp.exact fisher.exact chi.square
## Never NA NA NA
## Current 5.382361e-13 6.267566e-13 2.972286e-13
## Former 1.224893e-01 1.259125e-01 1.230677e-01
##
## Pearson's Chi-squared test
##
## data: tab
## X-squared = 66.227, df = 2, p-value = 4.159e-15
Kết quả phân tích cho thấy có một mối liên hệ có ý nghĩa thống kê giữa tình trạng hút thuốc và nguy cơ đột quỵ, được xác nhận bởi kiểm định Chi-squared với p-value rất nhỏ (4.159e−15). Tỷ lệ đột quỵ ở nhóm đang hút thuốc là 36.95%, cao hơn đáng kể so với nhóm chưa bao giờ hút thuốc (28.36%) và nhóm đã từng hút thuốc (26.57%). Phân tích Relative Risk (RR) cho thấy nguy cơ đột quỵ ở nhóm đang hút thuốc cao hơn 1.3 lần (RR = 1.30) so với nhóm chưa bao giờ hút. Tương tự, Odds Ratio (OR) cho thấy tỷ lệ cược đột quỵ của nhóm này cao hơn 1.48 lần (OR = 1.48). Ngược lại, nhóm đã từng hút thuốc có nguy cơ và tỷ lệ cược đột quỵ gần như không khác biệt so với nhóm chưa bao giờ hút thuốc, với RR và OR đều xấp xỉ 1 và p-value không có ý nghĩa thống kê (>0.1). Do không có sự khác biệt có ý nghĩa thống kê về nguy cơ đột quỵ giữa nhóm chưa bao giờ hút thuốc và nhóm đã từng hút thuốc, chúng ta có thể gộp hai nhóm này lại thành một nhóm mới là “Không hút thuốc” để đơn giản hóa phân tích. Việc gộp nhóm sẽ giúp tạo ra một biến nhị phân rõ ràng, có hoặc không có yếu tố nguy cơ, phục vụ tốt hơn cho các mô hình phân tích sau này.
Mô hình Logit cần ước lượng: \[ \begin{aligned} \log\left(\frac{P(Y=1)}{1 - P(Y=1)}\right) &= \beta_0 + \beta_1 \cdot Age + \beta_2 \cdot SES \\ &\quad + \beta_3 \cdot AvgGlucose + \beta_4 \cdot HeartDisease \\ &\quad + \beta_5 \cdot Hypertension + \beta_6 \cdot Diabetes \\ &\quad + \beta_7 \cdot BMI + \beta_8 \cdot Smoking\_Status \end{aligned} \]
model_logit <- glm(Stroke ~ Age+SES+Avg_Glucose+Heart_Disease+Hypertension+Diabetes+BMI+Smoking_Status,
data = df ,
family = binomial(link = "logit"))
summary(model_logit)##
## Call:
## glm(formula = Stroke ~ Age + SES + Avg_Glucose + Heart_Disease +
## Hypertension + Diabetes + BMI + Smoking_Status, family = binomial(link = "logit"),
## data = df)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -10.365051 0.354694 -29.223 < 2e-16 ***
## Age 0.063385 0.003195 19.839 < 2e-16 ***
## SESMedium 0.072004 0.063341 1.137 0.256
## SESHigh 0.042428 0.078453 0.541 0.589
## Avg_Glucose 0.007995 0.001808 4.422 9.78e-06 ***
## Heart_DiseaseYes 1.400393 0.059938 23.364 < 2e-16 ***
## HypertensionYes 2.011297 0.076337 26.348 < 2e-16 ***
## DiabetesYes 1.434903 0.065151 22.024 < 2e-16 ***
## BMI 0.057735 0.005556 10.391 < 2e-16 ***
## Smoking_StatusSmoking 0.584676 0.064811 9.021 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 12179.8 on 9999 degrees of freedom
## Residual deviance: 8509.2 on 9990 degrees of freedom
## AIC: 8529.2
##
## Number of Fisher Scoring iterations: 5
Kết quả từ mô hình hồi quy logistic cho thấy hầu hết các biến độc lập đều có mối liên hệ có ý nghĩa thống kê với khả năng bị đột quỵ. Các biến Age, Avg_Glucose, Heart_Disease, Hypertension, Diabetes, BMI và Smoking_Status đều có p-value rất nhỏ (<0.05), cho thấy chúng có tác động đáng kể lên tỷ lệ cược đột quỵ. Cụ thể:
Đối với hệ số chặn thì ở mức tuổi(70 tuổi), BMI(28) và chỉ số đường huyết(109) ở mức trung bình ở trong mẫu với địa vị xã hội là thấp, không bệnh tim, không tiểu đường, không cao huyết áp và không hút thuốc thì xác suất đột quỵ của người này là: \[ P(Stroke=1)= \frac{1}{1+exp[-(-10.365051+0.0633\times70+0.0577\times28+0.00799\times109)]} \] = 3.0842277%. Mặc dù tuổi đã cao và BMI tiệm cận ngưỡng béo phì, xác suất này vẫn ở mức tương đối thấp khi không có các yếu tố rủi ro đi kèm. Điều này nhấn mạnh tầm quan trọng của việc kiểm soát bệnh nền và lối sống. Do đó, chiến lược y tế công cộng nên tập trung vào phòng ngừa tích cực bệnh mạn tính và nâng cao nhận thức về lối sống lành mạnh, hơn là chỉ can thiệp khi biến cố đã xảy ra
Age: Khi tuổi tăng thêm 1 đơn vị, tỷ lệ cược đột quỵ tăng lên 1.0650268 lần.
Hypertension: Bệnh nhân có cao huyết áp có tỷ lệ cược đột quỵ cao gấp 7.4707844 lần đối với người không có cao huyết áp. Điều này phản ánh rõ xu hướng nguy cơ đột quỵ gia tăng theo thời gian sinh học, phù hợp với cơ chế suy giảm chức năng sinh lý ở người cao tuổi. Do đó, các biện pháp can thiệp phòng ngừa cần được ưu tiên triển khai cho nhóm dân số lão niên. Thông tin này đặc biệt hữu ích trong việc lập kế hoạch y tế cộng đồng và sàng lọc đối tượng nguy cơ cao.
Heart_Disease: Tỷ lệ cược đột quỵ ở người có bệnh tim cao gấp 4.0552 lần đối với người không có bệnh về tim mạch.Điều này hoàn toàn phù hợp với cơ sở sinh lý bệnh khi tổn thương tim làm suy giảm khả năng điều hòa huyết áp và lưu lượng máu não. Sự gia tăng đáng kể này nhấn mạnh vai trò then chốt của việc kiểm soát và điều trị bệnh tim trong chiến lược phòng chống đột quỵ.
Diabetes: Bệnh nhân tiểu đường có tỷ lệ cược đột quỵ cao gấp 4.199645 lần đối với người không có tiểu đường. Điều này phản ánh cơ chế bệnh sinh khi tình trạng tăng đường huyết mạn tính dẫn đến tổn thương thành mạch máu, xơ vữa động mạch và rối loạn tuần hoàn não. Bên cạnh đó, bệnh tiểu đường thường đi kèm với các yếu tố nguy cơ khác như cao huyết áp và béo phì, làm cộng hưởng tác động tiêu cực đến hệ tim mạch và não bộ.
BMI và Avg_Glucose: Cả hai biến này đều có tác động làm tăng nguy cơ và có ý nghĩa, với mỗi đơn vị tăng lên, tỷ lệ cược đột quỵ cũng tăng theo. Điều này phản ánh mối liên hệ giữa béo phì, rối loạn chuyển hóa và nguy cơ tổn thương mạch máu não. Do đó, kiểm soát cân nặng hợp lý thông qua chế độ ăn cân đối, hạn chế thực phẩm nhiều đường tinh luyện (như bánh kẹo, nước ngọt) và chất béo bão hòa (như đồ chiên rán, thịt đỏ), đồng thời tăng cường rau xanh, ngũ cốc nguyên hạt và hoạt động thể chất đều đặn là những biện pháp quan trọng để giảm thiểu nguy cơ đột quỵ.
Smoking_Status: Bệnh nhân nào có hút thuốc thì sẽ có tỷ lệ cược đột quỵ cao gấp 1.7942731 so với người không hút thuốc. Điều này phản ánh tác động tiêu cực rõ rệt của thuốc lá đối với hệ tim mạch và thần kinh. Do đó, việc triển khai các chương trình cai thuốc lá, tăng thuế thuốc lá, kết hợp truyền thông cộng đồng về tác hại của hút thuốc là chiến lược y tế công cộng thiết yếu. Đồng thời, lồng ghép tư vấn cai thuốc vào hệ thống chăm sóc sức khỏe ban đầu sẽ góp phần làm giảm tỷ lệ đột quỵ trong dân số.
Tuy nhiên, các biến về địa vị xã hội (SES) không có ý nghĩa thống kê (p-value >0.05), cho thấy sau khi kiểm soát các yếu tố sức khỏe khác, địa vị xã hội không phải là yếu tố dự đoán đáng kể cho đột quỵ trong mô hình này.
Kết luận từ mô hình hồi quy logistic cho thấy các yếu tố lâm sàng như tuổi tác, chỉ số đường huyết, BMI, tình trạng bệnh tim, cao huyết áp, tiểu đường và thói quen hút thuốc có ảnh hưởng đáng kể đến xác suất xảy ra đột quỵ. Điều này cho thấy nguy cơ đột quỵ chịu tác động mạnh từ tình trạng sức khỏe nền và thói quen sinh hoạt hơn là từ các yếu tố nhân khẩu học hoặc địa vị xã hội. Việc các biến xã hội không có ý nghĩa thống kê gợi ý rằng, trong bối cảnh dữ liệu nghiên cứu này, yếu tố sinh lý và bệnh lý đóng vai trò quyết định.
Mô hình Probit cần ước lượng:
\[ \begin{aligned} \left(\Phi^{-1}(P(Y=1))}\right) &= \beta_0 + \beta_1 \cdot Age + \beta_2 \cdot SES \\ &\quad + \beta_3 \cdot AvgGlucose + \beta_4 \cdot HeartDisease \\ &\quad + \beta_5 \cdot Hypertension + \beta_6 \cdot Diabetes \\ &\quad + \beta_7 \cdot BMI + \beta_8 \cdot Smoking\_Status \end{aligned} \]
model_probit <- glm(Stroke ~ Age+SES+Avg_Glucose+Heart_Disease+Hypertension+Diabetes+BMI+Smoking_Status,
data = df ,
family = binomial(link = "probit"))
summary(model_probit)##
## Call:
## glm(formula = Stroke ~ Age + SES + Avg_Glucose + Heart_Disease +
## Hypertension + Diabetes + BMI + Smoking_Status, family = binomial(link = "probit"),
## data = df)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -5.921066 0.197542 -29.974 < 2e-16 ***
## Age 0.036073 0.001812 19.909 < 2e-16 ***
## SESMedium 0.035441 0.036392 0.974 0.330
## SESHigh 0.014073 0.045108 0.312 0.755
## Avg_Glucose 0.004883 0.001041 4.692 2.7e-06 ***
## Heart_DiseaseYes 0.802634 0.034313 23.391 < 2e-16 ***
## HypertensionYes 1.109029 0.040571 27.335 < 2e-16 ***
## DiabetesYes 0.829931 0.037307 22.246 < 2e-16 ***
## BMI 0.033344 0.003187 10.463 < 2e-16 ***
## Smoking_StatusSmoking 0.337988 0.037369 9.045 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 12179.8 on 9999 degrees of freedom
## Residual deviance: 8535.6 on 9990 degrees of freedom
## AIC: 8555.6
##
## Number of Fisher Scoring iterations: 5
Các hệ số hồi quy trong mô hình Probit cho biết được mức độ thay đổi của Z-score (đại diện cho “nguy cơ tiềm ẩn” đột quỵ) khi một biến độc lập thay đổi. Z-score càng cao, xác suất đột quỵ càng lớn.
Cho thấy rằng những người ở trạng thái bình thường thì xác suất đột quỵ rất thấp. Mặc dù ở mức BMI là mức có thể được xem như là béo phì. Tuy nhiên, không nên chủ quan với yếu tố cân nặng, bởi vì BMI cao có thể trở thành yếu tố nguy cơ khi kết hợp với các rối loạn chuyển hóa khác như tăng đường huyết hoặc huyết áp.
Điều đáng chú ý là các biến về Địa vị xã hội (SES) không có ý nghĩa thống kê (p-value >0.05), cho thấy sau khi kiểm soát các yếu tố sức khỏe khác, địa vị xã hội không phải là một yếu tố dự đoán đáng tin cậy trong mô hình này.
Kết quả từ mô hình Probit cho thấy các yếu tố lâm sàng như tuổi tác, huyết áp, bệnh tim, tiểu đường, chỉ số BMI và đường huyết trung bình đều góp phần làm tăng Z-score nghĩa là làm gia tăng xác suất tiềm ẩn bị đột quỵ. Đặc biệt, các biến Hypertension, Heart_Disease và Diabetes có hệ số rất lớn, phản ánh mức độ ảnh hưởng mạnh mẽ và rõ rệt đến nguy cơ đột quỵ. Trong khi đó, các yếu tố liên quan đến địa vị xã hội không cho thấy ý nghĩa thống kê, cho thấy vai trò thứ yếu khi đã kiểm soát các yếu tố sức khỏe. Điều này nhấn mạnh rằng các yếu tố sinh lý có sức ảnh hưởng lớn hơn đến xác suất đột quỵ trong mô hình Probit.
model_names <- c("Logit", "Probit")
aic_values <- c(AIC(model_logit), AIC(model_probit))
table_aic <- data.frame(
"Mô hình" = model_names,
"Giá trị AIC" = round(aic_values, 2) # Làm tròn cho đẹp
)
# Trình bày bảng đẹp bằng kableExtra
kable(table_aic,
caption = "Bảng so sánh tiêu chí AIC giữa mô hình Logit và Probit",
align = "c",
booktabs = TRUE) %>%
kable_styling(latex_options = c("striped", "hold_position"),
full_width = TRUE,
font_size = 12)| Mô.hình | Giá.trị.AIC |
|---|---|
| Logit | 8529.16 |
| Probit | 8555.63 |
Dựa trên chỉ số AIC, mô hình Logit được lựa chọn vì có giá trị AIC thấp hơn so với Probit . Chỉ số AIC thấp cho thấy mô hình Logit có khả năng giải thích dữ liệu tốt hơn với các biến đã chọn, đồng thời cũng ít phức tạp hơn. Hơn nữa, việc diễn giải kết quả của mô hình Logit (dưới dạng Odds Ratio) trực quan và dễ hiểu hơn, giúp người đọc nắm bắt ý nghĩa của các hệ số một cách rõ ràng. Do đó, đây là mô hình được lựa chọn để phân tích đột quỵ.
df$predicted_prob <- predict(model_logit ,type = "response")
roc_obj <- roc(df$Stroke, df$predicted_prob, levels = c("No", "Yes"))
plot(roc_obj, col = "blue", print.auc = TRUE, main = "ROC Curve - logit model")## Area under the curve: 0.8506
## Ngưỡng để phân loại: 0.3024846
df$predicted_class <- ifelse(df$predicted_prob >= as.numeric(coords(roc_obj, "best", ret = "threshold")),
"Yes", "No")
confusionMatrix(factor(df$predicted_class),
factor(df$Stroke),
positive = "Yes")## Confusion Matrix and Statistics
##
## Reference
## Prediction No Yes
## No 5332 667
## Yes 1690 2311
##
## Accuracy : 0.7643
## 95% CI : (0.7559, 0.7726)
## No Information Rate : 0.7022
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.4872
##
## Mcnemar's Test P-Value : < 2.2e-16
##
## Sensitivity : 0.7760
## Specificity : 0.7593
## Pos Pred Value : 0.5776
## Neg Pred Value : 0.8888
## Prevalence : 0.2978
## Detection Rate : 0.2311
## Detection Prevalence : 0.4001
## Balanced Accuracy : 0.7677
##
## 'Positive' Class : Yes
##
Kết quả đánh giá mô hình cho thấy hiệu suất tương đối tốt. Chỉ số AUC đạt 0.8508, cho thấy khả năng phân biệt giữa hai nhóm đột quỵ và không đột quỵ của mô hình là khá cao. Dựa trên ma trận nhầm lẫn, mô hình có độ chính xác Accuracy là 76.23%, vượt trội đáng kể so với mức cơ sở là 70.22%, được xác nhận bởi p-value nhỏ hơn 2.2e-16.Mô hình có khả năng nhận diện các trường hợp đột quỵ là 78.01%, và khả năng nhận diện các trường hợp không đột quỵ là 75.48%. Mặc dù có độ chính xác cao khi dự đoán không đột quỵ (Negative Predictive Value = 89.00%), khả năng dự đoán đúng một trường hợp là đột quỵ khi mô hình dự đoán là đột quỵ (Positive Predictive Value) chỉ đạt 57.43%. Cụ thể, vì số lượng bệnh nhân không bị đột quỵ (70.22%) chiếm ưu thế lớn so với số bệnh nhân bị đột quỵ (29.78%), mô hình có xu hướng dự đoán phần lớn các trường hợp là “không đột quỵ” để tối đa hóa độ chính xác tổng thể. Điều này cho thấy mô hình đôi khi dự đoán sai một số trường hợp không đột quỵ thành đột quỵ, nhưng khả năng dự đoán đúng người không bị đột quỵ là rất tốt.
Nghiên cứu này đã thành công trong việc xác định các yếu tố nguy cơ chính liên quan đến đột quỵ thông qua khai thác dữ liệu lâm sàng và hành vi sức khỏe. Dựa trên mô hình hồi quy Logit được lựa chọn vì có chỉ số AIC thấp hơn so với mô hình Probit. Các yếu tố như tuổi tác, cao huyết áp, bệnh tim, tiểu đường, chỉ số BMI, mức đường huyết trung bình, và tình trạng hút thuốc đều cho thấy ảnh hưởng đáng kể đến xác suất xảy ra đột quỵ. Kết quả cho thấy rằng, mỗi yếu tố nguy cơ đều góp phần làm tăng khả năng mắc đột quỵ, với hai yếu tố có sức tác động mạnh nhất là cao huyết áp và bệnh tim, phản ánh vai trò trung tâm của bệnh lý nền trong quá trình hình thành bệnh. Ngược lại, yếu tố liên quan đến địa vị xã hội lại không có ý nghĩa thống kê trong mô hình, hàm ý rằng các điều kiện sinh học và thói quen sinh hoạt có vai trò quyết định hơn so với đặc điểm kinh tế xã hội trong việc dự báo nguy cơ mắc bệnh. Những phát hiện này không chỉ mang lại bằng chứng định lượng có giá trị mà còn củng cố thêm nền tảng lý luận cho công tác sàng lọc nguy cơ và can thiệp dự phòng sớm trong cộng đồng.
Từ các phát hiện trên, nghiên cứu đề xuất một số chiến lược phòng ngừa và điều trị có trọng tâm. Theo đó, công tác sàng lọc và kiểm soát nguy cơ đột quỵ nên được tập trung vào các nhóm dân số có yếu tố nguy cơ cao, đặc biệt là người cao tuổi, người mắc bệnh lý nền mạn tính và những người có lối sống không lành mạnh. Cần xây dựng các chương trình can thiệp cụ thể như theo dõi huyết áp thường xuyên, kiểm soát đường huyết, điều chỉnh chế độ dinh dưỡng để duy trì BMI hợp lý, và đẩy mạnh tư vấn bỏ thuốc lá. Những biện pháp này không chỉ giúp giảm xác suất khởi phát đột quỵ mà còn góp phần nâng cao chất lượng cuộc sống nói chung. Mặc dù mô hình đã đạt được độ chính xác phân loại khá tốt, vẫn còn dư địa để nâng cao khả năng nhận diện đúng các trường hợp đột quỵ. Do vậy, các kỹ thuật nâng cao như xử lý mất cân bằng dữ liệu hoặc áp dụng các mô hình phi tuyến có thể được xem xét trong các nghiên cứu tiếp theo nhằm tối ưu hóa hiệu năng dự báo.