install.packages(“caret”) install.packages(“corrplot”) install.packages(“factoextra”)
#Load required libraries
library(caret)
library(ggplot2)
library(corrplot)
library(factoextra)
#Load data set
file_path <- "C:\\Users\\fardm\\OneDrive\\Desktop\\PhD\\american_bankruptcy.csv"
bank_data <- read.csv("C:\\Users\\fardm\\OneDrive\\Desktop\\PhD\\american_bankruptcy.csv")
Two variables are character type, one is integer and rest are of numeric type
#changing type of the character variables
bank_data$company_name <- as.factor(bank_data$company_name)
bank_data$status_label <- as.factor(bank_data$status_label)
#Structure of the data
str(bank_data)
## 'data.frame': 78682 obs. of 21 variables:
## $ company_name: Factor w/ 8971 levels "C_1","C_10","C_100",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ status_label: Factor w/ 2 levels "alive","failed": 1 1 1 1 1 1 1 1 1 1 ...
## $ year : int 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 ...
## $ X1 : num 511 486 437 396 432 ...
## $ X2 : num 833 714 526 497 523 ...
## $ X3 : num 18.4 18.6 22.5 27.2 26.7 ...
## $ X4 : num 89 64.4 27.2 30.7 47.5 ...
## $ X5 : num 336 321 287 260 247 ...
## $ X6 : num 35.2 18.5 -58.9 -12.4 3.5 ...
## $ X7 : num 128.3 115.2 77.5 66.3 104.7 ...
## $ X8 : num 373 377 365 143 309 ...
## $ X9 : num 1024 874 639 606 652 ...
## $ X10 : num 741 702 710 687 709 ...
## $ X11 : num 180 180 218 165 249 ...
## $ X12 : num 70.66 45.79 4.71 3.57 20.81 ...
## $ X13 : num 191 160 112 110 129 ...
## $ X14 : num 164 125 150 204 131 ...
## $ X15 : num 201 204 140 124 132 ...
## $ X16 : num 1024 874 639 606 652 ...
## $ X17 : num 401 362 400 392 408 ...
## $ X18 : num 935 810 612 576 604 ...
There are 21 variables in the data set and 78682 observations
#checking for missing values
apply(is.na(bank_data),2,sum)
## company_name status_label year X1 X2 X3
## 0 0 0 0 0 0
## X4 X5 X6 X7 X8 X9
## 0 0 0 0 0 0
## X10 X11 X12 X13 X14 X15
## 0 0 0 0 0 0
## X16 X17 X18
## 0 0 0
#Checking for Outliers
boxplot(bank_data$X17)
#Removing outliers
outliers <- boxplot(bank_data$X1, plot = FALSE)$out
bank_data <- bank_data[-which(bank_data$X1 %in% outliers),]
No missing value in the data set
Univariate graphical analysis
#status_label variable
ggplot(data = bank_data,aes(status_label)) +
geom_bar(fill= "blue",alpha=0.5)+
theme(legend.position = "None") + theme_minimal()
# Combine all numeric variables into a long format
long_data <- reshape2::melt(bank_data[4:21])
# Plot using ggplot2
ggplot(long_data, aes(x = value)) +
geom_histogram(fill= "blue",alpha=0.5) +
xlim(-10,200) +
facet_wrap(~variable, scales = "free") +
theme_minimal()
#
ggplot(data = bank_data,aes(X1, fill=status_label)) +
geom_density(alpha=0.4)+ xlim(-2,5)+
theme(legend.position = "None") + theme_minimal()
#correlatio plot
cor_mat <- cor(bank_data[4:21])
corrplot(cor_mat)
Numeric variables are not uniformly distributed.
#outcome variable
table(bank_data$status_label)
##
## alive failed
## 62917 4791
#mean values of the numeric variables
mean_var <- sapply(bank_data[4:17],mean)
#max values of the numeric variables
max_var <- sapply(bank_data[4:17],max)
#min values of the numeric variables
min_var <- sapply(bank_data[4:17],min)
stat <- data.frame(cbind(mean_var,max_var,min_var))
stat
## mean_var max_var min_var
## X1 168.867816 1050.431 -7.7600
## X2 300.304403 15232.449 -366.6450
## X3 26.332285 3010.068 0.0000
## X4 57.376636 3131.000 -4512.1350
## X5 38.478249 903.294 0.0000
## X6 3.740006 24728.000 -7751.2480
## X7 55.685755 940.216 -0.0060
## X8 632.407727 253635.500 0.0001
## X9 446.377034 16199.300 -1964.9990
## X10 544.480343 29253.741 0.0010
## X11 159.463576 19973.000 -0.0230
## X12 31.044197 2491.000 -5083.0000
## X13 146.072754 4476.700 -4367.5710
## X14 98.564795 7423.688 0.0010
#scaling numeric variables
bank_data[4:21] <- scale(bank_data[4:21])
bank_data$company_name <- as.numeric(bank_data$company_name)
# Set random seed
set.seed(123)
# Creating index for splitting the data
index <- createDataPartition(bank_data$status_label, p = 0.8, list = FALSE)
# Split the data into training (80%) and test sets (20%)
trainset <- bank_data[index, ]
testset <- bank_data[-index, ]
# Build a 2-means cluster model
kmeans_model <- kmeans(trainset[-2], centers = 2)
#center of each cluster for each numeric variable
kmeans_model$centers
## company_name year X1 X2 X3 X4
## 1 2072.394 2006.741 0.05599586 0.08291335 0.02540138 0.05774558
## 2 6434.380 2007.593 -0.04829211 -0.07217393 -0.02081999 -0.05103554
## X5 X6 X7 X8 X9 X10
## 1 0.1002371 0.03467935 0.06246193 0.009633919 0.08130507 0.04383865
## 2 -0.0896018 -0.03289809 -0.05600331 -0.010462544 -0.07054073 -0.04040342
## X11 X12 X13 X14 X15 X16
## 1 0.01900338 0.05897118 0.05398887 0.04787952 0.08266085 0.08130507
## 2 -0.01472996 -0.05307925 -0.04630921 -0.04446276 -0.08277815 -0.07054073
## X17 X18
## 1 0.03891287 0.07929746
## 2 -0.03495843 -0.06858631
Positive values indicate that, on average, cluster 1 has higher values for the variables, while negative values indicate that cluster 2 has higher values.
#cluster plot
fviz_cluster(kmeans_model, data = trainset[-2]) +
theme_minimal()
• Discuss how well your clustering performed. • Calculate precision (positive predictive value) on your test set and interpret. • Calculate recall (sensitivity) on your test set and interpret. • Calculate accuracy on your test set and interpret. • Calculate the F1-scores on your test set and interpr
kmeans_test <- kmeans(testset[-2], centers = 2)
# Assign cluster labels based on majority class
cluster_labels <- ifelse(kmeans_test$cluster == 1, "alive", "failed")
# Confusion matrix
conf_matrix <- table(cluster_labels, testset$status_label)
# Precision
precision <- conf_matrix["alive", "failed"] / sum(conf_matrix["alive", ])
precision
## [1] 0.07458308
#precision is approximately 0.075, suggesting that out of the instances predicted as "alive," only about 7.5% are correctly predicted, while the majority are false positives.
# Recall
recall <- conf_matrix["alive", "failed"] / sum(conf_matrix[, "alive"])
recall
## [1] 0.03838512
# recall value is 0.038, indicating that the model captures only about 3.8% of the actual "alive" instances.
# Accuracy
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
accuracy
## [1] 0.4776604
# accuracy is approximately 0.478, suggesting that the model is correct in its predictions for about 47.8% of the instances. However, accuracy can be misleading in imbalanced datasets
# F1-Score
f1_score <- 2 * (precision * recall) / (precision + recall)
f1_score
## [1] 0.05068472
#F1-score is approximately 0.051, indicating a low overall performance, likely due to the low precision and recall values.