Di Indonesia, jumlah kendaraan bermotor, termasuk mobil, terus meningkat seiring dengan pertumbuhan ekonomi dan perkembangan infrastruktur. Namun, peningkatan ini juga diikuti oleh risiko kecelakaan lalu lintas yang lebih tinggi. Dalam konteks ini, perusahaan asuransi otomotif berhadapan dengan tantangan dalam mengelola klaim asuransi dengan efisien, akurat, dan tepat waktu.
Dengan adopsi Metode Machine Learning dalam industri asuransi, tentu akan membuka peluang untuk mengolah big data yang telah dikumpulkan dari pemegang polis dan klaim sebelumnya. Analisis lebih mendalam atas data (sampel) ini dapat memberikan wawasan berharga mengenai pola klaim, faktor-faktor risiko, dan variabel-variabel prediksi yang berkaitan dengan kemungkinan terjadinya kecelakaan dan klaim di masa depan.
Pada analisis ini, dataset yang digunakan adalah open-data yang tersedia pada website Kaggle, yaitu data dari sebuah startup yang menyediakan asuransi mobil. Ini merupakan salah satu merek asuransi mobil terbaik yang dikenal dengan rasio penyelesaian klaim tertinggi. Perusahaan ini diluncurkan pada bulan Oktober 2020 dan mendapatkan pemegang polis awalnya dengan menyediakan proses klaim yang bebas dari kerumitan, penerbitan polis instan, dan penyelesaian klaim dengan cakupan minimum.
Adapun data tersebut disediakan perusahaan untuk mengoptimalkan biaya asuransi dengan mengidentifikasi pemegang polis yang kemungkinan akan mengajukan klaim dalam 6 bulan mendatang.
Adapun setiap variabel tersebut merupakan representasi dari setiap penjelasan pada tabel di bawah. Secara lebih lengkap, data tersebut dapat dilihat melalui link kaggle berikut berikut
Sebelum melakukan analisis, langkah awal yang harus dilakukan adalah membersihkan dan menyiapkan data agar sesuai dengan kebutuhan model yang akan digunakan. Berikut beberapa library yang digunakan dalam analisis ini.
library(dplyr) #manipulasi data
library(ggplot2) #visualisasi data
library(corrplot) #matriks korelasi
library(car) #analisis regresi dan lainnya
library(viridis)
library(reshape2)
library(gridExtra)
library(magrittr)
library(plotly)
library(moments)
library(cluster)
library(ggiraphExtra)
library(partykit)
Kesesuaian tipe data menjadi salah satu faktor penting dari
keberhasilan analisis. Setelah dikaji, ternyata beberapa variabel tidak
bertipe factor sehingga dilakukan konversi tipe data, baik pada
data latih maupun data validasi. Adapun konversi tersebut tidak berlaku
untuk variabel policy_id,policy_tenure,
age_of_car, age_of_policyholder, dan
population_density.
cols_to_convert <- c("area_cluster", "make", "segment", "model", "fuel_type", "max_torque", "max_power",
"engine_type", "airbags", "is_esc", "is_adjustable_steering", "is_tpms", "is_parking_sensors",
"is_parking_camera", "rear_brakes_type", "displacement", "cylinder", "transmission_type",
"gear_box", "steering_type", "is_front_fog_lights", "is_rear_window_wiper",
"is_rear_window_washer", "is_rear_window_defogger", "is_brake_assist",
"is_power_door_locks", "is_central_locking", "is_power_steering",
"is_driver_seat_height_adjustable", "is_day_night_rear_view_mirror", "is_ecw",
"is_speed_alert", "ncap_rating", "is_claim")
for (col in cols_to_convert) {
train[[col]] <- as.factor(train[[col]])
}
for (col in cols_to_convert) {
if (col != "is_claim") {
test[[col]] <- as.factor(test[[col]])
}
}
Adapun beberapa alasan mengapa perlu dilakukan seleksi variabel, yaitu:
Dari total 44 variabel yang digunakan untuk data latih, disimpulkan
bahwa variabel policy_id sebaiknya tidak digunakan untuk
kepentingan analisis karena merupakan data unique
train <- select(train, -policy_id)
test <- select(test, -policy_id)
# Melihat jumlah nilai NA dalam setiap kolom
na_counts <- sapply(train, function(x) sum(is.na(x)))
# Menampilkan kolom-kolom yang memiliki nilai NA
cols_with_na <- names(na_counts[na_counts > 0])
print(cols_with_na)
## character(0)
Dari hasil tersebut, dapat diketahui bahwa data sudah tidak memiliki nilai NULL sehingga tidak perlu dilakukan inputasi/eliminasi data seperti pada umumnya
Perlu diketahui bahwa tidak semua data sudah dalam format yang sesuai sehingga perlu dilakukan penyesuaian untuk bisa melakukan visualisasi data. Adapun beberapa bentuk yang akan diurai, yakni seperti berikut.
max_torque_new <- train["max_torque"]
max_torque_new <- transform(max_torque_new,
torque = as.numeric(sub("Nm@.*", "", max_torque)),
rpm = as.numeric(sub(".*@(.*)rpm", "\\1", max_torque)))
max_torquerpm_counts <- as.data.frame(table(max_torque_new$rpm))
colnames(rpm_counts) <- c("RPM", "Count")
ggplot(rpm_counts, aes(x = factor(RPM), y = Count, fill = Count)) +
geom_bar(stat = "identity") +
scale_fill_gradient(low = "yellow", high = "darkblue") + # Specify the gradient colors
labs(title = "Bar Chart of RPM Counts from `max_torque`", x = "RPM", y = "Count") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
area_clustercluster_counts <- data.frame(
area_cluster = levels(train$area_cluster),
n = table(train$area_cluster))
color_scale <- colorRampPalette(viridis::viridis(length(cluster_counts$area_cluster)))
colors <- color_scale(length(cluster_counts$area_cluster))
pie_chart <- plot_ly(cluster_counts, labels = ~area_cluster, values = ~n.Freq, type = "pie",
marker = list(colors = colors, line = list(color = 'black')))
pie_chart
Melalui grafik di atas, dapat diketahui bahwa sebaran nilai terbanyak terdapat pada klaster daerah C8, C2, dan C5. Indikasi tersebut tentu menjadi bukti dominansi sehingga perlu dilakukan analisis lebih lanjut ataupun bentuk penanganan lainnya sebelum dianalisis. Sebaran tersebut juga bisa menjadi jawaban bahwa sebaran datanya mungkin belum mengikuti sebaran normal.
selected_cols <- select(train, is_esc, is_adjustable_steering, is_tpms, is_parking_sensors, is_parking_camera)
count_yes <- colSums(selected_cols == "Yes", na.rm = TRUE)
count_no <- colSums(selected_cols == "No", na.rm=TRUE)
# Create a data frame with the counts
data_counts <- data.frame(
Feature = names(count_yes),
Yes = count_yes,
No = count_no
)
data_long <- melt(data_counts, id.vars = "Feature") #change format data wide to long
bar_chart <- ggplot(data_long, aes(x = Feature, y = value, fill = variable)) +
geom_bar(stat = "identity") +
coord_flip() + # Flip the coordinates to make it horizontal
labs(x = "Count", y = "Feature") +
scale_fill_viridis(discrete = TRUE, option = "D", alpha = 0.9) + # Adjust alpha to make it softer
ggtitle("Stacked Horizontal Bar Chart with Yes/No Counts") +
theme_minimal()
bar_chart
Indikasi yang serupa juga ditunjukkan melalui grafik di atas. Oleh karena itu, dilakukan pengecekan terlebih dahulu. Lebih lanjut, jika data terbukti tidak menyebar mengikuti sebaran normal, dilakukan proses transformasi dan standardisasi data. Akan tetapi, variabel kategorikal atau variabel yang menggambarkan kategori atau label biasanya tidak perlu mengalami transformasi seperti ini karena mereka memiliki sifat yang berbeda. Oleh karena itu, sebelumnya perlu dilakukan filtrasi variabel dengan tipe numerik saja.
# Periksa distribusi dari masing-masing variabel numerik
numeric_vars <- c("policy_tenure","age_of_car", "age_of_policyholder" ,"population_density", "width", "height", "gross_weight")
# Menampilkan summary dari masing-masing variabel numerik
for (var in numeric_vars) {
print(paste("Skewness ", var, ":", round(skewness(train[[var]]), 2)))
}
## [1] "Skewness policy_tenure : 0.05"
## [1] "Skewness age_of_car : 1.09"
## [1] "Skewness age_of_policyholder : 0.64"
## [1] "Skewness population_density : 1.67"
## [1] "Skewness width : -0.49"
## [1] "Skewness height : 1.04"
## [1] "Skewness gross_weight : 0.55"
Berdasarkan hasil skewness, variabel-variabel dapat dikelompokkan
sebagai berikut: 1. Variabel yang memerlukan transformasi lebih lanjut:
age_of_car, age_of_policyholder,
population_density, dan height 2. Variabel
yang tidak memerlukan transformasi tambahan:“policy_tenure”, “width”,
“gross_weight” 3. Adapun variabel yang memerlukan transformasi lebih
lanjutan, seperti age_of_car,
age_of_policyholder, population_density, dan
height, transformasi seperti logaritma atau kuadrat bisa
dipertimbangkan untuk mendekati distribusi yang lebih simetris.
Transformasi ini dapat diterapkan pada variabel dengan skewness
yang tinggi, seperti pada variabel population_density,
height, dan width. Transformasi ini akan
membantu mendekati distribusi data ke kondisi yang lebih simetris.
# Identifikasi kolom-kolom numerik
numeric_cols <- sapply(train, is.numeric)
# Melakukan transformasi akar kuadrat (sqrt) untuk kolom-kolom numerik di train_x
for (col in names(train)[numeric_cols]) {
train[[col]] <- sqrt(train[[col]])
}
for (col in names(test)[numeric_cols]) {
test[[col]] <- sqrt(test[[col]])
}
# Melakukan standarisasi pada kolom-kolom numerik
train[numeric_cols] <- scale(train[numeric_cols])
test[numeric_cols] <- scale(test[numeric_cols])
datatable(train, options = list(scrollX = TRUE, pageLength =5))
## Warning in instance$preRenderHook(instance): It seems your data is too
## big for client-side DataTables. You may consider server-side processing:
## https://rstudio.github.io/DT/server.html