knitr::opts_chunk$set(echo = TRUE)
library(readxl)
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(ggplot2)
library(skimr)
library(corrplot)
## corrplot 0.95 loaded
Dataset yang saya pakai adalah Dataset Biaya Asuransi Kesehatan yang saya ambil dari kaggle
data <- read_excel("insurance.xlsx")
Jumlah baris: 1338
Jumlah kolom: 7
Data Wrangling Jenis variabel: Numerik: age, bmi, charges, premium, expenses Kategorik: sex, smoker, region, discount_eligibility
Data Cleaning Di dalam dataset ini tidak ada miss value. Di dalam dataset ini ada 1 data yang duplikat jadi saya hapus 1 baris.
data <- data %>% distinct()
Deteksi Outlier menggunakan boxplot di variabel BMI dan Charges, dalam boxplot charges cukup banyak outlier tapi karena data charges penting untuk dianalisis lebih lanjut jadi saya biarkan dan untuk boxplot BMI punya sedikit outlier jadi saya biarkan juga.
boxplot(data$bmi,
main = "Boxplot of BMI",
col = "grey",
ylab = "BMI")
boxplot(data$charges,
main = "Boxplot of Charges",
col = "grey",
ylab = "Medical Charges (USD)")
Nilai BMI sebagian besar berada antara sekitar 22 hingga 35. Terdapat beberapa outlier di sisi atas (nilai tinggi) yang artinya beberapa peserta memiliki BMI jauh di atas rata-rata. Biaya medis (charges) sangat bervariasi, dengan banyak peserta memiliki biaya di bawah 20.000 USD.
Terdapat banyak outlier di sisi atas, menunjukkan sejumlah peserta memiliki biaya medis yang sangat tinggi (>40.000 USD). Distribusi ini menunjukkan right-skewed, artinya mayoritas peserta membayar rendah, tapi ada sedikit yang sangat tinggi (kemungkinan karena kondisi kesehatan tertentu).
summary(data)
## age sex bmi children
## Min. :18.00 Length:1337 Min. :15.96 Min. :0.000
## 1st Qu.:27.00 Class :character 1st Qu.:26.29 1st Qu.:0.000
## Median :39.00 Mode :character Median :30.40 Median :1.000
## Mean :39.22 Mean :30.66 Mean :1.096
## 3rd Qu.:51.00 3rd Qu.:34.70 3rd Qu.:2.000
## Max. :64.00 Max. :53.13 Max. :5.000
## smoker region charges
## Length:1337 Length:1337 Min. : 1122
## Class :character Class :character 1st Qu.: 4746
## Mode :character Mode :character Median : 9386
## Mean :13279
## 3rd Qu.:16658
## Max. :63770
Usia peserta cukup tersebar merata dari muda hingga tua. Rata-rata BMI sedikit di atas ambang obesitas (BMI > 30). Ada beberapa nilai ekstrem (outlier). Mayoritas peserta memiliki 0–2 anak. Distribusi biaya medis sangat skewed ke atas, dengan banyak peserta membayar sedikit, tapi ada yang sangat mahal (outlier).
skim(data)
Name | data |
Number of rows | 1337 |
Number of columns | 7 |
_______________________ | |
Column type frequency: | |
character | 3 |
numeric | 4 |
________________________ | |
Group variables | None |
Variable type: character
skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
---|---|---|---|---|---|---|---|
sex | 0 | 1 | 4 | 6 | 0 | 2 | 0 |
smoker | 0 | 1 | 2 | 3 | 0 | 2 | 0 |
region | 0 | 1 | 9 | 9 | 0 | 4 | 0 |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
---|---|---|---|---|---|---|---|---|---|---|
age | 0 | 1 | 39.22 | 14.04 | 18.00 | 27.00 | 39.00 | 51.00 | 64.00 | ▇▅▅▆▆ |
bmi | 0 | 1 | 30.66 | 6.10 | 15.96 | 26.29 | 30.40 | 34.70 | 53.13 | ▂▇▇▂▁ |
children | 0 | 1 | 1.10 | 1.21 | 0.00 | 0.00 | 1.00 | 2.00 | 5.00 | ▇▂▂▁▁ |
charges | 0 | 1 | 13279.12 | 12110.36 | 1121.87 | 4746.34 | 9386.16 | 16657.72 | 63770.43 | ▇▂▁▁▁ |
numeric_data <- data %>%
select(where(is.numeric))
for (col in names(numeric_data)) {
print(
ggplot(data, aes_string(x = col)) +
geom_histogram(bins = 30, fill = "skyblue", color = "black") +
labs(title = paste("Histogram of", col), x = col, y = "Count")
)
}
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Usia tersebar dari sekitar 18 hingga 64 tahun. Jumlah individu paling
banyak berada di usia sekitar 18–20 tahun, dan jumlahnya relatif merata
untuk kelompok usia lainnya, meskipun sedikit menurun pada usia di atas
60 tahun.
Nilai BMI sebagian besar berada di rentang 25 hingga 35 kg/m², dengan puncaknya sekitar 28–30 kg/m². Distribusi BMI menyerupai distribusi normal, namun agak miring ke kanan.
Mayoritas individu tidak memiliki anak (anak = 0), dengan frekuensi jauh lebih tinggi dibanding jumlah anak lainnya. Semakin banyak anak, frekuensinya semakin menurun.
Sebagian besar individu memiliki biaya asuransi di bawah 10.000. Distribusi charges sangat miring ke kanan, artinya hanya sedikit orang yang membayar biaya yang sangat tinggi (hingga 60.000 lebih).
numeric_data <- data[, c("age", "bmi", "children", "charges")]
cor_matrix <- cor(numeric_data, use = "complete.obs")
cor_matrix
## age bmi children charges
## age 1.00000000 0.10934361 0.04153621 0.29830821
## bmi 0.10934361 1.00000000 0.01275466 0.19840083
## children 0.04153621 0.01275466 1.00000000 0.06738935
## charges 0.29830821 0.19840083 0.06738935 1.00000000
corrplot(cor_matrix, method = "color", type = "upper",
addCoef.col = "black", tl.col = "black", tl.srt = 45)
Korelasi age dan charges : Korelasi positif sedang (0.3) Semakin tua,
cenderung membayar biaya medis lebih tinggi.
Korelasi bmi dan charges: Korelasi lemah (0.2) Ada pengaruh, tapi tidak kuat.
Korelasi children dan charges: Korelasi sangat lemah (0.07) Jumlah anak tidak berpengaruh besar terhadap biaya medis.
Hubungan antar variabel selain itu juga lemah → tidak ada multikolinearitas yang signifikan antar variabel numerik.
data$age_group <- cut(data$age,
breaks = c(0, 25, 45, 65),
labels = c("Remaja", "Dewasa", "Lansia"),
right = FALSE)
Remaja: usia < 25 Dewasa: usia 25–44 Lansia: usia 45 ke atas
data$bmi_status <- cut(data$bmi,
breaks = c(0, 18.5, 25, 30, Inf),
labels = c("Underweight", "Normal", "Overweight", "Obese"),
right = FALSE)
< 18.5 Underweight 18.5–24.9 Normal 25–29.9 Overweight ≥ 30 Obese
Rata-rata per grup dengan dplyr::group_by() %>% summarise().
data %>%
group_by(smoker, sex) %>%
summarise(mean_charges = mean(charges), .groups = "drop")
## # A tibble: 4 × 3
## smoker sex mean_charges
## <chr> <chr> <dbl>
## 1 no female 8762.
## 2 no male 8100.
## 3 yes female 30679.
## 4 yes male 33042.
Rata-rata biaya medis jauh lebih tinggi pada peserta yang merokok dibandingkan yang tidak. Perokok laki-laki memiliki rata-rata tertinggi, di atas 30.000 USD.
data %>%
group_by(smoker, sex) %>%
summarise(total_charges = sum(charges), .groups = "drop")
## # A tibble: 4 × 3
## smoker sex total_charges
## <chr> <chr> <dbl>
## 1 no female 4792977.
## 2 no male 4179445.
## 3 yes female 3528085.
## 4 yes male 5253679.
Biaya medis untuk yang merokok dan tidak merokok tidak jauh berbeda. Biaya yang paling tinggi itu perokok laki laki yaitu lebih dari 5.000.000 USD.
Integrasi Data Saya menggabungkan data utama (Medical Insurance Cost Dataset) dengan dataset lain (Medical Cost Personal Datasets).Kedua dataset saya dapatkan dari Kaggle. Dalam kedua set tersebut memiliki kesamaan di data variabel age, bmi, children, sex, smoker dan region sehingga saya hanya menambahkan data variabel expenses dan premium dari data set kedua ke data set pertama. Kedua data set sama sama memiliki data berjumlah 1338.
Visualisasi Akhir Dalam poin kedua yaitu Preprocessing Data sudah ada 2 grafik boxplot charges dan BMI, juga ada histogram dari data numerik.
Interpretasi Singkat Variabel numerik seperti usia (age), BMI, dan biaya medis (charges) memiliki distribusi yang beragam, dengan biaya medis menunjukkan distribusi yang sangat skewed ke kanan. Hal ini menunjukkan bahwa sebagian besar peserta membayar biaya asuransi yang relatif rendah, namun ada beberapa peserta dengan biaya yang sangat tinggi (outlier). Outlier pada variabel BMI dan charges terdeteksi melalui boxplot. Meski ada banyak outlier, khususnya pada biaya medis, data tersebut tetap dipertahankan karena dianggap relevan untuk analisis lebih lanjut. Korelasi positif sedang antara usia dan biaya medis menunjukkan bahwa semakin tua peserta, cenderung biaya medisnya lebih tinggi. Sedangkan korelasi antara BMI dan jumlah anak dengan biaya medis relatif lemah. Penambahan variabel kategori seperti kelompok usia (age_group) dan status BMI (bmi_status) membantu dalam segmentasi data untuk analisis yang lebih terfokus. Rata-rata biaya medis lebih tinggi pada peserta yang merokok, terutama perokok laki-laki, yang dapat menjadi indikator risiko kesehatan. Dataset utama digabungkan dengan dataset kedua yang memiliki variabel tambahan, memperkaya informasi untuk analisis yang lebih komprehensif.
Manfaat Preprocessing Data Preprocessing data adalah tahap penting yang memberikan beberapa manfaat utama, yaitu: Membersihkan Data: Menghapus data duplikat dan memeriksa missing values memastikan dataset lebih akurat dan tidak bias oleh data yang berulang atau kosong. Mendeteksi dan Memahami Outlier: Identifikasi outlier membantu dalam mengambil keputusan apakah data ekstrem tersebut valid untuk analisis atau perlu ditangani khusus, sehingga hasil analisis lebih realistis dan dapat dipercaya. Transformasi Variabel: Penambahan variabel kategori (seperti age_group dan bmi_status) memudahkan segmentasi dan interpretasi hasil, serta memungkinkan analisis yang lebih kaya dan mendalam. Penggabungan Data: Integrasi dataset memperluas cakupan informasi, memungkinkan analisis yang lebih holistik dan meningkatkan akurasi model prediksi atau insight. Meningkatkan Kualitas Analisis: Dengan data yang sudah bersih, lengkap, dan terstruktur, analisis statistik dan visualisasi menjadi lebih bermakna dan membantu pengambilan keputusan yang lebih tepat.