This dataset contains simulated data for brain tumor diagnosis, treatment, and patient details. It consists of 19 columns and 20,000 rows, providing information such as patient demographics, tumor characteristics, symptoms, treatment details, and follow-up requirements. The dataset is designed for machine learning projects focused on predicting the type and severity of brain tumors, as well as understanding various treatment methods and patient outcomes.
Columns:
Patient_ID: Unique identifier for each patient.
Age: Age of the patient (in years).
Gender: Gender of the patient (Male/Female).
Tumor_Type: Type of tumor (Benign/Malignant).
Tumor_Size: Size of the tumor in centimeters.
Location: The part of the brain where the tumor is located (e.g., Frontal, Temporal).
Histology: The histological type of the tumor (e.g., Astrocytoma, Glioblastoma).
Stage: The stage of the tumor (I, II, III, IV).
Symptom_1: The first symptom observed (e.g., Headache, Seizures).
Symptom_2: The second symptom observed.
Symptom_3: The third symptom observed.
Radiation_Treatment: Whether radiation treatment was administered (Yes/No).
Surgery_Performed: Whether surgery was performed (Yes/No).
Chemotherapy: Whether chemotherapy was administered (Yes/No).
Survival_Rate: The estimated survival rate of the patient (percentage).
Tumor_Growth_Rate: The growth rate of the tumor (cm per month).
Family_History: Whether the patient has a family history of brain tumors (Yes/No).
MRI_Result: The result of the MRI scan (Positive/Negative).
Follow_Up_Required: Whether follow-up is required (Yes/No).
The goal of the project is to amake predictions about the tumor diagnosis -benign or malignant.
Class of the diagnosis:
Benign tumor: It does not invade nearby tissue or spread to other parts of the body the way cancer can.
Malignant tumor: It is a group of diseased cells defined by one of three characteristics: uncontrolled growth, invasion and damage of healthy cells, or metastasizing (spreading) to other organs of the body.
#packages
#Tidyverse for map_int()
if(!require(tidyverse)) install.packages("tidyverse", repos = "http://cran.us.r-project.org")
#corrplot package for corrplot()
if(!require(corrplot)) install.packages("corrplot", repos = "http://cran.us.r-project.org")
#caret package for find.Correlation()
if(!require(caret)) install.packages("caret", repos = "http://cran.us.r-project.org")
#randomForest package for randomForest()
if(!require(randomForest)) install.packages("randomForest", repos = "http://cran.us.r-project.org")
#kernlab package for SVM
if(!require(kernlab)) install.packages("kernlab", repos = "http://cran.us.r-project.org")
bc<-read.csv("brain_tumor_dataset.csv", header=T, sep=",")
str(bc)
## 'data.frame': 20000 obs. of 19 variables:
## $ Patient_ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Age : int 73 26 31 29 54 27 72 61 50 54 ...
## $ Gender : chr "Male" "Male" "Male" "Male" ...
## $ Tumor_Type : chr "Malignant" "Benign" "Benign" "Malignant" ...
## $ Tumor_Size : num 5.38 4.85 5.59 1.44 2.42 ...
## $ Location : chr "Temporal" "Parietal" "Parietal" "Temporal" ...
## $ Histology : chr "Astrocytoma" "Glioblastoma" "Meningioma" "Medulloblastoma" ...
## $ Stage : chr "III" "II" "I" "IV" ...
## $ Symptom_1 : chr "Vision Issues" "Headache" "Vision Issues" "Vision Issues" ...
## $ Symptom_2 : chr "Seizures" "Headache" "Headache" "Seizures" ...
## $ Symptom_3 : chr "Seizures" "Nausea" "Seizures" "Headache" ...
## $ Radiation_Treatment: chr "No" "Yes" "No" "Yes" ...
## $ Surgery_Performed : chr "No" "Yes" "No" "No" ...
## $ Chemotherapy : chr "No" "Yes" "No" "Yes" ...
## $ Survival_Rate : num 51.3 46.4 47.1 51.9 54.7 ...
## $ Tumor_Growth_Rate : num 0.112 2.166 1.884 1.283 2.069 ...
## $ Family_History : chr "No" "Yes" "No" "Yes" ...
## $ MRI_Result : chr "Positive" "Positive" "Negative" "Negative" ...
## $ Follow_Up_Required : chr "Yes" "Yes" "No" "No" ...
We have 20000 observations of 19 variables. So we can understand by our bc dataset that we have 20000 patients and 19 characteristics/features per patient. So, we can imagine a matrix of 20000 rows and 19 columns. This matrix has 380000 elements.
Let’s check if these id numbers are unique.
ifelse (n_distinct(bc$Patient_ID) == 20000, "Id numbers are unique.", "Id numbers are not unique.")
## [1] "Id numbers are unique."
The id numbers are unique, so there are no double id features in our data set.
Let’s check if we have missing values in our data set.
map_int(bc, function(.x) sum(is.na(.x)))
## Patient_ID Age Gender Tumor_Type
## 0 0 0 0
## Tumor_Size Location Histology Stage
## 0 0 0 0
## Symptom_1 Symptom_2 Symptom_3 Radiation_Treatment
## 0 0 0 0
## Surgery_Performed Chemotherapy Survival_Rate Tumor_Growth_Rate
## 0 0 0 0
## Family_History MRI_Result Follow_Up_Required
## 0 0 0
There are no missing values. So, we do not need to transform our data set.
Let’s see if our classification data set is imbalanced. Classes that make up small proportions of the data set are called minority classes. Let’s calculate our proportions of our classes.
round(prop.table(table(bc$Tumor_Type)), 2)
##
## Benign Malignant
## 0.5 0.5
The proportion of negative and positive labels are equal, so there is no impalanced dataset.
Let’s check if there is multicollinearity on our data set. Multicollinearity exists when two or more of the predictors in a regression model are moderately or highly correlated with one another. Then, we will remove the highly correlated predictors (if any).
bc_corr <- cor(bc%>%select(Age, Tumor_Size, Survival_Rate,Tumor_Growth_Rate))
bc_corr
## Age Tumor_Size Survival_Rate Tumor_Growth_Rate
## Age 1.000000000 -0.014385485 -0.014825024 -0.009852592
## Tumor_Size -0.014385485 1.000000000 0.003294837 0.004346803
## Survival_Rate -0.014825024 0.003294837 1.000000000 -0.006824939
## Tumor_Growth_Rate -0.009852592 0.004346803 -0.006824939 1.000000000
corrplot::corrplot(bc_corr)
There is no multicollinearity in our dataset.
Let’s transform our data set and create a training and a testing set. Our testing set will be 20% of our data set.
bc1<-bc%>%select(Age, Tumor_Size, Survival_Rate,Tumor_Growth_Rate)
bc2<-bc1%>%cbind(diagnosis=as.factor(bc$Tumor_Type))
set.seed(1570)
bc_index <- createDataPartition(bc2$diagnosis, times = 1, p = 0.8, list = FALSE)
bc_training <- bc2[bc_index, ]
bc_testing <- bc2[-bc_index, ]
bc_control <- trainControl(method="cv",
number = 10,
classProbs = TRUE,
summaryFunction = twoClassSummary)
model1_lr <- train(diagnosis ~., data = bc_training, method = "glm",
metric = "ROC", preProcess = c("scale", "center"),
trControl = bc_control)
prediction_lr <- predict(model1_lr, bc_testing)
con_mat_lr <- confusionMatrix(prediction_lr, bc_testing$diagnosis, positive = "Malignant")
con_mat_lr
## Confusion Matrix and Statistics
##
## Reference
## Prediction Benign Malignant
## Benign 873 871
## Malignant 1121 1135
##
## Accuracy : 0.502
## 95% CI : (0.4864, 0.5176)
## No Information Rate : 0.5015
## P-Value [Acc > NIR] : 0.4811
##
## Kappa : 0.0036
##
## Mcnemar's Test P-Value : 2.419e-08
##
## Sensitivity : 0.5658
## Specificity : 0.4378
## Pos Pred Value : 0.5031
## Neg Pred Value : 0.5006
## Prevalence : 0.5015
## Detection Rate : 0.2838
## Detection Prevalence : 0.5640
## Balanced Accuracy : 0.5018
##
## 'Positive' Class : Malignant
##
model2_rf <- train(diagnosis~.,
bc_training,
method="rf",
metric="ROC",
trControl=bc_control)
pred_rf <- predict(model2_rf, bc_testing)
con_mat_rf <- confusionMatrix(pred_rf, bc_testing$diagnosis, positive = "Malignant")
con_mat_rf
## Confusion Matrix and Statistics
##
## Reference
## Prediction Benign Malignant
## Benign 983 969
## Malignant 1011 1037
##
## Accuracy : 0.505
## 95% CI : (0.4894, 0.5206)
## No Information Rate : 0.5015
## P-Value [Acc > NIR] : 0.3347
##
## Kappa : 0.0099
##
## Mcnemar's Test P-Value : 0.3568
##
## Sensitivity : 0.5169
## Specificity : 0.4930
## Pos Pred Value : 0.5063
## Neg Pred Value : 0.5036
## Prevalence : 0.5015
## Detection Rate : 0.2592
## Detection Prevalence : 0.5120
## Balanced Accuracy : 0.5050
##
## 'Positive' Class : Malignant
##
Let’s make plots and see our model results.
plot(model2_rf)
randomForest::varImpPlot(model2_rf$finalModel, sort = TRUE,
n.var = 4, main = "The top 4 predictive features")
model3_knn<- train(diagnosis ~., data = bc_training,
method = "knn",
metric = "ROC",
preProcess = c("scale", "center"),
trControl = bc_control,
tuneLength =31)
Let’s make a plot of our model.
plot(model3_knn)
predictions_knn <- predict(model3_knn, bc_testing)
con_mat_knn <- confusionMatrix(predictions_knn, bc_testing$diagnosis, positive = "Malignant")
con_mat_knn
## Confusion Matrix and Statistics
##
## Reference
## Prediction Benign Malignant
## Benign 1009 997
## Malignant 985 1009
##
## Accuracy : 0.5045
## 95% CI : (0.4889, 0.5201)
## No Information Rate : 0.5015
## P-Value [Acc > NIR] : 0.3581
##
## Kappa : 0.009
##
## Mcnemar's Test P-Value : 0.8048
##
## Sensitivity : 0.5030
## Specificity : 0.5060
## Pos Pred Value : 0.5060
## Neg Pred Value : 0.5030
## Prevalence : 0.5015
## Detection Rate : 0.2522
## Detection Prevalence : 0.4985
## Balanced Accuracy : 0.5045
##
## 'Positive' Class : Malignant
##
set.seed(1570)
model4_svm <- train(diagnosis ~., data = bc_training, method = "svmLinear",
metric = "ROC",
preProcess = c("scale", "center"),
trace = FALSE,
trControl = bc_control)
## line search fails 0.002909029 -0.006175341 -4.071908e-06 1.362345e-05 4.179166e-09 -3.876586e-09 -6.982964e-14
## Warning in method$predict(modelFit = modelFit, newdata = newdata, submodels =
## param): kernlab class prediction calculations failed; returning NAs
## Warning in method$prob(modelFit = modelFit, newdata = newdata, submodels =
## param): kernlab class probability calculations failed; returning NAs
## Warning in data.frame(..., check.names = FALSE): row names were found from a
## short variable and have been discarded
## Warning in nominalTrainWorkflow(x = x, y = y, wts = weights, info = trainInfo,
## : There were missing values in resampled performance measures.
prediction_svm <- predict(model4_svm, bc_testing)
con_mat_svm <- confusionMatrix(prediction_svm, bc_testing$diagnosis, positive = "Malignant")
con_mat_svm
## Confusion Matrix and Statistics
##
## Reference
## Prediction Benign Malignant
## Benign 146 143
## Malignant 1848 1863
##
## Accuracy : 0.5022
## 95% CI : (0.4866, 0.5179)
## No Information Rate : 0.5015
## P-Value [Acc > NIR] : 0.4685
##
## Kappa : 0.0019
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.92871
## Specificity : 0.07322
## Pos Pred Value : 0.50202
## Neg Pred Value : 0.50519
## Prevalence : 0.50150
## Detection Rate : 0.46575
## Detection Prevalence : 0.92775
## Balanced Accuracy : 0.50097
##
## 'Positive' Class : Malignant
##
Models <- c("Logistic Regression", "Random Forest", "K-Nearest Neighbor", "Support Vector Machine")
Accuracy <- round(c(con_mat_lr$overall["Accuracy"], +
con_mat_rf$overall["Accuracy"],+
con_mat_knn$overall["Accuracy"], +
con_mat_svm$overall["Accuracy"]),2)
table_of_Accuracy <- data.frame(Models, Accuracy)
table_of_Accuracy
## Models Accuracy
## 1 Logistic Regression 0.5
## 2 Random Forest 0.5
## 3 K-Nearest Neighbor 0.5
## 4 Support Vector Machine 0.5
model_list <- list(Logistic = model1_lr, rf = model2_rf, knn = model3_knn, svm = model4_svm)
results <- resamples(model_list)
summary(results)
##
## Call:
## summary.resamples(object = results)
##
## Models: Logistic, rf, knn, svm
## Number of resamples: 10
##
## ROC
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## Logistic 0.4844101 0.4954016 0.5024477 0.5027556 0.5113788 0.5265904 0
## rf 0.4730076 0.4855249 0.4914622 0.4941759 0.5004844 0.5211558 0
## knn 0.4828225 0.5023376 0.5093715 0.5072971 0.5149446 0.5200292 0
## svm 0.4800780 0.4924796 0.4935018 0.4976706 0.5054240 0.5171642 1
##
## Sens
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## Logistic 0.42534504 0.4335840 0.4422836 0.4443320 0.4556321 0.4661654 0
## rf 0.46741855 0.4763434 0.4956140 0.4913553 0.5001572 0.5219573 0
## knn 0.47678795 0.4863716 0.5040754 0.5008772 0.5090852 0.5263158 0
## svm 0.09273183 0.3621554 0.3984962 0.3594461 0.4341280 0.4624060 1
##
## Spec
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## Logistic 0.5280199 0.5434495 0.5617207 0.5601959 0.5767664 0.5853051 0
## rf 0.4788030 0.4890898 0.5034254 0.5029877 0.5104327 0.5379826 0
## knn 0.4769614 0.5045178 0.5074813 0.5054850 0.5132444 0.5224439 0
## svm 0.5516812 0.5635910 0.5748130 0.6384518 0.6288917 0.9178082 1
bwplot(results, metric = "ROC")
The knn model give us the best results. The accuracy of the model is 50% and ROC has a medium but slightly better predictive power. The main future goal is to make predictions on real health data to see the actual differences or improvements.