tau-data Analytics
Exploratory Data Analysis: Missing Values Analysis
Outline:¶
- Pendahuluan Data Preprocessing/Cleansing
- Pendahuluan Missing Values
- Tipe Missing Values
- Pengujian Missing Values
- Imputasi Dasar Missing Values
- Supervised imputation
- Time Series Imputation
Data Cleaning, Cleansing, Munging, Wrangling? ¶
- Cleaning dan cleansing sebenarnya menurut standar formal berbeda: https://indica.nl/blog/2021/3/16/what-is-the-difference-between-data-cleansing-and-data-cleaning namun dalam keseharian bisa digunakan satu-sama-lain (hati-hati kalau dalam kontrak bisnis formal).
- Banyaknya istilahnya "membingungkan", biasanya lebih "aman"/umum menggunakan terminology data preprocessing
Mengapa perlu preprocessing? ¶
Garbage in-Garbage out¶
- Data di dunia nyata biasanya tidak sebersih/indah data di buku akademik.
- Noise: Misal gaji bernilai negatif
- Ouliers: Misal seseorang dengan penghasilan >500 juta/bulan.
- Duplikasi: Banyak di media sosial
- Encodings, dsb: Banyak di Big Data, karena masalah bagaimana data disimpan/join.
- Tidak lengkap: hanya agregat, kurang variabel penting, dsb.
- Analisa pada data yang tidak di preprocess biasanya menghasilkan insight yang tidak/kurang tepat atau model yang tidak memiliki performa yang baik.
Missing Values¶
Salah satu proses dalam ‘membersihkan data’ itu adalah mengidentifikasi dan menghandle missing value, apa itu missing value? Missing value adalah istilah untuk data yang hilang
Penyebab Missing Value¶
Data yang hilang ini bisa disebabkan oleh beberapa hal, salah satu contohnya adalah
- Error pada data entry, baik itu human error ataupun kesalahan pada sistem
- Pada data survey, bisa disebabkan oleh responden yang lupa mengisi pertanyaan, pertanyaan yang sulit dimengerti, ataupun pertanyaan enggan diisi karena merupakan pertanyaan yang sensitif
Missing Values ¶
Salah satu proses dalam data preprocessing adalah mengidentifikasi dan menangani missing value, apa itu missing value? Missing value adalah istilah untuk data yang hilang
Penyebab Missing Value¶
- Error pada data entry, baik itu human error, kesalahan pada sistem, atau hardware/software fault.
- Pada data survey/kuesioner, bisa disebabkan oleh responden yang lupa mengisi pertanyaan, pertanyaan yang sulit dimengerti, ataupun pertanyaan enggan diisi karena merupakan pertanyaan yang sensitif
- permasalahan yang dihadapi pada data di dunia nyata adalah, terkadang penandaan untuk mengatakan bahwa data tersebut missing sangat beragam, bisa ditulis ‘?’ (tanda tanya), bisa ditulis ‘-‘ (strip), bisa suatu bilangan yang sangat besar atau sangat kecil (misal 99 atau -999), di kosongkan, NaN, dsb.
Langkah pertama penanganan MV adalah dengan melakukan EDA, terutama mengetahui berapa banyak proporsi data yang Missing.¶
Perhatikan bahwa data ini memiliki berbagai macam cara untuk mengatakan bahwa data pada cell tertentu adalah missing, misalnya:
- cellnya dikosongkan
- ditulis dengan n/a, NA, na, ataupun NaN
- ditulis dengan symbol –
- ataupun mempunyai nilai yang cukup aneh seperti nilai 12 pada kolom OWN_OCCUPIED, ataupun HURLEY pada kolom NUM_BATH
Ketika kita meng-load data ini ke python menggunakan pandas, beberapa notasi missing yang umum otomatis dikategorikan sebagai NaN (notasi missing value pada python)
Menangani Missing Value¶
Setelah kita mengenali apa itu missing value, bagaimana biasanya missing value itu ditulis, dan juga apa saja tipe missing value. Sekarang akan dijelaskan bagaimana cara menghandle missing value
sumber gambar : https://towardsdatascience.com/how-to-handle-missing-data-8646b18db0d4¶
Missing Values Treatment 01: Deletion ¶
- Jika data yang missing sedikit "dan" tidak terlalu berharga, biasanya relatif aman untuk tidak mengikutsertakan data tersebut dalam proses pengolahan data selanjutnya.
- Jika suatu variabel memiliki terlalu banyak missing value, secara umum juga aman untuk tidak mengikutsertakan data tersebut dalam proses pengolahan data selanjutnya.
- Terdapat beberapa cara dalam menghapus data:
- Listwise Deletion: menghapus baris/record yang mempunyai satu atau lebih missing di suatu variabelnya.
- **Pairwise Deletion**: menghapus *missing value* dengan memperhatikan variabel-variabel yang ingin digunakan. misal kita ingin mencari korelasi antara **variabel A** dan **variabel B**, maka kita hanya perlu menghapus baris yang bersesuaian tersebut.
Missing Values Treatment 02: Mengabaikan missing value ¶
Beberapa algoritma machine learning atau metode analisis lainnya memiliki kemampuan internal model/algoritma untuk menangani missing value, contohnya adalah decision tree, k-Nearest Neighbors (k-NN), Neural network yang dapat mengimputasi sendiri missing value pada data.
Ataupun jika ada beberapa kolom yang tidak memberikan informasi apa apa, kita dapat membiarkan missing value ada di kolom tersebut karena kolom tersebut pun tidak memberikan informasi yang signifikan, contohnya adalah nomor tiket pada data penerbangan, kita tidak perlu sulit-sulit memikirkan bagaimana cara mengimputasi kolom tersebut. Cukup drop kolom tersebut.
Missing Values Treatment 03: Imputasi ¶
* Selain yang ada di gambar masih banyak teknik lain, termasuk menggunakan model/algoritma untuk melakukan prediksi pada kolom yang tidak memiliki nilai (missing).
Sumber gambar : https://towardsdatascience.com/how-to-handle-missing-data-8646b18db0d4
Perlu dicatat bahwa, tidak ada metode yang benar benar terbaik dalam menghandle missing value, metode yang dapat digunakan akan bergantung pada tipe data dan masalah yang ditelaah
Tipe Missing Value ¶
Langkah kedua penanganan MV adalah meneliti bagaimana MV terdistribusi (tipe MV).
MCAR: Data hilang secara acak, dan tidak berkaitan dengan variabel/mekanisme apapun.
- Contoh: Beberapa peserta workshop tidak hadir karena alasan masing-masing dan mereka tidak saling berkomunikasi.
MAR: Terdapat hubungan sistematis antara kecenderungan data yang missing dan yang tidak missing, "tapi tidak dengan (harapan nilai) missing value itu sendiri".
- Contoh: Karena akhir tahun & banyak deadline, sehingga banyak karyawan yang memilih mengerjakan laporan ketimbang ikut workshop.
MNAR: Terdapat hubungan sistematis antara kecenderungan data yang missing dan yang tidak missing, dan juga dengan (harapan nilai) missing value itu sendiri.
- Contoh: Siswa yang memiliki orang tua dengan penghasilan dibawah rata-rata akan lebih sungkan mengisi form yang menanyakan penghasilan orang tua. Apalagi kalau jawabannya harus berupa angka eksak (bukan pilihan berupa interval). Pada siatuasi ini tidak hanya data berpotensi missing, tapi juga berpotensi untuk menurunkan kualitas data (siswa berbohong).
Referensi Little MCar Test: https://journals.sagepub.com/doi/pdf/10.1177/1536867X1301300407
Statistic Test: Terdapat uji statistik untuk MNAR, namun bahasan ini diluar scope. Namun MNAR juga dapat diketahui dari domain/business knowledge. https://towardsdatascience.com/statistical-test-for-mcar-in-python-9fb617a76eac
MCAR test di Python (gunakan dengan hati-hati): https://rianneschouten.github.io/pyampute/build/html/pyampute.exploration.html#module-pyampute.exploration.mcar_statistical_tests
Alternatifnya fungsi custom: https://stackoverflow.com/a/76581627/2844866
Langkah ketiga adalah menangani MV.¶
# Importing Some Python Modules
import warnings; warnings.simplefilter('ignore')
import scipy, itertools, pandas as pd, matplotlib.pyplot as plt, seaborn as sns, numpy as np
from scipy import stats
from sklearn.preprocessing import StandardScaler, MinMaxScaler
plt.style.use('bmh'); sns.set()
from scipy.stats import chi2
def little_mcar_test(data, alpha=0.05):
"""
Performs Little's MCAR (Missing Completely At Random) test on a dataset with missing values.
"""
data.columns = ['x' + str(i) for i in range(data.shape[1])]
data['missing'] = np.sum(data.isnull(), axis=1)
n = data.shape[0]
k = data.shape[1] - 1
df = k * (k - 1) / 2
chi2_crit = chi2.ppf(1 - alpha, df)
chi2_val = ((n - 1 - (k - 1) / 2) ** 2) / (k - 1) / ((n - k) * np.mean(data['missing']))
p_val = 1 - chi2.cdf(chi2_val, df)
if chi2_val > chi2_crit:
print('Reject null hypothesis: Data is not MCAR (p-value={:.4f}, chi-square={:.4f})'.format(p_val, chi2_val))
else:
print('Do not reject null hypothesis: Data is MCAR (p-value={:.4f}, chi-square={:.4f})'.format(p_val, chi2_val))
• Multivariate Imputation¶
Single Imputation¶
Metode metode yang dapat digunakan adalah memprediksi nilai missing dengan menggunakan metode metode supervised learning seperti kNN, regresi linear, regresi logistik (untuk data kategorik)
Kasus Lainnya¶
Salah satu cara menangani missing value pada data kategorik dapat dijadikan level tersendiri
missing value pada data Time Series, imputasi dapat dilakukan dengan:
mengisi nilai yang missing dengan nilai sebelumnya yang tidak missing, sering disebut juga dengan Last Observation Carried Forward (LOCF) ataupun dengan nilai selanjutnya yang tidak missing, sering disebut juga Next Observation Carried Backward (NOCB)
Menggunakan Interpolasi Linear
Menggunakan Interpolasi Linear dengan memperhitungkan tren seasonal
file_ = 'data/price.csv'
try: # Running Locally, yakinkan "file_" berada di folder "data"
price = pd.read_csv(file_)
except: # Running in Google Colab
!mkdir data
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/price.csv
price = pd.read_csv(file_)
price.head(3)
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9796.0 | 5250.0 | 10703.0 | 1659.0 | 1961.0 | Open | CAT B | 530 | 6649000 |
1 | 2 | 8294.0 | 8186.0 | 12694.0 | 1461.0 | 1752.0 | Not Provided | CAT B | 210 | 3982000 |
2 | 3 | 11001.0 | 14399.0 | 16991.0 | 1340.0 | 1609.0 | Not Provided | CAT A | 720 | 5401000 |
Langkah pertama menganalisa missing values¶
- Bandingkan "Count" dan "shape"
price.shape
(936, 10)
price.describe(include='all')
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
count | 936.000000 | 923.000000 | 923.000000 | 935.000000 | 928.000000 | 921.000000 | 936 | 936 | 936.000000 | 9.360000e+02 |
unique | NaN | NaN | NaN | NaN | NaN | NaN | 4 | 3 | NaN | NaN |
top | NaN | NaN | NaN | NaN | NaN | NaN | Open | CAT B | NaN | NaN |
freq | NaN | NaN | NaN | NaN | NaN | NaN | 373 | 365 | NaN | NaN |
mean | 468.500000 | 8239.512459 | 11039.122427 | 13082.894118 | 1511.558190 | 1794.610206 | NaN | NaN | 786.730769 | 6.089048e+06 |
std | 270.344225 | 2561.188953 | 2565.058074 | 2586.507654 | 789.370074 | 467.395372 | NaN | NaN | 266.218109 | 5.015046e+06 |
min | 1.000000 | 146.000000 | 1666.000000 | 3227.000000 | 775.000000 | 932.000000 | NaN | NaN | -110.000000 | 3.000000e+04 |
25% | 234.750000 | 6481.500000 | 9366.000000 | 11308.000000 | 1318.000000 | 1583.000000 | NaN | NaN | 600.000000 | 4.661000e+06 |
50% | 468.500000 | 8233.000000 | 11166.000000 | 13179.000000 | 1481.000000 | 1775.000000 | NaN | NaN | 780.000000 | 5.879500e+06 |
75% | 702.250000 | 9967.000000 | 12688.500000 | 14848.000000 | 1653.500000 | 1982.000000 | NaN | NaN | 970.000000 | 7.187250e+06 |
max | 936.000000 | 20662.000000 | 20945.000000 | 23294.000000 | 24300.000000 | 12730.000000 | NaN | NaN | 1560.000000 | 1.500000e+08 |
# General Look at the Missing Values
print(price.isnull().sum())
Observation 0 Dist_Taxi 13 Dist_Market 13 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
(price.isnull().sum()/len(price)*100).to_frame('persentase missing')
persentase missing | |
---|---|
Observation | 0.000000 |
Dist_Taxi | 1.388889 |
Dist_Market | 1.388889 |
Dist_Hospital | 0.106838 |
Carpet | 0.854701 |
Builtup | 1.602564 |
Parking | 0.000000 |
City_Category | 0.000000 |
Rainfall | 0.000000 |
House_Price | 0.000000 |
# Contoh test MCAR
# Harus tetap cek ke domain knowledge
little_mcar_test(price[['Dist_Taxi', 'Dist_Market']], alpha=0.05)
Reject null hypothesis: Data is not MCAR (p-value=0.0000, chi-square=33660.0096)
Visualisasi Missing Values ¶
- Berguna jika datanya besar dan memiliki keterurutan tertentu.
sns.heatmap(price.isnull(), cbar=False)
plt.title('Heatmap Missing Value')
plt.show()
X = price.dropna() # jika ada MV minimal satu di salah satu kolom, maka baris di hapus
price.dropna(how='all') # jika ada MV di semua kolom, maka baris di hapus
price.dropna(thresh=2) # jika ada MV minimal di salah 2 kolom, maka baris di hapus
price.dropna(subset=['Dist_Hospital'])[:7] # jika ada MV minimal satu di salah kolom Dist_Hospital
price.head()
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9796.0 | 5250.0 | 10703.0 | 1659.0 | 1961.0 | Open | CAT B | 530 | 6649000 |
1 | 2 | 8294.0 | 8186.0 | 12694.0 | 1461.0 | 1752.0 | Not Provided | CAT B | 210 | 3982000 |
2 | 3 | 11001.0 | 14399.0 | 16991.0 | 1340.0 | 1609.0 | Not Provided | CAT A | 720 | 5401000 |
3 | 4 | 8301.0 | 11188.0 | 12289.0 | 1451.0 | 1748.0 | Covered | CAT B | 620 | 5373000 |
4 | 5 | 10510.0 | 12629.0 | 13921.0 | 1770.0 | 2111.0 | Open | CAT B | 450 | 4662000 |
print(price.isnull().sum())
Observation 0 Dist_Taxi 0 Dist_Market 0 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
# inplace=True if really really sure
price.dropna(inplace=True)
# memeriksa apakah Missing value-nya sudah tidak ada.
print(price.isnull().sum())
Observation 0 Dist_Taxi 0 Dist_Market 0 Dist_Hospital 0 Carpet 0 Builtup 0 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
Populer NULL di Python¶
import numpy as np
np.nan # ==> Null paling populer
# Untuk menyederhanakan biasanya sering ditulis
nan = np.nan #ATAU
null = np.nan
nan, null
(nan, nan)
Marking Missing Values¶
- Jika missing values ditulis dengan suatu nilai khusus, maka kita bisa menggunakan teknik "marking"
# Contoh
from sklearn.impute import MissingIndicator
X = np.array([[-1, -1, 1, 3],
[4, -1, 0, -1],
[8, -1, 1, 0]])
X
array([[-1, -1, 1, 3], [ 4, -1, 0, -1], [ 8, -1, 1, 0]])
# Misal -1 Sebenarnya Missing
indicator = MissingIndicator(missing_values=-1)
mask_missing_values_only = indicator.fit_transform(X)
mask_missing_values_only
array([[ True, True, False], [False, True, True], [False, True, False]])
Tentu saja kita juga bisa menggunakan "Replace"¶
df = {
"Array_1": [-1, 70],
"Array_2": [65.1, 49.50]
}
data = pd.DataFrame(df)
data
Array_1 | Array_2 | |
---|---|---|
0 | -1 | 65.1 |
1 | 70 | 49.5 |
data.replace(-1, nan)
Array_1 | Array_2 | |
---|---|---|
0 | NaN | 65.1 |
1 | 70.0 | 49.5 |
Teknik Imputasi Dasar Missing Values: Imputasi Univariate ¶
# Load Ulang
file_ = 'data/price.csv'
try: # Running Locally, yakinkan "file_" berada di folder "data"
price = pd.read_csv(file_)
except: # Running in Google Colab
!mkdir data
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/price.csv
price = pd.read_csv(file_)
price.head(3)
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9796.0 | 5250.0 | 10703.0 | 1659.0 | 1961.0 | Open | CAT B | 530 | 6649000 |
1 | 2 | 8294.0 | 8186.0 | 12694.0 | 1461.0 | 1752.0 | Not Provided | CAT B | 210 | 3982000 |
2 | 3 | 11001.0 | 14399.0 | 16991.0 | 1340.0 | 1609.0 | Not Provided | CAT A | 720 | 5401000 |
# Sebagai ilustrasi Kita akan menggunakan variabel "Price" (bukan Price2)
print(price.isnull().sum())
Observation 0 Dist_Taxi 13 Dist_Market 13 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
# Misal di imputasi dengan rata-rata
price["Dist_Taxi"].fillna(price["Dist_Taxi"].mean(), inplace = True)
print(price.isnull().sum())
Observation 0 Dist_Taxi 0 Dist_Market 13 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
Misal sengaja hapus beberapa cell tipe kategorik untuk menciptakan MV¶
price.head()
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9796.0 | 5250.0 | 10703.0 | 1659.0 | 1961.0 | Open | CAT B | 530 | 6649000 |
1 | 2 | 8294.0 | 8186.0 | 12694.0 | 1461.0 | 1752.0 | Not Provided | CAT B | 210 | 3982000 |
2 | 3 | 11001.0 | 14399.0 | 16991.0 | 1340.0 | 1609.0 | Not Provided | CAT A | 720 | 5401000 |
3 | 4 | 8301.0 | 11188.0 | 12289.0 | 1451.0 | 1748.0 | Covered | CAT B | 620 | 5373000 |
4 | 5 | 10510.0 | 12629.0 | 13921.0 | 1770.0 | 2111.0 | Not Provided | CAT B | 450 | 4662000 |
price.loc[0,'Parking'] = np.nan
price.loc[4,'Parking'] = np.nan
price.head()
Observation | Dist_Taxi | Dist_Market | Dist_Hospital | Carpet | Builtup | Parking | City_Category | Rainfall | House_Price | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9796.0 | 5250.0 | 10703.0 | 1659.0 | 1961.0 | NaN | CAT B | 530 | 6649000 |
1 | 2 | 8294.0 | 8186.0 | 12694.0 | 1461.0 | 1752.0 | Not Provided | CAT B | 210 | 3982000 |
2 | 3 | 11001.0 | 14399.0 | 16991.0 | 1340.0 | 1609.0 | Not Provided | CAT A | 720 | 5401000 |
3 | 4 | 8301.0 | 11188.0 | 12289.0 | 1451.0 | 1748.0 | Covered | CAT B | 620 | 5373000 |
4 | 5 | 10510.0 | 12629.0 | 13921.0 | 1770.0 | 2111.0 | NaN | CAT B | 450 | 4662000 |
print(price.isnull().sum())
Observation 0 Dist_Taxi 13 Dist_Market 13 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 2 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
# Misal MV di var kategori di imputasi dengan modus
price['Parking'].fillna(price['Parking'].mode()[0], inplace=True)
print(price.isnull().sum())
# tapi di contoh data ini di var kategori tidak ada MV
Observation 0 Dist_Taxi 13 Dist_Market 13 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
Diskusi/Latihan: Bagaimana cara imputasi MV numerik dengan Median? ¶
Imputasi missing Values dengan suatu nilai¶
price['Dist_Market'].fillna(99999, inplace=True)
print(price.isnull().sum())
Observation 0 Dist_Taxi 13 Dist_Market 0 Dist_Hospital 1 Carpet 8 Builtup 15 Parking 0 City_Category 0 Rainfall 0 House_Price 0 dtype: int64
Saving (preprocessed) Data¶
# Saving the preprocessed Data for future use/analysis
price.to_csv("data/price_PreProcessed.csv", encoding='utf8', index=False)
Supervised Imputation¶
Single Imputation¶
Metode metode yang dapat digunakan adalah memprediksi nilai missing dengan menggunakan metode metode supervised learning seperti kNN, regresi linear, regresi logistik (untuk data kategorik)
Referensi utk imputasi kNN: Olga Troyanskaya, Michael Cantor, Gavin Sherlock, Pat Brown, Trevor Hastie, Robert Tibshirani, David Botstein and Russ B. Altman, Missing value estimation methods for DNA microarrays, BIOINFORMATICS Vol. 17 no. 6, 2001 Pages 520-525.
Hal yang perlu di pahami tentang knnImputer:¶
- Menggunakan jarak Euclidean semu : https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.nan_euclidean_distances.html
- Artinya hanya menghitung jarak berdasarkan entry yg tidak Nan
- Nan di proses kolom per kolom dimulai dari kolom pertama, lalu kolom kedua, dst: https://github.com/scikit-learn/scikit-learn/blob/95d4f0841d57e8b5f6b2a570312e9d832e69debc/sklearn/impute/_knn.py#L235
- kNN pada data Numerik menggunakan rata-rata. Untuk mempermudah pemahaman bisa menggunakan nilai neighbour yang berbeda-beda.
- kNN pada data kategorik menggunakan modus, tapi tidak disupport di knnImputer.
Hati-hati banyak tutorial sesat knnImputer untuk data kategorik.¶
from sklearn.impute import KNNImputer
# Contoh pakai numpy array, tapi bisa juga diterapkan di Dataframe
# hati-hati kNN hanya utk data numerik dan sejatinya bermakna numerik
X = [[1, 2, nan], [3, 4, 3], [nan, 6, 5], [8, 8, 7]]
np.array(X)
array([[ 1., 2., nan], [ 3., 4., 3.], [nan, 6., 5.], [ 8., 8., 7.]])
imputer = KNNImputer(n_neighbors=2, weights="uniform") # setting model
imputedX = imputer.fit_transform(X)
imputedX # Nan baris ke-03 di imputasi terlebih dahulu, baru kemudian Nan di baris pertama
array([[1. , 2. , 4. ], [3. , 4. , 3. ], [5.5, 6. , 5. ], [8. , 8. , 7. ]])
Time Series Imputation¶
missing value pada data Time Series, imputasi dapat dilakukan dengan:
mengisi nilai yang missing dengan nilai sebelumnya yang tidak missing, sering disebut juga dengan Last Observation Carried Forward (LOCF) ataupun dengan nilai selanjutnya yang tidak missing, sering disebut juga Next Observation Carried Backward (NOCB)
Menggunakan Interpolasi Linear
Menggunakan Interpolasi Linear dengan memperhitungkan tren seasonal
Source: https://drnesr.medium.com/filling-gaps-of-a-time-series-using-python-d4bfddd8c460
remote_path = "https://raw.githubusercontent.com/drnesr/WaterConsumption/master/data/SampleData.csv"
df=pd.read_csv(remote_path)
df.head()
Date | reference | target | |
---|---|---|---|
0 | 15-01-2010 | 12.0 | 12.0 |
1 | 15-02-2010 | 18.0 | 18.0 |
2 | 15-03-2010 | 22.0 | 22.0 |
3 | 15-04-2010 | 26.0 | 26.0 |
4 | 15-05-2010 | 31.0 | NaN |
# Converting the column to DateTime format
df.Date = pd.to_datetime(df.Date, format='%d-%m-%Y')
df = df.set_index('Date')
df.head(10)
reference | target | |
---|---|---|
Date | ||
2010-01-15 | 12.0 | 12.0 |
2010-02-15 | 18.0 | 18.0 |
2010-03-15 | 22.0 | 22.0 |
2010-04-15 | 26.0 | 26.0 |
2010-05-15 | 31.0 | NaN |
2010-06-15 | 38.0 | NaN |
2010-07-15 | 45.0 | 45.0 |
2010-08-15 | 43.0 | 43.0 |
2010-09-15 | 35.0 | NaN |
2010-10-15 | 29.0 | 29.0 |
# Buat kolom baru hanya utk keperluan plot
df = df.assign(missing= np.nan)
df.head()
reference | target | missing | |
---|---|---|---|
Date | |||
2010-01-15 | 12.0 | 12.0 | NaN |
2010-02-15 | 18.0 | 18.0 | NaN |
2010-03-15 | 22.0 | 22.0 | NaN |
2010-04-15 | 26.0 | 26.0 | NaN |
2010-05-15 | 31.0 | NaN | NaN |
df.missing[df.target.isna()] = df.reference
df.head()
reference | target | missing | |
---|---|---|---|
Date | |||
2010-01-15 | 12.0 | 12.0 | NaN |
2010-02-15 | 18.0 | 18.0 | NaN |
2010-03-15 | 22.0 | 22.0 | NaN |
2010-04-15 | 26.0 | 26.0 | NaN |
2010-05-15 | 31.0 | NaN | 31.0 |
df.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
Imputasi Dasar dengan Rata-rata atau median¶
df_rerata = df.assign(FillMean=df.target.fillna(df.target.mean()))
df_rerata.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
df_median = df.assign(FillMedian=df.target.fillna(df.target.median()))
df_median.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
Kurang baik karena tidak memanfaatkan informasi bahwa Time Series data memiliki sifat keterurutan¶
Menggunakan Rolling Average¶
Rolling?¶
- moving average, also called a rolling or running average is used to analyze the time-series data by calculating averages of different subsets of the complete dataset. Since it involves taking the average of the dataset over time, it is also called a moving mean (MM) or rolling mean.
- https://www.datacamp.com/community/tutorials/moving-averages-in-pandas
- https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rolling.html
- https://medium.com/@alexander.mueller/rolling-aggregations-on-time-series-data-with-pandas-80dee5893f9
# Contoh sederhana
df2 = pd.DataFrame({'B': [0, 7, 4, 9, 10]})
print(df2)
df2.rolling(3).mean()
B 0 0 1 7 2 4 3 9 4 10
B | |
---|---|
0 | NaN |
1 | NaN |
2 | 3.666667 |
3 | 6.666667 |
4 | 7.666667 |
Rolling Mean¶
df_rolMean = df.assign(RollingMean=df.target.fillna(df.target.rolling(12,min_periods=1,).mean()))
df_rolMean.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
Rolling Median¶
df_rolMed = df.assign(RollingMedian=df.target.fillna(df.target.rolling(12,min_periods=1,).median()))
df_rolMed.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
Interpolasi (seperti yang di Metode Numerik)¶
- Much, much better
df_inter = df.assign(InterpolateLinear=df.target.interpolate(method='linear'))
df_inter.plot(style=['k--', 'bo-', 'r*'], figsize=(12, 6));
Evaluasi bisa dilakukan dengan membandingkan nilai "Reference" dan "Hasil Imputasi"¶
df_inter.head()
reference | target | missing | InterpolateLinear | |
---|---|---|---|---|
Date | ||||
2010-01-15 | 12.0 | 12.0 | NaN | 12.000000 |
2010-02-15 | 18.0 | 18.0 | NaN | 18.000000 |
2010-03-15 | 22.0 | 22.0 | NaN | 22.000000 |
2010-04-15 | 26.0 | 26.0 | NaN | 26.000000 |
2010-05-15 | 31.0 | NaN | 31.0 | 32.333333 |
No comments:
Post a Comment
Relevant & Respectful Comments Only.