Latar Belakang Masalah
Sebuah rumah sakit ingin menganalisis data pasien rawat jalan untuk memprediksi risiko diabetes. Dataset mengandung missing values karena:
- Pasien menolak memberikan informasi tertentu
- Kesalahan input petugas administrasi
- Data lab tidak lengkap untuk pasien tertentu
Dataset Contoh (data_pasien.csv
):
ID | Usia | Gender | Glukosa | Tekanan_Darah | BMI | Riwayat_Keluarga | HbA1c |
---|---|---|---|---|---|---|---|
1 | 45 | L | 148 | 72 | 33.6 | Ya | 6.1 |
2 | 50 | P | NaN | 90 | 26.6 | Tidak | NaN |
3 | 32 | L | 138 | NaN | 43.1 | Ya | 5.7 |
4 | NaN | P | 96 | 74 | NaN | Tidak | 5.0 |
5 | 61 | L | NaN | 82 | 28.1 | NaN | 6.5 |
Analisis Missing Data
a. Eksplorasi Awal
import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('data_pasien.csv') print("Persentase Missing Values:") print(df.isnull().mean() * 100) plt.figure(figsize=(10,4)) plt.title('Distribusi Missing Values') sns.heatmap(df.isnull(), cbar=False, cmap='Blues') plt.show()
Output:
Persentase Missing Values: Usia 20.0 Gender 10.0 Glukosa 40.0 Tekanan_Darah 20.0 BMI 20.0 Riwayat_Keluarga 20.0 HbA1c 40.0 dtype: float64
b. Pola Missing Data
import missingno as msno # Matrix plot untuk identifikasi pola msno.matrix(df) plt.show() # Korelasi missing values antar kolom msno.heatmap(df) plt.show()
Solusi Penanganan
a. Penanganan Berdasarkan Jenis Kolom
1. Kolom Numerik (Glukosa, Tekanan Darah, BMI, HbA1c)
from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer # Imputasi multivariat imputer = IterativeImputer(max_iter=10, random_state=42) numeric_cols = ['Usia', 'Glukosa', 'Tekanan_Darah', 'BMI', 'HbA1c'] df[numeric_cols] = imputer.fit_transform(df[numeric_cols])
2. Kolom Kategorik (Gender, Riwayat_Keluarga)
# Imputasi modus + flag missing df['Gender'].fillna(df['Gender'].mode()[0], inplace=True) df['Riwayat_Keluarga'].fillna('Tidak Diketahui', inplace=True)
b. Validasi Hasil Imputasi
# Bandingkan statistik sebelum-sesudah original_stats = df.describe() # Buat data artifisial untuk validasi df_artificial = df.copy() for col in numeric_cols: df_artificial[col] = np.where( np.random.random(len(df)) < 0.2, np.nan, df[col] ) # Imputasi data artifisial df_imputed = df_artificial.copy() df_imputed[numeric_cols] = imputer.fit_transform(df_imputed[numeric_cols]) # Hitung error mse = ((df[numeric_cols] - df_imputed[numeric_cols])**2).mean() print("Mean Squared Error Imputasi:", mse)
Implementasi Lengkap
import pandas as pd import numpy as np from sklearn.impute import KNNImputer, SimpleImputer from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline # 1. Baca Data df = pd.read_csv('data_pasien.csv') # 2. Pipeline Imputasi numeric_features = ['Usia', 'Glukosa', 'Tekanan_Darah', 'BMI', 'HbA1c'] categorical_features = ['Gender', 'Riwayat_Keluarga'] numeric_transformer = Pipeline(steps=[ ('imputer', KNNImputer(n_neighbors=3)), ]) categorical_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='most_frequent')), ]) preprocessor = ColumnTransformer( transformers=[ ('num', numeric_transformer, numeric_features), ('cat', categorical_transformer, categorical_features) ]) # 3. Eksekusi Imputasi df_clean = pd.DataFrame( preprocessor.fit_transform(df), columns=numeric_features + categorical_features ) # 4. Tambahkan kolom ID kembali df_clean['ID'] = df['ID'] # 5. Simpan Data Bersih df_clean.to_csv('data_pasien_clean.csv', index=False) print("Data setelah cleaning:") print(df_clean.head())
Visualisasi Hasil
a. Sebelum vs Sesudah Imputasi
fig, axes = plt.subplots(2, 2, figsize=(12,8)) # Glukosa sns.kdeplot(df['Glukosa'], ax=axes[0,0], label='Original', fill=True) sns.kdeplot(df_clean['Glukosa'], ax=axes[0,0], label='Imputed', fill=True) axes[0,0].set_title('Distribusi Glukosa') # BMI sns.boxplot(data=pd.DataFrame({ 'Original': df['BMI'], 'Imputed': df_clean['BMI'] }), ax=axes[0,1]) axes[0,1].set_title('Perbandingan BMI') # HbA1c sebelum-sesudah df['HbA1c_imputed'] = df_clean['HbA1c'] sns.scatterplot(data=df, x='Usia', y='HbA1c', hue='HbA1c_imputed', ax=axes[1,0]) axes[1,0].set_title('Hubungan Usia-HbA1c') plt.tight_layout() plt.show()
Rekomendasi untuk Analisis Lanjutan
- Uji Sensitivitas:
# Bandingkan hasil model dengan berbagai metode imputasi from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score # Contoh: Prediksi diabetes (asumsi target ada) X = df_clean[numeric_features] y = df['Diabetes'] # Asumsi kolom target ada model = LogisticRegression() scores = cross_val_score(model, X, y, cv=5) print("Akurasi model setelah imputasi:", scores.mean())
- Dokumentasi Proses:
PROTOKOL PENANGANAN MISSING VALUES: 1. Kolom numerik: - Imputasi menggunakan KNN (k=3) - Pertimbangkan korelasi antar variabel 2. Kolom kategorik: - Isi dengan modus - Tambahkan kategori 'Tidak Diketahui' jika perlu 3. Validasi: - Bandingkan distribusi sebelum-sesudah - Hitung MSE pada data artifisial
Lesson Learned
- Tantangan:
- HbA1c memiliki 40% missing values (butuh investigasi klinis)
- Korelasi missing antara Glukosa dan HbA1c (MAR)
- Solusi Efektif:
- Imputasi multivariat untuk data laboratorium
- Penanganan berbeda untuk tipe data (numerik vs kategorik)
- Hasil:
- Dataset lengkap tanpa mengurangi sampel
- Mempertahankan distribusi asli variabel
- Siap untuk analisis statistik/modeling