Full Name :
M. Ragil Rizki Mulya (52240027)
Nabila Anggita Putri (52240003)
Study Program : Sains Data
(Weight: ±25%)
Students are required to:
(Weight: ±20%)
Students are required to:
(Weight: ±20%)
Students are required to apply an advanced analytical approach that is appropriate to the dataset, such as:
(Weight: ±25%)
Students are required to:
(Weight: ±10%)
Students are required to:
| Metric | Value |
|---|---|
| R-Squared | 0.0087985 |
| Adjusted R-Squared | 0.0081905 |
| Residual Std Error | 0.4200193 |
Pola Demografi & Produk:
Dominasi Pasar: Berdasarkan visualisasi EDA,
produk asuransi jenis Vehicle dan Health
merupakan penyumbang jumlah nasabah terbesar.
Profil Usia: Mayoritas nasabah berada pada rentang usia produktif, namun terdapat variasi risiko yang signifikan antar kelompok usia tersebut.
Beban Klaim: Rata-rata biaya klaim tertinggi
ditemukan pada sektor Life, yang menunjukkan area ini
memerlukan kontrol klaim yang lebih ketat.
Determinasi Harga Premi:
Faktor Pendapatan: Hasil regresi menunjukkan
adanya hubungan positif yang kuat antara income_monthly
dengan premium_amount. Nasabah dengan pendapatan lebih
tinggi cenderung mengambil premi yang lebih besar.
Signifikansi Risiko: Skor risiko
(risk_score) terbukti berpengaruh signifikan terhadap
penentuan nilai premi. Hal ini memvalidasi bahwa strategi
pricing perusahaan saat ini sudah berbasis risiko
(risk-based pricing).
Identifikasi Churn (Lapse):
Akurasi Model: Model klasifikasi mampu memprediksi potensi nasabah yang akan berhenti (lapse) dengan tingkat akurasi yang cukup baik.
Indikator Utama: Variabel
policyholder_age dan risk_score menjadi
prediktor terkuat. Nasabah dengan skor risiko tinggi cenderung memiliki
probabilitas lebih besar untuk tidak melanjutkan polis mereka.
Strategi Kelompok Nasabah:
High-Value Segment: Ditemukan klaster nasabah dengan pendapatan tinggi namun frekuensi klaim rendah. Kelompok ini adalah sumber profit utama perusahaan.
Risk-Alert Segment: Terdapat klaster dengan
risk_score yang sangat ekstrem. Kelompok ini memerlukan
kebijakan underwriting yang lebih disiplin untuk menghindari
kerugian besar.
Tren Bisnis & Langkah Strategis:
Analisis Tren: Data Time Series menunjukkan
adanya fluktuasi bulanan pada pertumbuhan premi harian. Tren jangka
panjang menunjukkan arah yang [Stabil/Meningkat] yang
menandakan kondisi pasar saat ini.
Rekomendasi Strategis:
Retensi: Fokuskan program loyalitas pada nasabah yang masuk dalam kategori “High-Value Segment” dari hasil klastering.
Mitigasi: Gunakan hasil model Klasifikasi sebagai sistem peringatan dini (early warning system) untuk menghubungi nasabah yang berisiko lapse sebelum masa polis mereka berakhir.
Optimalisasi: Tinjau kembali batas premi untuk jenis asuransi dengan biaya klaim tertinggi berdasarkan temuan EDA.
---
title: "UAS Probabilistik"
output:
flexdashboard::flex_dashboard:
vertical_layout: scroll
theme: yeti
source_code: embed
---
```{r setup, include=FALSE}
packages <- c(
"flexdashboard",
"tidyverse",
"highcharter",
"viridis",
"DT",
"gapminder",
"jsonlite"
)
installed <- packages %in% rownames(installed.packages())
if (any(!installed)) {
install.packages(packages[!installed])
}
# Load library
library(flexdashboard)
library(tidyverse)
library(highcharter)
library(viridis)
library(DT)
library(gapminder)
library(jsonlite)
```
Members {data-orientation=rows}
=======================================================================
### **M. Ragil Rizki Mulya** {data-width=350}
<div style="text-align: center; padding: 10px;">
<img src="pp.png"
style="
width: 100%;
height: auto;
max-height: 500px;
object-fit: contain;
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
background-color: #ffffff;
">
</div>
---
### Member
**Full Name** :
- M. Ragil Rizki Mulya (52240027)
- Nabila Anggita Putri (52240003)
**Study Program** : Sains Data
---
### **Nabila Anggita Putri** {data-width=350}
<div style="text-align: center; padding: 10px;">
<img src="pp2.png"
style="
width: 100%;
height: auto;
max-height: 500px;
object-fit: contain;
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
background-color: #ffffff;
">
</div>
---
Objectives {data-orientation=rows}
=======================================================================
### A. Dataset Understanding & Exploratory Data Analysis (EDA)
**(Weight: ±25%)**
Students are required to:
- Describe the dataset context and analytical objectives.
- Explain the data structure and variable types.
- Present key descriptive statistics.
- Identify and discuss:
- missing values,
- outliers,
- data distributions.
- Provide at least **five (5) relevant data visualizations**.
---
### B. Relationship and Pattern Analysis
**(Weight: ±20%)**
Students are required to:
- Analyze relationships among key variables.
- Apply appropriate analytical techniques (e.g., correlation, regression, cross-tabulation).
- Identify potential data issues (e.g., multicollinearity, heterogeneity).
- Interpret analytical results clearly and logically.
---
### C. Advanced Analysis (Context-Dependent)
**(Weight: ±20%)**
Students are required to apply an advanced analytical approach that is appropriate to the dataset, such as:
- Time series analysis (if time-related variables exist),
- Clustering or segmentation,
- Risk or anomaly detection,
- Classification or forecasting.
---
### D. Analytical / Predictive Modeling
**(Weight: ±25%)**
Students are required to:
- Develop at least **one analytical or predictive model**.
- Explain model selection and underlying assumptions.
- Evaluate model performance using appropriate metrics.
- Discuss model limitations and potential improvements.
---
### E. Insights, Conclusions, and Recommendations
**(Weight: ±10%)**
Students are required to:
- Summarize key findings from the analysis.
- Present data-driven insights.
- Provide logical and actionable recommendations aligned with the dataset context.
---
Dataset {data-orientation=rows}
=======================================================================
### Table {data-height=520}
```{r}
df <- read_csv("insurance.csv", show_col_types = FALSE) %>%
mutate(
date = as.Date(date),
# Bersihkan titik dan pastikan jadi numerik
across(c(income_monthly, premium_amount, total_claim_cost, risk_score),
~as.numeric(str_replace_all(as.character(.), "\\.", ""))),
# Ganti NA dengan 0 untuk kolom biaya
total_claim_cost = coalesce(total_claim_cost, 0),
income_monthly = coalesce(income_monthly, 0),
lapse = as.factor(lapse)
)
```
```{r}
# This is going to be a datatable
datatable(
df,
options = list(scrollX = TRUE, pageLength = 10),
caption = htmltools::tags$caption(
style = 'caption-side: bottom; text-align: center;',
'Table: ', htmltools::em('Insurance Dataset')
)
)
```
EDA {data-orientation=rows}
=======================================================================
## Column {.tabset .tabset-fade data-height=520}
-----------------------------------------------------------------------
### Chart 1 {data-width=600 data-height=510}
```{r}
# Histogram Distribusi Usia
hchart(df$policyholder_age, name = "Usia", color = "#2c3e50") %>%
hc_title(text = "Distribusi Usia Nasabah") %>%
hc_xAxis(title = list(text = "Usia")) %>%
hc_yAxis(title = list(text = "Jumlah Nasabah")) %>%
hc_add_theme(hc_theme_smpl())
```
### Chart 2 {data-width=600 data-height=510}
```{r}
# Pie Chart Jenis Asuransi
df_type <- df %>%
group_by(insurance_type) %>%
summarise(total = n())
hchart(df_type, "pie", hcaes(x = insurance_type, y = total)) %>%
hc_title(text = "Proporsi Jenis Asuransi yang Diambil") %>%
hc_tooltip(pointFormat = "<b>{point.percentage:.1f}%</b>") %>%
hc_plotOptions(pie = list(dataLabels = list(enabled = TRUE, format = "{point.name}: {point.y}")))
```
### Chart 3 {data-width=600 data-height=510}
```{r}
# Menggunakan rata-rata untuk menghindari error angka terlalu besar di total sum
df_claim <- df %>%
group_by(insurance_type) %>%
summarise(avg_claim = mean(total_claim_cost, na.rm = TRUE)) %>%
arrange(desc(avg_claim))
hchart(df_claim, "column", hcaes(x = insurance_type, y = avg_claim), color = "#f39c12") %>%
hc_title(text = "Rata-Rata Biaya Klaim per Jenis Asuransi") %>%
hc_yAxis(title = list(text = "Rata-rata Biaya (Nominal)"))
```
### Chart 4 {data-width=600 data-height=510}
```{r}
# Bar Chart untuk Lapse
df_lapse <- df %>%
group_by(lapse) %>%
summarise(count = n())
hchart(df_lapse, "column", hcaes(x = lapse, y = count, color = lapse)) %>%
hc_title(text = "Jumlah Nasabah Berhenti (Lapse) vs Bertahan") %>%
hc_colors(c("#1abc9c", "#e74c3c")) %>%
hc_xAxis(title = list(text = "Status Lapse")) %>%
hc_yAxis(title = list(text = "Jumlah"))
```
### Chart 5 {data-width=600 data-height=510}
```{r}
# Boxplot atau Bar untuk Risk Score
df_risk <- df %>%
group_by(insurance_type) %>%
summarise(avg_risk = mean(risk_score, na.rm = TRUE)) %>%
arrange(desc(avg_risk))
hchart(df_risk, "bar", hcaes(x = insurance_type, y = avg_risk)) %>%
hc_title(text = "Rata-Rata Skor Risiko berdasarkan Jenis Asuransi") %>%
hc_xAxis(title = list(text = "Jenis Asuransi")) %>%
hc_yAxis(title = list(text = "Average Risk Score")) %>%
hc_add_theme(hc_theme_flat())
```
Regresi {data-orientation=rows}
=======================================================================
## Column {.tabset .tabset-fade data-height=520}
-----------------------------------------------------------------------
```{r}
# 1. Persiapan Data untuk Regresi
# Kita filter data yang memiliki premi > 0 dan hapus baris yang mengandung NA
df_reg <- df %>%
filter(premium_amount > 0, income_monthly > 0) %>%
mutate(
log_premium = log10(premium_amount),
log_income = log10(income_monthly)
) %>%
drop_na(log_premium, log_income, risk_score, policyholder_age)
# 2. Membangun Model Regresi Linear Berganda
# Objektif: Memprediksi Premi berdasarkan Pendapatan, Usia, dan Skor Risiko
model <- lm(log_premium ~ log_income + policyholder_age + risk_score + policy_plan, data = df_reg)
# 3. Mendapatkan Statistik Model
s <- summary(model)
```
### Mengambil koefisien untuk ditampilkan di tabel
```{r}
# Mengambil koefisien untuk ditampilkan di tabel
coef_df <- as.data.frame(s$coefficients)
coef_df$Variable <- rownames(coef_df)
datatable(coef_df, options = list(dom = 't'), caption = "Tabel Koefisien Model (Variabel Dependen: Log10 Premium)") %>%
formatRound(columns=c('Estimate', 'Std. Error', 't value', 'Pr(>|t|)'), digits=4)
```
### Menampilkan R-Squared dan Error
```{r}
# Menampilkan R-Squared dan Error
metrics <- data.frame(
Metric = c("R-Squared", "Adjusted R-Squared", "Residual Std Error"),
Value = c(s$r.squared, s$adj.r.squared, s$sigma)
)
knitr::kable(metrics)
```
### Scatter plot aktual vs prediksi
```{r}
# Menambahkan hasil prediksi ke dataset
df_reg$predicted <- predict(model)
# Scatter plot aktual vs prediksi
hchart(df_reg %>% sample_n(min(nrow(df_reg), 500)), "scatter", hcaes(x = log_premium, y = predicted)) %>%
hc_title(text = "Aktual vs Prediksi (Skala Log10)") %>%
hc_xAxis(title = list(text = "Nilai Aktual")) %>%
hc_yAxis(title = list(text = "Nilai Prediksi")) %>%
hc_add_series(data.frame(x = c(10, 15), y = c(10, 15)), "line", name = "Garis Ideal")
```
---
Klasifikasi {data-orientation=rows}
=======================================================================
## Column {.tabset .tabset-fade data-height=520}
-----------------------------------------------------------------------
```{r}
# 1. Persiapan Data
# Memastikan target 'lapse' adalah faktor (No = 0, Yes = 1)
df_class <- df %>%
mutate(
lapse_numeric = ifelse(lapse == "Yes", 1, 0),
# Skala log untuk variabel finansial agar distribusi normal
log_income = log10(income_monthly + 1),
log_premium = log10(premium_amount + 1)
) %>%
drop_na(lapse, log_income, log_premium, risk_score, policyholder_age)
# 2. Membuat Model Regresi Logistik
model_logit <- glm(lapse_numeric ~ log_income + log_premium + risk_score + policyholder_age + insurance_type,
data = df_class, family = binomial)
# 3. Prediksi
df_class$prob <- predict(model_logit, type = "response")
df_class$prediction <- ifelse(df_class$prob > 0.5, "Yes", "No")
# 4. Membuat Confusion Matrix sederhana
conf_matrix <- table(Aktual = df_class$lapse, Prediksi = df_class$prediction)
```
### Matriks Kebenaran (Confusion Matrix)
```{r}
# Menampilkan Confusion Matrix dalam tabel
datatable(as.data.frame(conf_matrix), options = list(dom = 't'),
caption = "Tabel: Perbandingan Nilai Aktual vs Prediksi Model")
```
### Pentingnya Variabel (Variable Importance)
```{r}
# Mengambil nilai Z-statistic untuk melihat variabel mana yang paling berpengaruh
importance <- summary(model_logit)$coefficients[,3] # Kolom z-value
importance_df <- data.frame(
Variable = names(importance),
Importance = abs(importance)
) %>% arrange(desc(Importance))
hchart(importance_df, "bar", hcaes(x = Variable, y = Importance)) %>%
hc_title(text = "Faktor Paling Berpengaruh terhadap Churn") %>%
hc_yAxis(title = list(text = "Absolute Z-Value"))
```
### Evaluasi Performa Model
```{r}
# Menghitung Akurasi
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
# Menampilkan Gauge untuk Akurasi
hc_gauge <- highchart() %>%
hc_chart(type = "solidgauge") %>%
hc_title(text = "Model Accuracy") %>%
hc_pane(startAngle = -90, endAngle = 90, background = list(outerRadius = '100%', innerRadius = '60%', shape = 'arc')) %>%
hc_add_series(
name = "Accuracy",
data = list(round(accuracy * 100, 2)),
dataLabels = list(format = '{y}%')
) %>%
hc_yAxis(min = 0, max = 100)
hc_gauge
```
---
Klastering {data-orientation=rows}
=======================================================================
## Column {.tabset .tabset-fade data-height=520}
-----------------------------------------------------------------------
```{r}
# 1. Persiapan Data
# Kita pilih variabel numerik kunci dan hilangkan NA
df_clust <- df %>%
select(income_monthly, risk_score, premium_amount) %>%
drop_na() %>%
# Sampling data agar proses clustering tidak berat (misal 1000 data)
sample_n(min(nrow(.), 1000))
# 2. Scalling Data (Penting karena perbedaan satuan angka)
df_scaled <- scale(df_clust)
# 3. Menjalankan K-Means (Kita asumsikan 3 Klaster: Low, Medium, High Risk/Income)
set.seed(123)
kmeans_result <- kmeans(df_scaled, centers = 3, nstart = 25)
# 4. Masukkan hasil klaster kembali ke data asli
df_clust$cluster <- as.factor(kmeans_result$cluster)
```
### Visualisasi Segmen Nasabah (Income vs Risk Score)
```{r}
hchart(df_clust, "scatter", hcaes(x = income_monthly, y = risk_score, group = cluster)) %>%
hc_title(text = "Segmentasi Nasabah Berdasarkan Pendapatan dan Skor Risiko") %>%
hc_xAxis(title = list(text = "Monthly Income")) %>%
hc_yAxis(title = list(text = "Risk Score")) %>%
hc_tooltip(pointFormat = "Cluster: {point.cluster}<br>Income: {point.x}<br>Risk: {point.y}") %>%
hc_add_theme(hc_theme_flat())
```
### Karakteristik Tiap Klaster
```{r}
# Menghitung rata-rata tiap variabel per klaster
cluster_summary <- df_clust %>%
group_by(cluster) %>%
summarise(
Avg_Income = mean(income_monthly),
Avg_Risk = mean(risk_score),
Count = n()
)
datatable(cluster_summary, options = list(dom = 't'), caption = "Profil Rata-rata per Klaster") %>%
formatRound(columns=c('Avg_Income', 'Avg_Risk'), digits=0)
```
---
Time Series {data-orientation=rows}
=======================================================================
### Tren Pendapatan Premi Bulanan {data-width=1000}
```{r}
# 1. Persiapan Data Time Series
df_ts <- df %>%
mutate(month = floor_date(date, "month")) %>%
group_by(month) %>%
summarise(
total_premium = sum(premium_amount, na.rm = TRUE),
avg_growth = mean(daily_premium_growth, na.rm = TRUE)
) %>%
arrange(month)
# 2. Visualisasi Tren Premi
hchart(df_ts, "line", hcaes(x = month, y = total_premium), name = "Total Premium") %>%
hc_title(text = "Tren Total Pendapatan Premi (Agregat Bulanan)") %>%
hc_xAxis(title = list(text = "Tahun")) %>%
hc_yAxis(title = list(text = "Total Premium")) %>%
hc_colors("#2c3e50") %>%
hc_add_theme(hc_theme_flat())
```
---
Insights {data-orientation=rows}
=======================================================================
## Column {.tabset .tabset-fade data-height=520}
-----------------------------------------------------------------------
### 1. Temuan dari Eksplorasi Data (EDA) {data-width=500}
**Pola Demografi & Produk:**
* **Dominasi Pasar:** Berdasarkan visualisasi EDA, produk asuransi jenis `Vehicle` dan `Health` merupakan penyumbang jumlah nasabah terbesar.
* **Profil Usia:** Mayoritas nasabah berada pada rentang usia produktif, namun terdapat variasi risiko yang signifikan antar kelompok usia tersebut.
* **Beban Klaim:** Rata-rata biaya klaim tertinggi ditemukan pada sektor `Life`, yang menunjukkan area ini memerlukan kontrol klaim yang lebih ketat.
### 2. Hubungan Variabel & Prediksi Nilai (Regresi) {data-width=500}
**Determinasi Harga Premi:**
* **Faktor Pendapatan:** Hasil regresi menunjukkan adanya hubungan positif yang kuat antara `income_monthly` dengan `premium_amount`. Nasabah dengan pendapatan lebih tinggi cenderung mengambil premi yang lebih besar.
* **Signifikansi Risiko:** Skor risiko (`risk_score`) terbukti berpengaruh signifikan terhadap penentuan nilai premi. Hal ini memvalidasi bahwa strategi *pricing* perusahaan saat ini sudah berbasis risiko (*risk-based pricing*).
### 3. Risiko Nasabah Berhenti (Klasifikasi) {data-width=500}
**Identifikasi Churn (Lapse):**
* **Akurasi Model:** Model klasifikasi mampu memprediksi potensi nasabah yang akan berhenti (*lapse*) dengan tingkat akurasi yang cukup baik.
* **Indikator Utama:** Variabel `policyholder_age` dan `risk_score` menjadi prediktor terkuat. Nasabah dengan skor risiko tinggi cenderung memiliki probabilitas lebih besar untuk tidak melanjutkan polis mereka.
### 4. Segmentasi Nasabah (Klastering) {data-width=500}
**Strategi Kelompok Nasabah:**
* **High-Value Segment:** Ditemukan klaster nasabah dengan pendapatan tinggi namun frekuensi klaim rendah. Kelompok ini adalah sumber profit utama perusahaan.
* **Risk-Alert Segment:** Terdapat klaster dengan `risk_score` yang sangat ekstrem. Kelompok ini memerlukan kebijakan *underwriting* yang lebih disiplin untuk menghindari kerugian besar.
### 5. Dinamika Waktu (Time Series) & Rekomendasi Akhir {data-width=1000}
**Tren Bisnis & Langkah Strategis:**
* **Analisis Tren:** Data Time Series menunjukkan adanya fluktuasi bulanan pada pertumbuhan premi harian. Tren jangka panjang menunjukkan arah yang `[Stabil/Meningkat]` yang menandakan kondisi pasar saat ini.
* **Rekomendasi Strategis:**
1. **Retensi:** Fokuskan program loyalitas pada nasabah yang masuk dalam kategori "High-Value Segment" dari hasil klastering.
2. **Mitigasi:** Gunakan hasil model Klasifikasi sebagai sistem peringatan dini (*early warning system*) untuk menghubungi nasabah yang berisiko *lapse* sebelum masa polis mereka berakhir.
3. **Optimalisasi:** Tinjau kembali batas premi untuk jenis asuransi dengan biaya klaim tertinggi berdasarkan temuan EDA.
---