#Data Preprocessing
library(readr)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
library(ggplot2)
library(corrplot)
## corrplot 0.92 loaded
library(caTools)
#Data Cleaning
#Load the dataset
data <- read_csv('C:/Users/USer/Downloads/archive (8)/creditcard_2023.csv')
## Rows: 568630 Columns: 31
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (31): id, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(data)
## # A tibble: 6 × 31
## id V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0 -0.261 -0.470 2.50 -0.0837 0.130 0.733 0.519 -0.130 0.727 0.638
## 2 1 0.985 -0.356 0.558 -0.430 0.277 0.429 0.406 -0.133 0.347 0.530
## 3 2 -0.260 -0.949 1.73 -0.458 0.0741 1.42 0.744 -0.0956 -0.261 0.691
## 4 3 -0.152 -0.509 1.75 -1.09 0.249 1.14 0.518 -0.0651 -0.206 0.575
## 5 4 -0.207 -0.165 1.53 -0.448 0.106 0.531 0.659 -0.213 1.05 0.968
## 6 5 0.0253 -0.141 1.19 -0.708 0.430 0.459 0.611 -0.0926 0.181 0.452
## # ℹ 20 more variables: V11 <dbl>, V12 <dbl>, V13 <dbl>, V14 <dbl>, V15 <dbl>,
## # V16 <dbl>, V17 <dbl>, V18 <dbl>, V19 <dbl>, V20 <dbl>, V21 <dbl>,
## # V22 <dbl>, V23 <dbl>, V24 <dbl>, V25 <dbl>, V26 <dbl>, V27 <dbl>,
## # V28 <dbl>, Amount <dbl>, Class <dbl>
View(data)
nrow(data)
## [1] 568630
ncol(data)
## [1] 31
#Check the structure of the dataset
str(data)
## spc_tbl_ [568,630 × 31] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:568630] 0 1 2 3 4 5 6 7 8 9 ...
## $ V1 : num [1:568630] -0.261 0.985 -0.26 -0.152 -0.207 ...
## $ V2 : num [1:568630] -0.47 -0.356 -0.949 -0.509 -0.165 ...
## $ V3 : num [1:568630] 2.496 0.558 1.729 1.747 1.527 ...
## $ V4 : num [1:568630] -0.0837 -0.4297 -0.458 -1.0902 -0.4483 ...
## $ V5 : num [1:568630] 0.1297 0.2771 0.0741 0.2495 0.1061 ...
## $ V6 : num [1:568630] 0.733 0.429 1.419 1.143 0.531 ...
## $ V7 : num [1:568630] 0.519 0.406 0.744 0.518 0.659 ...
## $ V8 : num [1:568630] -0.13 -0.1331 -0.0956 -0.0651 -0.2127 ...
## $ V9 : num [1:568630] 0.727 0.347 -0.261 -0.206 1.05 ...
## $ V10 : num [1:568630] 0.638 0.53 0.691 0.575 0.968 ...
## $ V11 : num [1:568630] -0.987 0.14 -0.273 -0.753 -1.203 ...
## $ V12 : num [1:568630] 0.293 1.564 0.659 0.737 1.03 ...
## $ V13 : num [1:568630] -0.941 0.574 0.805 0.593 1.439 ...
## $ V14 : num [1:568630] 0.549 0.628 0.617 0.56 0.241 ...
## $ V15 : num [1:568630] 1.805 0.706 3.069 -0.698 0.153 ...
## $ V16 : num [1:568630] 0.2156 0.7892 -0.5775 -0.0307 0.2245 ...
## $ V17 : num [1:568630] 0.512 0.404 0.887 0.243 0.366 ...
## $ V18 : num [1:568630] 0.334 0.202 0.239 2.179 0.292 ...
## $ V19 : num [1:568630] 0.124 -0.341 -2.366 -1.345 0.445 ...
## $ V20 : num [1:568630] 0.0912 -0.234 0.3617 -0.3782 0.2472 ...
## $ V21 : num [1:568630] -0.11055 -0.19494 -0.00502 -0.14693 -0.10698 ...
## $ V22 : num [1:568630] 0.2176 -0.6058 0.7029 -0.0382 0.7297 ...
## $ V23 : num [1:568630] -0.1348 0.0795 0.945 -0.214 -0.1617 ...
## $ V24 : num [1:568630] 0.166 -0.577 -1.155 -1.893 0.313 ...
## $ V25 : num [1:568630] 0.126 0.19 -0.606 1.004 -0.414 ...
## $ V26 : num [1:568630] -0.435 0.297 -0.313 -0.516 1.071 ...
## $ V27 : num [1:568630] -0.0812 -0.2481 -0.3003 -0.1653 0.0237 ...
## $ V28 : num [1:568630] -0.151 -0.0645 -0.2447 0.0484 0.4191 ...
## $ Amount: num [1:568630] 17982 6531 2514 5384 14279 ...
## $ Class : num [1:568630] 0 0 0 0 0 0 0 0 0 0 ...
## - attr(*, "spec")=
## .. cols(
## .. id = col_double(),
## .. V1 = col_double(),
## .. V2 = col_double(),
## .. V3 = col_double(),
## .. V4 = col_double(),
## .. V5 = col_double(),
## .. V6 = col_double(),
## .. V7 = col_double(),
## .. V8 = col_double(),
## .. V9 = col_double(),
## .. V10 = col_double(),
## .. V11 = col_double(),
## .. V12 = col_double(),
## .. V13 = col_double(),
## .. V14 = col_double(),
## .. V15 = col_double(),
## .. V16 = col_double(),
## .. V17 = col_double(),
## .. V18 = col_double(),
## .. V19 = col_double(),
## .. V20 = col_double(),
## .. V21 = col_double(),
## .. V22 = col_double(),
## .. V23 = col_double(),
## .. V24 = col_double(),
## .. V25 = col_double(),
## .. V26 = col_double(),
## .. V27 = col_double(),
## .. V28 = col_double(),
## .. Amount = col_double(),
## .. Class = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
#Summary statistics of the dataset
summary(data)
## id V1 V2 V3
## Min. : 0 Min. :-3.49558 Min. :-49.9666 Min. :-3.183760
## 1st Qu.:142157 1st Qu.:-0.56529 1st Qu.: -0.4867 1st Qu.:-0.649299
## Median :284315 Median :-0.09364 Median : -0.1359 Median : 0.000353
## Mean :284315 Mean : 0.00000 Mean : 0.0000 Mean : 0.000000
## 3rd Qu.:426472 3rd Qu.: 0.83266 3rd Qu.: 0.3436 3rd Qu.: 0.628538
## Max. :568629 Max. : 2.22905 Max. : 4.3619 Max. :14.125834
## V4 V5 V6 V7
## Min. :-4.95122 Min. :-9.95279 Min. :-21.11111 Min. : -4.3518
## 1st Qu.:-0.65602 1st Qu.:-0.29350 1st Qu.: -0.44587 1st Qu.: -0.2835
## Median :-0.07376 Median : 0.08109 Median : 0.07872 Median : 0.2334
## Mean : 0.00000 Mean : 0.00000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.70700 3rd Qu.: 0.43974 3rd Qu.: 0.49779 3rd Qu.: 0.5260
## Max. : 3.20154 Max. :42.71689 Max. : 26.16840 Max. :217.8730
## V8 V9 V10 V11
## Min. :-10.7563 Min. :-3.75192 Min. :-3.1633 Min. :-5.95472
## 1st Qu.: -0.1923 1st Qu.:-0.56874 1st Qu.:-0.5901 1st Qu.:-0.70145
## Median : -0.1145 Median : 0.09253 Median : 0.2626 Median :-0.04105
## Mean : 0.0000 Mean : 0.00000 Mean : 0.0000 Mean : 0.00000
## 3rd Qu.: 0.0473 3rd Qu.: 0.55926 3rd Qu.: 0.5925 3rd Qu.: 0.74777
## Max. : 5.9580 Max. :20.27006 Max. :31.7227 Max. : 2.51357
## V12 V13 V14 V15
## Min. :-2.0204 Min. :-5.95523 Min. :-2.1074 Min. :-3.86181
## 1st Qu.:-0.8311 1st Qu.:-0.69667 1st Qu.:-0.8732 1st Qu.:-0.62125
## Median : 0.1621 Median : 0.01761 Median : 0.2305 Median :-0.03926
## Mean : 0.0000 Mean : 0.00000 Mean : 0.0000 Mean : 0.00000
## 3rd Qu.: 0.7447 3rd Qu.: 0.68561 3rd Qu.: 0.7518 3rd Qu.: 0.66541
## Max. :17.9136 Max. : 7.18749 Max. :19.1695 Max. :14.53220
## V16 V17 V18 V19
## Min. :-2.2145 Min. :-2.4849 Min. :-2.42195 Min. :-7.80499
## 1st Qu.:-0.7163 1st Qu.:-0.6195 1st Qu.:-0.55605 1st Qu.:-0.56531
## Median : 0.1340 Median : 0.2716 Median : 0.08729 Median :-0.02598
## Mean : 0.0000 Mean : 0.0000 Mean : 0.00000 Mean : 0.00000
## 3rd Qu.: 0.6556 3rd Qu.: 0.5182 3rd Qu.: 0.54439 3rd Qu.: 0.56012
## Max. :46.6529 Max. : 6.9941 Max. : 6.78372 Max. : 3.83167
## V20 V21 V22 V23
## Min. :-78.1478 Min. :-19.38252 Min. :-7.73480 Min. :-30.29545
## 1st Qu.: -0.3502 1st Qu.: -0.16644 1st Qu.:-0.49049 1st Qu.: -0.23763
## Median : -0.1234 Median : -0.03743 Median :-0.02733 Median : -0.05969
## Mean : 0.0000 Mean : 0.00000 Mean : 0.00000 Mean : 0.00000
## 3rd Qu.: 0.2482 3rd Qu.: 0.14798 3rd Qu.: 0.46388 3rd Qu.: 0.15572
## Max. : 29.8728 Max. : 8.08708 Max. :12.63251 Max. : 31.70763
## V24 V25 V26 V27
## Min. :-4.0680 Min. :-13.612633 Min. :-8.22697 Min. :-10.4986
## 1st Qu.:-0.6516 1st Qu.: -0.554148 1st Qu.:-0.63189 1st Qu.: -0.3050
## Median : 0.0159 Median : -0.008193 Median :-0.01189 Median : -0.1729
## Mean : 0.0000 Mean : 0.000000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.7007 3rd Qu.: 0.550015 3rd Qu.: 0.67289 3rd Qu.: 0.3340
## Max. :12.9656 Max. : 14.621509 Max. : 5.62329 Max. :113.2311
## V28 Amount Class
## Min. :-39.03524 Min. : 50.01 Min. :0.0
## 1st Qu.: -0.23188 1st Qu.: 6054.89 1st Qu.:0.0
## Median : -0.01393 Median :12030.15 Median :0.5
## Mean : 0.00000 Mean :12041.96 Mean :0.5
## 3rd Qu.: 0.40959 3rd Qu.:18036.33 3rd Qu.:1.0
## Max. : 77.25594 Max. :24039.93 Max. :1.0
#Check for missing values
colSums(is.na(data))
## id V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
## 0 0 0 0 0 0 0 0 0 0 0
## V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21
## 0 0 0 0 0 0 0 0 0 0 0
## V22 V23 V24 V25 V26 V27 V28 Amount Class
## 0 0 0 0 0 0 0 0 0
#Data Visualization
# Visualize the class distribution
ggplot(data, aes(x = factor(Class))) +
geom_bar(fill = "blue") +
labs(title = "Class Distribution: Non-Fraud (0) vs. Fraud(0)", x = "Class", y = "Count")

#Boxplot to check for outliers
ggplot(data, aes(x = factor(Class), y = Amount)) +
geom_boxplot(fill = "lightblue") +
labs(title = "Transaction Amounts by Class", x = "Class (0 = Non-Fraud, 1 = Fraud)", y = "Transaction Amount") +
theme_minimal()

#Correlation plot
correlation_matrix <- cor(data)
corrplot(correlation_matrix, method = "color", type = "upper", order = "hclust", tl.cex = 0.7)

#Data Normalization
# Normalize numerical features (excluding 'Class' and 'id')
numerical_features <- data %>% select(-id, -Class)
normalized_data <- as.data.frame(lapply(numerical_features, function(x) (x - min(x)) / (max(x) - min(x))))
#Add the 'Class' and 'id' columns back to the dataset
data_normalized <- cbind(data %>% select(id, Class), normalized_data)
#Feature Engineering
#Calculate the total transaction amount per transaction
#Sum all numerical features
data_normalized$total_amount <- rowSums(data_normalized[, 3:31])
#Normalize 'total_amount' using min-max normalization
total_amount_min <- min(data_normalized$total_amount)
total_amount_max <- max(data_normalized$total_amount)
data_normalized$total_amount <- (data_normalized$total_amount - total_amount_min) / (total_amount_max - total_amount_min)
#Ensure 'Class' is a factor with levels 0 and 1
data_normalized$Class <- factor(data_normalized$Class, levels = c(0, 1))
head(data_normalized)
## id Class V1 V2 V3 V4 V5 V6
## 1 0 0 0.5650908 0.9110684 0.3281432 0.5970370 0.1914283 0.4620185
## 2 1 0 0.7827027 0.9131595 0.2161701 0.5546060 0.1942280 0.4555824
## 3 2 0 0.5651565 0.9022381 0.2837905 0.5511308 0.1903723 0.4765402
## 4 3 0 0.5840433 0.9103449 0.2848478 0.4735875 0.1937029 0.4706990
## 5 4 0 0.5744938 0.9166708 0.2721504 0.5523198 0.1909811 0.4577386
## 6 5 0 0.6150417 0.9171267 0.2527441 0.5204673 0.1971395 0.4562247
## V7 V8 V9 V10 V11 V12 V13
## 1 0.02191858 0.6357600 0.1864575 0.1089552 0.5866237 0.1160752 0.3814921
## 2 0.02141212 0.6355738 0.1706508 0.1058615 0.7197234 0.1798261 0.4968001
## 3 0.02292880 0.6378199 0.1453095 0.1104737 0.6709423 0.1344239 0.5143839
## 4 0.02191522 0.6396415 0.1476240 0.1071636 0.6143080 0.1383510 0.4982396
## 5 0.02254783 0.6308149 0.1998936 0.1184235 0.5610990 0.1530041 0.5626340
## 6 0.02233273 0.6379963 0.1637138 0.1036251 0.7074380 0.1453619 0.4310758
## V14 V15 V16 V17 V18 V19 V20
## 1 0.1248504 0.3080726 0.04972865 0.3161964 0.2993366 0.6814033 0.7242971
## 2 0.1285492 0.2483381 0.06146634 0.3047504 0.2850145 0.6414470 0.7212867
## 3 0.1280395 0.3767985 0.03349879 0.3556749 0.2891036 0.4673944 0.7268008
## 4 0.1253446 0.1720206 0.04468916 0.2877466 0.4997537 0.5551359 0.7199514
## 5 0.1103950 0.2182678 0.04991160 0.3008108 0.2947892 0.7089925 0.7257416
## 6 0.1287030 0.2404050 0.06048293 0.3066447 0.3024717 0.6498634 0.7227455
## V21 V22 V23 V24 V25 V26 V27
## 1 0.7015744 0.3904494 0.4864380 0.2485632 0.4866064 0.5625994 0.08419483
## 2 0.6985025 0.3500235 0.4898937 0.2049227 0.4888664 0.6154018 0.08284655
## 3 0.7054162 0.4142768 0.5038540 0.1710326 0.4606858 0.5714028 0.08242462
## 4 0.7002502 0.3778892 0.4851598 0.1276792 0.5176922 0.5567420 0.08351523
## 5 0.7017043 0.4155937 0.4860047 0.2571698 0.4674665 0.6713302 0.08504298
## 6 0.6987645 0.3533250 0.4877981 0.2017432 0.4659661 0.6122371 0.08539026
## V28 Amount total_amount
## 1 0.3343693 0.7474844 0.3941976
## 2 0.3351134 0.2701701 0.3527213
## 3 0.3335638 0.1026902 0.2832060
## 4 0.3360845 0.2223613 0.2782535
## 5 0.3392722 0.5931224 0.3942216
## 6 0.3364920 0.2855983 0.3114595
#Data Splitting
set.seed(123)
split = sample.split(data_normalized$Class, SplitRatio = 0.8)
training_data = subset(data_normalized, split == TRUE)
test_data= subset(data_normalized, split == FALSE)
nrow(training_data)
## [1] 454904
nrow(test_data)
## [1] 113726
#Data Modelling
library(caret)
## Loading required package: lattice
library(e1071)
#Logistic Regression
set.seed(123)
glm_model = glm(Class~. ,data = training_data, family = binomial(link = 'logit'))
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
pred_glm <- predict(glm_model, newdata = test_data, type = 'response')
#Naive Bayes
start_time_nb <- Sys.time()
nb_model <- naiveBayes(Class ~ ., data = training_data)
end_time_nb <- Sys.time()
time_nb <- end_time_nb - start_time_nb
pred_nb <- predict(nb_model, newdata = test_data)
pred_nb_prob <- predict(nb_model, newdata = test_data, type = "raw")[, 2]
#Model Evaluation
library(pROC)
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
library(reshape2)
##
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
##
## smiths
#Logistic Regression
#Convert pred_glm to factors with common levels
pred_glm <- factor(ifelse(pred_glm > 0.5, 1, 0), levels = c(0, 1))
#Create confusion matrix
confusion <- confusionMatrix(pred_glm, test_data$Class)
#Calculate accuracy
accuracy <- confusion$overall['Accuracy']
#Calculate precision
precision <- confusion$byClass['Pos Pred Value']
#Calculate recall (sensitivity)
recall <- confusion$byClass['Sensitivity']
#Calculate F1-score
f1_score <- confusion$byClass['F1']
#Calculate AUC-ROC using predicted probabilities
roc_auc <- roc(test_data$Class, as.numeric(pred_glm))
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc_roc <- auc(roc_auc)
#Print the metrics
cat("Logistic Regression Metrics:\n")
## Logistic Regression Metrics:
cat("Accuracy:", accuracy, "\n")
## Accuracy: 0.9984964
cat("Precision:", precision, "\n")
## Precision: 0.9981022
cat("Recall:", recall, "\n")
## Recall: 0.9988921
cat("F1-Score:", f1_score, "\n")
## F1-Score: 0.998497
cat("AUC-ROC:", auc_roc, "\n")
## AUC-ROC: 0.9984964
#Model Evaluation
#Naive Bayes
#Create confusion matrix
confusion_nb <- confusionMatrix(pred_nb, test_data$Class)
#Calculate accuracy
accuracy_nb <- confusion_nb$overall['Accuracy']
#Calculate precision
precision_nb <- confusion_nb$byClass['Pos Pred Value']
#Calculate recall (sensitivity)
recall_nb <- confusion_nb$byClass['Sensitivity']
#Calculate F1-score
f1_score_nb <- confusion_nb$byClass['F1']
#Calculate AUC-ROC
nb_probabilities <- predict(nb_model, newdata = test_data, type = "raw")
nb_roc <- roc(test_data$Class, nb_probabilities[, 2])
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc_roc_nb <- auc(nb_roc)
#Print the metrics
cat("Naive Bayes Metrics:\n")
## Naive Bayes Metrics:
cat("Accuracy:", accuracy_nb, "\n")
## Accuracy: 0.9314053
cat("Precision:", precision_nb, "\n")
## Precision: 0.8915563
cat("Recall:", recall_nb, "\n")
## Recall: 0.9822908
cat("F1-Score:", f1_score_nb, "\n")
## F1-Score: 0.9347268
cat("AUC-ROC:", auc_roc_nb, "\n")
## AUC-ROC: 0.9889559
#Compare model performance
#Create a data frame for model evaluation comparison
evaluation_comparison <- data.frame(
Model = c("Logistic Regression", "Naive Bayes"),
Accuracy = c(accuracy, accuracy_nb),
Precision = c(precision, precision_nb),
Recall = c(recall, recall_nb),
F1_Score = c(f1_score, f1_score_nb),
AUC_ROC = c(auc_roc, auc_roc_nb)
)
#Melt the data frame for ggplot2
evaluation_comparison_melted <- melt(evaluation_comparison, id.vars = 'Model')
#Plot
ggplot(evaluation_comparison_melted, aes(x = Model, y = value, fill = variable)) +
geom_bar(stat = 'identity', position = 'dodge') +
labs(title = 'Model Evaluation Comparison', x = 'Model', y = 'Score') +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
