library(readxl) #Membaca file dari excel
library(rmarkdown) #Membuat laporan dinamis yang dapat ditampilkan dengan baik di format HTML
library(VIM)#Membuat grafik agregasi missing data
## Loading required package: colorspace
## Loading required package: grid
## VIM is ready to use.
## Suggestions and bug-reports can be submitted at: https://github.com/statistikat/VIM/issues
##
## Attaching package: 'VIM'
## The following object is masked from 'package:datasets':
##
## sleep
library(mice) #Menangani data yang memiliki nilai yang hilang (missing data)
##
## Attaching package: 'mice'
## The following object is masked from 'package:stats':
##
## filter
## The following objects are masked from 'package:base':
##
## cbind, rbind
library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
#Membagi data menjadi set pelatihan dan pengujian secara stratified, menjaga proporsi kelas dalam setiap set.
#Menghitung confusion matrix dan metrik kinerja lainnya dari model.
library(randomForest) #Membangun model random forest
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
##
## margin
file_path <- "D:/R SEI/Level Risiko Investasi.xlsx"
data <- read_excel(file_path, sheet = "Training")
file_path <- "D:/R SEI/Level Risiko Investasi.xlsx"
data.tes <- read_excel(file_path, sheet = "Testing")
paged_table(as.data.frame(data))
paged_table(as.data.frame(data.tes))
Melakukan pegimporan data dari excel yang disimpan dalam folder D, file R SEI, dengan nama Risiko Investasi dan menyimpannya dalam variabel file_path.
Membaca file excel yang sudah tersimpan di variabel file_path hanya pada bagian sheet Training dan menyimpannya dalam variabel data.
Membaca file excel yang sudah tersimpan di variabel file_path hanya pada bagian sheet Testing dan menyimpannya dalam variabel data.tes.
Mengonversi objek pada variabel data menjadi data frame, kemudian menampilkan data frame yang terdiri dari kolom Country, X1 hingga X14, dan Risk Level.
Mengonversi objek pada variabel data.tes menjadi data frame, kemudian menampilkan data frame yang terdiri dari kolom Country dan X1 hingga X14.
colSums(is.na(data))
## Country X1 X2 X3 X4 X5 X6
## 0 12 0 0 0 0 0
## X7 X8 X9 X10 X11 X12 X13
## 0 7 0 0 17 0 0
## X14 Risk Level
## 11 0
aggr(data, col = c('yellow', 'green'))
Berdasarkan hasil di atas pada kolom X1 ada 12 nilai yang kosong, kolom
X8 ada 7 nilai yang kosong, kolom X11 ada 17 nilai yang kosong, dan X14
terdapat 11 nilai yang kosong. Selanjutnya nilai-nilai yang kosong
tersebut harus diisi agar pemodelan dapat dilakukan.
data_clean <- data[ , !(names(data) %in% c("Country", "Risk Level"))]
paged_table(as.data.frame(data_clean))
Pemisahan kolom Country dan Risk Level dilakukan karena kedua kolom tersebut tidak terlibat dalam proses imputasi (pengisian nilai yang hilang).
Dapat dilihat pada variabel data_clean untuk kolom Country dan Risk Level sudah tidak ada.
imputed_data <- mice(data_clean, method = "pmm", m = 5)
##
## iter imp variable
## 1 1 X1 X8 X11 X14
## 1 2 X1 X8 X11 X14
## 1 3 X1 X8 X11 X14
## 1 4 X1 X8 X11 X14
## 1 5 X1 X8 X11 X14
## 2 1 X1 X8 X11 X14
## 2 2 X1 X8 X11 X14
## 2 3 X1 X8 X11 X14
## 2 4 X1 X8 X11 X14
## 2 5 X1 X8 X11 X14
## 3 1 X1 X8 X11 X14
## 3 2 X1 X8 X11 X14
## 3 3 X1 X8 X11 X14
## 3 4 X1 X8 X11 X14
## 3 5 X1 X8 X11 X14
## 4 1 X1 X8 X11 X14
## 4 2 X1 X8 X11 X14
## 4 3 X1 X8 X11 X14
## 4 4 X1 X8 X11 X14
## 4 5 X1 X8 X11 X14
## 5 1 X1 X8 X11 X14
## 5 2 X1 X8 X11 X14
## 5 3 X1 X8 X11 X14
## 5 4 X1 X8 X11 X14
## 5 5 X1 X8 X11 X14
completed_data <- complete(imputed_data)
paged_table(as.data.frame(completed_data))
Imputasi (pengisian data yang hilang) pada data_clean menggunakan metode pmm (predictive mean matching). Ini adalah metode di mana nilai yang hilang digantikan oleh nilai terdekat yang diprediksi berdasarkan variabel lainnya. PMM biasanya digunakan karena menghindari prediksi yang ekstrem dan menjaga distribusi asli dari data. m = 5: Parameter ini menentukan bahwa akan dilakukan 5 kali imputasi berganda, yaitu 5 dataset yang berbeda akan dibuat, masing-masing dengan nilai hilang yang diisi berdasarkan prediksi yang berbeda-beda.
completed_data adalah variabel yang akan menyimpan dataset yang sudah diisi lengkap dengan nilai pengganti untuk nilai yang hilang, sehingga dataset tidak lagi memiliki missing values.
Kolom iter menunjukkan pengulangan dari proses imputasi. mice melakukan beberapa pengulangan pada setiap dataset untuk memperbaiki prediksi nilai-nilai yang hilang. Dalam output ini, ada 5 ulangan (iter = 1, 2, 3, 4, 5).
Kolom imp terdapat nilai dari 1 sampai 5 yang menunjukkan dataset pertama hingga kelima yang sedang diimputasi pada setiap ulangan.
Kolom variabel menunjukkan variabel yang sedang diimputasi dalam setiap ulangan. Pada setiap ulangan, variabel-variabel yang berisi missing values diisi berdasarkan metode yang telah dipilih (dalam hal ini Predictive Mean Matching, “pmm”). Variabel X1, X8, X11, dan X14 adalah variabel yang memiliki missing values, dan mereka diimputasi pada setiap ulangan untuk setiap dataset.
Berdasarkan hasil di atas (completed_data), apabila dicek nilai yang hilang pada kolom X1, X8, X11, dan X14 sudah terisi.
completed_data$Risk_Level <- data$`Risk Level`
paged_table(as.data.frame(completed_data))
Penggabungan kembali Risk Level kedalam data set karena nantinya Risk Level ini akan diprediksi. Dapat dilihat dari hasil di atas bahwa Risk Level sudah masuk lagi kedalam completed_data.
colSums(is.na(completed_data))
## X1 X2 X3 X4 X5 X6 X7
## 0 0 0 0 0 0 0
## X8 X9 X10 X11 X12 X13 X14
## 0 0 0 0 0 0 0
## Risk_Level
## 0
aggr(completed_data, col = c('yellow', 'green'))
Pengecekan kembali untuk memastikan bahwa semua kolom nilainya sudah
terisi.
Dapat dilihat dari hasil di atas bahwa semua kolom sudah 0, yang artinya tidak ada nilai yang kosong.
colSums(is.na(data.tes))
## Country X1 X2 X3 X4 X5 X6 X7 X8 X9
## 0 1 0 0 0 0 0 0 2 0
## X10 X11 X12 X13 X14
## 0 4 0 0 1
aggr(data.tes, col = c('yellow', 'green'))
data_testingclean <- data.tes[ , !(names(data.tes) %in% c("Country"))]
paged_table(as.data.frame(data_testingclean))
imputed_datatesting <- mice(data_testingclean, method = "pmm", m = 5)
##
## iter imp variable
## 1 1 X1 X8 X11 X14
## 1 2 X1 X8 X11 X14
## 1 3 X1 X8 X11 X14
## 1 4 X1 X8 X11 X14
## 1 5 X1 X8 X11 X14
## 2 1 X1 X8 X11 X14
## 2 2 X1 X8 X11 X14
## 2 3 X1 X8 X11 X14
## 2 4 X1 X8 X11 X14
## 2 5 X1 X8 X11 X14
## 3 1 X1 X8 X11 X14
## 3 2 X1 X8 X11 X14
## 3 3 X1 X8 X11 X14
## 3 4 X1 X8 X11 X14
## 3 5 X1 X8 X11 X14
## 4 1 X1 X8 X11 X14
## 4 2 X1 X8 X11 X14
## 4 3 X1 X8 X11 X14
## 4 4 X1 X8 X11 X14
## 4 5 X1 X8 X11 X14
## 5 1 X1 X8 X11 X14
## 5 2 X1 X8 X11 X14
## 5 3 X1 X8 X11 X14
## 5 4 X1 X8 X11 X14
## 5 5 X1 X8 X11 X14
## Warning: Number of logged events: 30
completed_datatesting <- complete(imputed_datatesting)
paged_table(as.data.frame(completed_datatesting))
colSums(is.na(completed_datatesting))
## X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0
aggr(completed_datatesting, col = c('yellow', 'green'))
completed_data$Risk_Level <- as.factor(completed_data$Risk_Level)
str(completed_data)
## 'data.frame': 100 obs. of 15 variables:
## $ X1 : num 17.5 18.2 18.7 19.1 14 ...
## $ X2 : num 38675 40105 76038 27883 4251 ...
## $ X3 : num 172.8 103.5 31 24.8 89.6 ...
## $ X4 : num 0.68 1.77 2.63 1.29 1.44 ...
## $ X5 : num 1.221 0.87 1.489 1.753 0.256 ...
## $ X6 : num 1.79 2.66 1.85 2.23 4.75 ...
## $ X7 : num -2.084 -0.725 -1.901 -1.135 2.332 ...
## $ X8 : num 55 103 103 103 167 ...
## $ X9 : num -26.5 -13.6 -56.2 24.8 47.3 ...
## $ X10 : num 2.86 352.91 199.93 10.11 12.65 ...
## $ X11 : num 8 8.15 8.15 3.26 6.6 ...
## $ X12 : num 23.1 24.9 20.4 21.7 19.4 ...
## $ X13 : num 26.9 32.5 31 17.3 15.1 ...
## $ X14 : num 3 2.45 0.12 4.5 18.5 ...
## $ Risk_Level: Factor w/ 2 levels "high","low": 2 2 2 2 1 1 1 2 2 1 ...
Pengubahan tipe data Risk Level menjadi faktor dilakukan karena akan melakukan klasifikasi.
Dapat dilihat dari hasil di atas bahwa Risk Level sudah bertipe data faktor dan dilakukan penyimbolan dimana 1 berarti high dan 2 berarti low.
X <- completed_data[ , !(names(completed_data) %in% c("Risk_Level"))]
y <- completed_data$Risk_Level
paged_table(as.data.frame(X))
paged_table(as.data.frame(y))
Pemisahan fitur (X) dan target (y) karena:
Fitur (X): Digunakan sebagai input untuk melatih model. Ini adalah variabel independen atau prediktor yang digunakan oleh model untuk mempelajari pola.
Target (y): Adalah variabel yang ingin diprediksi oleh model. Dalam kasus klasifikasi, ini adalah kategori atau label (seperti “high” atau “low” untuk risiko investasi).
Dapat dilihat dari hasil diatas X akan menyimpan fitur (variabel independen) yaitu X1 hingga X14 dan y akan menyimpan target yaitu Risk Level.
set.seed(123) #Memastikan bahwa pemisahan data dilakukan secar konsisten
trainIndex <- createDataPartition(y, p = 0.8, list = FALSE)
X_train <- X[trainIndex, ]
X_test <- X[-trainIndex, ]
y_train <- y[trainIndex]
y_test <- y[-trainIndex]
paged_table(as.data.frame(X_train))
paged_table(as.data.frame(X_test))
paged_table(as.data.frame(y_train))
paged_table(as.data.frame(y_test))
Data dibagi menjadi training dan testing dengan 80% sebagai training dan 20% sebagai testing. Pemilihan mana yang akan menjadi training dan mana yang akan menjadi testing dilakukan secara acak melalui fungsi createDataPartition dengan proporsi kategori target (y) tetap terjaga (stratified sampling). Pemisahan ini dilakukan berdasarkan baris bukan kolam.
Dapat dilihat dari hasil di atas:
X_train akan berisi 80% data dari X yang akan digunakan untuk training.
X_test akan berisi 20% data dari X yang akan digunakan untuk menguji model.
y_train akan berisi 80% data dari y yang akan digunakan untuk melatih model.
y_test akan berisi 20% data dari y yang akan digunakan untuk menguji akurasi model pada data uji.
rf_model <- randomForest(X_train, y_train)
rf_model
##
## Call:
## randomForest(x = X_train, y = y_train)
## Type of random forest: classification
## Number of trees: 500
## No. of variables tried at each split: 3
##
## OOB estimate of error rate: 18.52%
## Confusion matrix:
## high low class.error
## high 38 6 0.1363636
## low 9 28 0.2432432
Dapat dilihat dari hasil di atas:
Model random forest ini digunakan untuk classification.
Model random forest membangun 500 pohon keputusan dalam proses pelatihannya.
Pada setiap pemisahan (split) dalam setiap pohon, model secara acak memilih 3 variabel dari sekian banyak fitur yang tersedia untuk menentukan pemisahan terbaik. Ini adalah mekanisme penting dalam random forest yang membantu mengurangi overfitting dan memberikan hasil yang lebih akurat.
Tingkat kesalahan OOB sebesar 17.28% berarti bahwa sekitar 17.28% dari prediksi yang dibuat oleh model salah ketika diuji dengan data OOB.Hal ini dapat dikatakan bahwa model bekerja cukup baik, artinya sekitar 82.72% prediksi model benar secara keseluruhan.
Baris pertama (high)
Model memprediksi 38 data dengan benar sebagai “high”
Model memprediksi 6 data salah sebagai “low” padahal sebenarnya adalah “high”
Class error: 0.1363636 berarti sekitar 13.64% dari data yang sebenarnya “high” diprediksi salah oleh model.
Baris kedua (low)
Model memprediksi 29 data dengan benar sebagai “low”
Model memprediksi 8 data salah sebagai “high” padahal sebenarnya adalah “low”
Class error: 0.2162162 berarti sekitar 21.62% dari data yang sebenarnya “low” diprediksi salah oleh model.
Model lebih baik dalam memprediksi kelas high dibandingkan kelas low, karena error rate untuk kelas “high” (13.64%) lebih kecil dibandingkan dengan kelas “low” (21.62%).
saveRDS(rf_model, "model_datatraining.rds")
Penyimpanan dilakukan agar model yang sudah dilatih dapat digunakan kembali untuk memprediksi “Risk Level” pada data lain pada file yang berbeda.
Penyimpanan rf_model diberi nama “model_datatraining.rds”
rf_pred <- predict(rf_model, X_test)
paged_table(as.data.frame(rf_pred))
Hasil di atas adalah prediksi Risk Level yang di dapatkan melalui model random forest.
comparison <- data.frame(Actual = y_test,Predicted = rf_pred)
comparison
## Actual Predicted
## 1 low low
## 5 high high
## 6 high high
## 12 high high
## 22 low low
## 30 high low
## 32 low low
## 42 high high
## 50 low low
## 51 low high
## 58 high high
## 62 low low
## 66 high high
## 68 low low
## 71 high high
## 73 high high
## 75 low low
## 93 high high
## 94 low low
Dapat dilihat dari hasil di atas bahwa terdapat satu nilai yang salah prediksi dimana seharusnya low tetapi di prediksi high. Hal ini sesuai dengan kesimpulan model yang menyebutkan bahwa model lebih baik dalam memprediksi kelas high dibandingkan kelas low, karena error rate untuk kelas “high” (13.64%) lebih kecil dibandingkan dengan kelas “low” (21.62%).
confusionMatrix(rf_pred, y_test)
## Confusion Matrix and Statistics
##
## Reference
## Prediction high low
## high 9 1
## low 1 8
##
## Accuracy : 0.8947
## 95% CI : (0.6686, 0.987)
## No Information Rate : 0.5263
## P-Value [Acc > NIR] : 0.0007916
##
## Kappa : 0.7889
##
## Mcnemar's Test P-Value : 1.0000000
##
## Sensitivity : 0.9000
## Specificity : 0.8889
## Pos Pred Value : 0.9000
## Neg Pred Value : 0.8889
## Prevalence : 0.5263
## Detection Rate : 0.4737
## Detection Prevalence : 0.5263
## Balanced Accuracy : 0.8944
##
## 'Positive' Class : high
##
Dapat dilihat dari hasil di atas:
Baris pertama (Prediction: high):
Model memprediksi 10 sampel sebagai “high” dan memang benar, karena data aslinya juga “high”
Model memprediksi 1 sampel sebagai “high”, padahal sebenarnya sampel tersebut adalah “low”
Baris kedua (Prediction: low):
Model memprediksi 0 sampel sebagai “low” yang sebenarnya adalah “high”
Model memprediksi 8 sampel sebagai “low” dan memang benar, karena data aslinya juga “low”
Accuracy: 0.9474 (atau 94.74%)
Ini adalah proporsi prediksi yang benar (baik untuk kelas “high” maupun “low”) dari total data. Model berhasil memprediksi dengan benar sekitar 94.74% dari seluruh data.
95% CI: (0.7397, 0.9987)
Interval kepercayaan 95% memberikan rentang kemungkinan untuk akurasi model pada populasi yang lebih besar. Artinya, kita bisa yakin 95% bahwa akurasi sebenarnya dari model ini berada antara 73.97% hingga 99.87%.
NIR: 0.5263 (atau 52.63%)
No Information Rate adalah tingkat akurasi jika model selalu menebak kategori dengan jumlah terbanyak. Dalam hal ini, jika model selalu memprediksi kategori “high”, tingkat akurasi dasarnya adalah 52.63% (proporsi kelas “high” dalam data).
P-Value [Acc > NIR]: 9.149e-05
P-value ini menunjukkan bahwa akurasi model jauh lebih baik dibandingkan NIR (p-value yang sangat rendah menunjukkan perbedaan signifikan).
Kappa: 0.8939
Nilai 0.8939 menunjukkan bahwa model ini memiliki kinerja yang sangat baik, dengan prediksi yang jauh lebih baik daripada tebakan acak.
Mcnemar’s Test P-Value: 1
P-value 1 menunjukkan tidak ada perbedaan signifikan antara prediksi yang salah untuk kelas “high” dan kelas “low”, artinya model memiliki kinerja yang seimbang.
Sensitivity: 1.0000 (atau 100%)
Model mampu mengidentifikasi semua sampel “high” dengan benar.
Specificity: 0.8889 (atau 88.89%)
Model mampu mengidentifikasi 88.89% sampel “low” dengan benar, tetapi ada beberapa kesalahan dalam memprediksi “low”.
Pos Pred Value (PPV): 0.9091 (atau 90.91%)
Dari semua sampel yang diprediksi sebagai “high”, 90.91% prediksi adalah benar.
Neg Pred Value (NPV): 1.0000 (atau 100%)
Dari semua sampel yang diprediksi sebagai “low”, 100% prediksi adalah benar.
Prevalence: 0.5263 (atau 52.63%)
Prevalence menunjukkan proporsi kelas “high” dalam dataset secara keseluruhan. Ini menunjukkan bahwa sekitar 52.63% dari data memiliki kelas “high”.
Detection Rate: 0.5263 (atau 52.63%)
Detection rate mengukur proporsi sampel yang benar-benar diklasifikasikan sebagai positif dibandingkan dengan seluruh sampel.
Sebanyak 52.63% sampel benar-benar diklasifikasikan sebagai “high”
Detection Prevalence: 0.5789 (atau 57.89%)
Detection Prevalence mengukur proporsi sampel yang diprediksi sebagai positif (kelas “high”) dibandingkan dengan total sampel.
Sebanyak 57.89% dari sampel dalam dataset diprediksi oleh model sebagai “high”, baik prediksi tersebut benar (true positive) atau salah (false positive).
Balanced Accuracy: 0.9444 (atau 94.44%)
Balanced accuracy adalah rata-rata dari sensitivity dan specificity. Ini memberikan ukuran yang lebih seimbang untuk model yang menangani kelas yang mungkin tidak seimbang.
Model memiliki tingkat akurasi yang seimbang untuk mendeteksi kedua kelas (high dan low) dengan performa sangat baik.
Secara keseluruhan, model ini menunjukkan kinerja yang sangat kuat dan seimbang untuk mendeteksi kedua kelas, dengan kesalahan yang minimal.
rf_pred.tes <- predict(rf_model,completed_datatesting )
paged_table(as.data.frame(rf_pred.tes))