#clear the memory
rm(list = ls())

setwd("/Users/nickponzi/lab/data")
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.5.0     ✔ purrr   1.0.2
## ✔ tibble  3.2.1     ✔ dplyr   1.1.4
## ✔ tidyr   1.3.1     ✔ stringr 1.5.0
## ✔ readr   2.1.3     ✔ forcats 0.5.2
## Warning: package 'ggplot2' was built under R version 4.2.3
## Warning: package 'tidyr' was built under R version 4.2.3
## Warning: package 'dplyr' was built under R version 4.2.3
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
# Load the CSV file into a data frame
data <- read.csv("diabetes.csv", header = TRUE)

# Display the structure of the dataset
str(data)
## 'data.frame':    768 obs. of  9 variables:
##  $ Pregnancies             : int  6 1 8 1 0 5 3 10 2 8 ...
##  $ Glucose                 : int  148 85 183 89 137 116 78 115 197 125 ...
##  $ BloodPressure           : int  72 66 64 66 40 74 50 0 70 96 ...
##  $ SkinThickness           : int  35 29 0 23 35 0 32 0 45 0 ...
##  $ Insulin                 : int  0 0 0 94 168 0 88 0 543 0 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 2.288 ...
##  $ Age                     : int  50 31 32 21 33 30 26 29 53 54 ...
##  $ Outcome                 : int  1 0 1 0 1 0 1 0 1 1 ...
# Display the first few rows of the dataset
head(data)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35       0 33.6
## 2           1      85            66            29       0 26.6
## 3           8     183            64             0       0 23.3
## 4           1      89            66            23      94 28.1
## 5           0     137            40            35     168 43.1
## 6           5     116            74             0       0 25.6
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 5                    2.288  33       1
## 6                    0.201  30       0
# Check for missing values
missing_values <- colSums(is.na(data))
print(missing_values)
##              Pregnancies                  Glucose            BloodPressure 
##                        0                        0                        0 
##            SkinThickness                  Insulin                      BMI 
##                        0                        0                        0 
## DiabetesPedigreeFunction                      Age                  Outcome 
##                        0                        0                        0
# Calculate Z-scores for each numerical feature
z_scores <- scale(data[, -9]) # Exclude the outcome variable

# Identify outliers based on Z-scores
outliers <- apply(abs(z_scores) > 3, 1, any) # Check if any Z-score exceeds 3 for each row
outlier_indices <- which(outliers)

# Print the indices of outliers
print(outlier_indices)
##  [1]   5   8   9  10  14  16  46  50  59  61  76  79  82  89 112 124 146 154 160
## [20] 173 178 183 187 194 221 223 229 248 262 267 270 287 299 301 331 333 337 343
## [39] 348 350 358 371 372 396 410 416 427 431 436 446 454 456 460 469 485 487 495
## [58] 503 523 534 536 580 585 590 594 602 605 620 622 644 646 656 667 674 685 696
## [77] 698 704 707 754
# Remove outliers
data_clean <- data[-outlier_indices, ]

# Verify the removal of outliers
print("Number of observations after removing outliers:")
## [1] "Number of observations after removing outliers:"
print(dim(data_clean))
## [1] 688   9
# Set seed for reproducibility
set.seed(123)

# Split data into training and testing sets
library(caTools)
split <- sample.split(data_clean$Outcome, SplitRatio = 0.7)
training_data <- subset(data_clean, split == TRUE)
testing_data <- subset(data_clean, split == FALSE)

# Check dimensions of training and testing sets
dim(training_data)
## [1] 482   9
dim(testing_data)
## [1] 206   9
#Create a logistic Regression Model

# Load required library
library(glmnet)
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## 
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
## 
## Loaded glmnet 4.1-6
# Create a logistic regression model
logistic_model <- glm(Outcome ~ ., data = training_data, family = "binomial")

# Print the summary of the model
summary(logistic_model)
## 
## Call:
## glm(formula = Outcome ~ ., family = "binomial", data = training_data)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -3.0172  -0.6840  -0.3505   0.6132   2.5647  
## 
## Coefficients:
##                            Estimate Std. Error z value Pr(>|z|)    
## (Intercept)              -1.078e+01  1.131e+00  -9.535  < 2e-16 ***
## Pregnancies               1.234e-01  4.402e-02   2.804 0.005044 ** 
## Glucose                   3.738e-02  5.029e-03   7.434 1.06e-13 ***
## BloodPressure            -7.116e-03  1.076e-02  -0.662 0.508286    
## SkinThickness            -8.219e-03  9.285e-03  -0.885 0.376046    
## Insulin                   7.604e-04  1.515e-03   0.502 0.615629    
## BMI                       1.230e-01  2.265e-02   5.429 5.68e-08 ***
## DiabetesPedigreeFunction  1.635e+00  4.205e-01   3.888 0.000101 ***
## Age                       2.239e-02  1.265e-02   1.771 0.076605 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 611.26  on 481  degrees of freedom
## Residual deviance: 416.74  on 473  degrees of freedom
## AIC: 434.74
## 
## Number of Fisher Scoring iterations: 5
#Evaluate Model Performance

# Predict probabilities of diabetes on testing data
logistic_probabilities <- predict(logistic_model, newdata = testing_data, type = "response")

# Convert probabilities to binary predictions (0 or 1) based on a threshold of 0.5
logistic_predictions <- ifelse(logistic_probabilities > 0.5, 1, 0)

# Calculate confusion matrix
conf_matrix <- table(Actual = testing_data$Outcome, Predicted = logistic_predictions)

# Calculate accuracy
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)

# Calculate precision
precision <- conf_matrix[2, 2] / sum(conf_matrix[, 2])

# Calculate recall (sensitivity)
recall <- conf_matrix[2, 2] / sum(conf_matrix[2, ])

# Calculate F1-score
f1_score <- 2 * precision * recall / (precision + recall)

# Print evaluation metrics
print(paste("Accuracy:", accuracy))
## [1] "Accuracy: 0.762135922330097"
print(paste("Precision:", precision))
## [1] "Precision: 0.641791044776119"
print(paste("Recall (Sensitivity):", recall))
## [1] "Recall (Sensitivity): 0.63235294117647"
print(paste("F1-Score:", f1_score))
## [1] "F1-Score: 0.637037037037037"