This RMarkdown file contains the report of the data analysis done for the project on building and deploying a stroke prediction model in R. It contains analysis such as data exploration, summary statistics and building the prediction models. The final report was completed on Fri Mar 14 06:48:14 2025.
Data Description:
According to the World Health Organization (WHO) stroke is the 2nd leading cause of death globally, responsible for approximately 11% of total deaths.
This data set is used to predict whether a patient is likely to get stroke based on the input parameters like gender, age, various diseases, and smoking status. Each row in the data provides relevant information about the patient.
setwd(“/home/rstudio/Build-deploy-stroke-prediction-model-R”) data<-read.csv(“healthcare-dataset-stroke-data.csv”)
#untuk melihat struktur dari datasheet
str(data)
#untuk melihat ringkasan statistik tiap kolom summary(data)
#untuk menampilkan jumlah baris dan kolom yang ada dim(data)
#untuk melihat nilai total yang hilang dalam dataset sum(is.na(data))
#untuk melakukan pengecekan data duplikat yang ada pada dataset sum(duplicated(data))
install.packages(“caret”) install.packages(“randomForest”) install.packages(“e1071”)
library(caret) library(randomForest) library(e1071)
data<-read.csv(“healthcare-dataset-stroke-data.csv”) data <- data[, -1]
data\(gender <- as.factor(data\)gender) data\(ever_married <- as.factor(data\)ever_married) data\(work_type <- as.factor(data\)work_type) data\(Residence_type <- as.factor(data\)Residence_type) data\(smoking_status <- as.factor(data\)smoking_status) data\(stroke <- as.factor(data\)stroke) # Target variable
colSums(is.na(trainData)) # Cek NA di training data colSums(is.na(testData)) # Cek NA di testing data trainData\(bmi <- as.numeric(as.character(trainData\)bmi)) testData\(bmi <- as.numeric(as.character(testData\)bmi)) sum(is.na(trainData\(bmi)) # Cek di training data sum(is.na(testData\)bmi)) # Cek di testing data trainData\(bmi[is.na(trainData\)bmi)] <- median(trainData\(bmi, na.rm = TRUE) testData\)bmi[is.na(testData\(bmi)] <- median(testData\)bmi, na.rm = TRUE) levels(trainData\(work_type) levels(testData\)work_type)
testData\(work_type <- factor(testData\)work_type, levels = levels(trainData$work_type))
set.seed(123)
trainIndex <- createDataPartition(data$stroke, p = 0.8, list = FALSE)
trainData <- data[trainIndex, ] testData <- data[-trainIndex,
]
###Model 1: Logistic Regression log_model <- glm(stroke ~ ., data = trainData, family = binomial) summary(log_model)
names(trainData) names(testData)
testData\(work_type <-
factor(testData\)work_type, levels = levels(trainData\(work_type)) testData\)smoking_status <-
factor(testData\(smoking_status, levels =
levels(trainData\)smoking_status)) # Output: Probabilitas stroke
log_pred <- predict(log_model, testData, type = “response”)
log_pred_class <- ifelse(log_pred > 0.5, 1, 0) # Threshold 0.5
log_pred_class <- as.factor(log_pred_class) # Konversi ke faktor
print(table(log_pred_class)) # Harus menampilkan jumlah kelas 0 dan
1
library(caret) confusionMatrix(log_pred_class, testData$stroke)
saveRDS(log_model, file = “logistic_model.rds”) log_model <- readRDS(“logistic_model.rds”) predict_stroke <- function(new_data, model) { new_data\(bmi <- as.numeric(as.character(new_data\)bmi)) # Pastikan tipe numeric new_data\(gender <- as.factor(new_data\)gender) # Pastikan tipe faktor new_data\(ever_married <- as.factor(new_data\)ever_married) new_data\(work_type <- as.factor(new_data\)work_type) new_data\(Residence_type <- as.factor(new_data\)Residence_type) new_data\(smoking_status <- as.factor(new_data\)smoking_status)
pred <- predict(model, new_data, type = “response”) # Probabilitas stroke return(ifelse(pred > 0.5, “Stroke”, “No Stroke”)) # Klasifikasi } new_patient <- data.frame( gender = “Male”, age = 45, hypertension = 0, heart_disease = 0, ever_married = “Yes”, work_type = “Private”, Residence_type = “Urban”, avg_glucose_level = 120.5, bmi = 27.3, smoking_status = “formerly smoked” )
predict_stroke(new_patient, log_model)
install.packages(“plumber”) library(plumber)
library(plumber)
log_model <- readRDS(“logistic_model.rds”)
#* @post /predict #* @param gender #* @param age #* @param hypertension #* @param heart_disease #* @param ever_married #* @param work_type #* @param Residence_type #* @param avg_glucose_level #* @param bmi #* @param smoking_status #* @response 200 Returns stroke prediction function(gender, age, hypertension, heart_disease, ever_married, work_type, Residence_type, avg_glucose_level, bmi, smoking_status) { new_data <- data.frame( gender = as.factor(gender), age = as.numeric(age), hypertension = as.numeric(hypertension), heart_disease = as.numeric(heart_disease), ever_married = as.factor(ever_married), work_type = as.factor(work_type), Residence_type = as.factor(Residence_type), avg_glucose_level = as.numeric(avg_glucose_level), bmi = as.numeric(bmi), smoking_status = as.factor(smoking_status) )
pred <- predict(log_model, new_data, type = “response”) return(ifelse(pred > 0.5, “Stroke”, “No Stroke”)) }
library(plumber) r <- plumb(“api.R”) r$run(port = 8000)
Findings and Conclusions 🔹 Findings (Temuan) Data Preprocessing
Dataset mengalami beberapa missing values, terutama pada kolom BMI. Variabel bmi awalnya bertipe character, sehingga menyebabkan error saat prediksi. Solusi: Missing values di bmi diisi dengan median, dan semua kolom dikonversi ke tipe data yang sesuai. Model Training & Performance
Model Logistic Regression digunakan untuk memprediksi stroke. Model mengalami kesalahan saat prediksi karena perbedaan tipe data antara training dan testing. Solusi: ✅ Pastikan bmi bertipe numeric di semua tahap. ✅ Pastikan semua variabel kategori (factor) memiliki level yang sesuai antara trainData dan testData. ✅ Model dilatih ulang setelah preprocessing diperbaiki. Model Evaluation
Confusion Matrix menunjukkan akurasi model cukup baik, tetapi masih perlu perbaikan. Model dapat mengklasifikasikan sebagian besar kasus dengan benar, tetapi mungkin perlu ditingkatkan dengan model yang lebih kompleks seperti Random Forest atau SVM. Model Deployment
Model berhasil disimpan menggunakan RDS (saveRDS()) untuk digunakan kembali. API dibuat menggunakan plumber, sehingga prediksi bisa dilakukan melalui web service. API dapat menerima data baru dan mengembalikan prediksi (Stroke atau No Stroke). 🔹 Conclusions (Kesimpulan) ✅ Model dapat memprediksi risiko stroke berdasarkan fitur pasien seperti usia, hipertensi, penyakit jantung, dan kebiasaan merokok.
✅ Data preprocessing sangat penting dalam memastikan akurasi model—terutama dalam menangani missing values dan tipe data.
✅ Model deployment menggunakan API (Plumber) memungkinkan penggunaan model dalam aplikasi lain, seperti website atau aplikasi mobile.
✅ Untuk meningkatkan akurasi, model lebih kompleks seperti Random Forest atau XGBoost dapat dicoba.