KOMPUTASI STATISTIKA
~ Persiapan Data ~
Kontak | Konsultasi & Diskusi ke : \(\downarrow\) |
dsciencelabs@outlook.com | |
https://www.instagram.com/dsciencelabs/ | |
RPubs | https://rpubs.com/dsciencelabs/ |
Github | https://github.com/dsciencelabs/ |
Telegram | @dsciencelabs |
Import Data
Saat menjalankan suatu program di Python, kita perlu menggunakan kumpulan data set untuk analisis data. Python memiliki berbagai modul yang dapat membantu kita dalam mengimport data eksternal dalam berbagai format file ke program python. Pada bagian ini, akan diperlihatkan cara mengimpor data dengan format .csv
ke program python. Format .csv
menggunakan koma sebagai pembatas sehingga anda sebagai user Python perlu untuk mengimpor paket pandas
dan kemudian import kumpulan data set.
import pandas as pd # load library pandas
=pd.read_csv('data/week3/X_train.csv') # import data training X
X_train=pd.read_csv('data/week3/X_test.csv') # import data testing X
X_test=pd.read_csv('data/week3/Y_train.csv') # import data training Y
Y_train=pd.read_csv('data/week3/Y_test.csv') # import data testing Y
Y_test# print 5 data awal X_train.head()
## Loan_ID Gender Married ... Loan_Amount_Term Credit_History Property_Area
## 0 LP001032 Male No ... 360.0 1 Urban
## 1 LP001824 Male Yes ... 480.0 1 Semiurban
## 2 LP002928 Male Yes ... 180.0 1 Semiurban
## 3 LP001814 Male Yes ... 360.0 1 Urban
## 4 LP002244 Male Yes ... NaN 1 Urban
##
## [5 rows x 12 columns]
# print 5 data akhir X_train.tail()
## Loan_ID Gender Married ... Loan_Amount_Term Credit_History Property_Area
## 379 LP002585 Male Yes ... 360.0 0 Rural
## 380 LP001841 Male No ... 360.0 1 Rural
## 381 LP002820 Male Yes ... 360.0 1 Rural
## 382 LP001744 Male No ... 360.0 1 Semiurban
## 383 LP001552 Male Yes ... 360.0 1 Semiurban
##
## [5 rows x 12 columns]
Menangani Data yang Hilang
Nilai yang hilang (Missing values) adalah data kejadian umum dan jika tidak ditangani dalam kumpulan data pelatihan (data train), dapat mengurangi kinerja model fit atau dapat menyebabkan model bias. Ini dapat menyebabkan prediksi atau klasifikasi yang salah. Banyak hal yang mengakibatkan nilai suatu data set hilang, mungkin datanya tidak tersedia atau tidak berlaku atau peristiwa itu tidak terjadi. Bisa jadi orang yang memasukkan data tidak mengetahui nilai yang benar, atau salah mengisi.
Pertama-tama kita check apakah ada nilai yang hilang dari dataset.
print(X_train.isnull().sum()) # Check Data yang Hilang di X_train
## Loan_ID 0
## Gender 2
## Married 2
## Dependents 0
## Education 0
## Self_Employed 0
## ApplicantIncome 0
## CoapplicantIncome 3
## LoanAmount 0
## Loan_Amount_Term 3
## Credit_History 0
## Property_Area 2
## dtype: int64
Dengan Cara Menghapus
Ada beberapa metode penambangan data untuk menangani nilai yang hilang. Salah satu cara yang sering digunakan adalah dengan cara menghapuskan data yang hilang tersebut. Tentu anda perlu mempertimbangkan dan harus hati-hati dalam melakukannnya, karena bisa saja hasil analisa menjadi tidak relevan jika sala-salah mengahapuskan data yang hilang terseebut.
= X_train.dropna() # hapus baris yang berisi nilai yg hilang
df_rm print(df_rm.isnull().sum()) # check apakah masih ada data yg hilang
## Loan_ID 0
## Gender 0
## Married 0
## Dependents 0
## Education 0
## Self_Employed 0
## ApplicantIncome 0
## CoapplicantIncome 0
## LoanAmount 0
## Loan_Amount_Term 0
## Credit_History 0
## Property_Area 0
## dtype: int64
Input Mean/Modus/Median
Untuk tipe data numerik penggunaan Mean/Mode/Median sebagai pengganti atau input pada data yang hilang adalah salah satu metode yang paling sering digunakan. Sedangkan untuk tipe data kategoris lebih cocok untuk menggunakan mode.
# Loan_Amount_Term
# Mengisi nilai variabel numerik yang hilang dengan rata-rata
'CoapplicantIncome'] = X_train['CoapplicantIncome'].fillna((X_train['CoapplicantIncome'].mean()))
X_train[
# Mengisi nilai variabel karakter yang hilang dengan mode
'Gender'] = X_train['Gender'].fillna((X_train['Gender'].mode()).iloc[0])
X_train['Married'] = X_train['Married'].fillna((X_train['Married'].mode()).iloc[0])
X_train['Property_Area'] = X_train['Property_Area'].fillna((X_train['Property_Area'].mode()).iloc[0]) X_train[
Interpolasi Linier
'Loan_Amount_Term'] = X_train['Loan_Amount_Term'].fillna((X_train['Loan_Amount_Term'].interpolate())) X_train[
Forward Filling
Forward Filling adalah proses mengganti nilai yang hilang dengan catatan yang terakhir diamati. Proses ini banyak digunakan dalam data deret waktu. Metode ini menguntungkan karena mudah dikomunikasikan, tetapi didasarkan pada asumsi bahwa nilai hasil tetap tidak berubah oleh data yang hilang.
import pandas as pd
= pd.DataFrame([[1,2,3],[None,None,4],[None,5,None]])
df print(df)
## 0 1 2
## 0 1.0 2.0 3.0
## 1 NaN NaN 4.0
## 2 NaN 5.0 NaN
=df[0].fillna(method='ffill')
df0print(df0)
## 0 1.0
## 1 1.0
## 2 1.0
## Name: 0, dtype: float64
=df[1].fillna(method='ffill')
df1print(df1)
## 0 2.0
## 1 2.0
## 2 5.0
## Name: 1, dtype: float64
=df[2].fillna(method='ffill')
df2print(df2)
## 0 3.0
## 1 4.0
## 2 4.0
## Name: 2, dtype: float64
Backward Filling
Metode ini hampir sama dengan Forward Filling, tetapi Backward Filling membutuhkan pengamatan pertama setelah nilai yang hilang dan membawanya ke belakang. Untuk Backward Filling ini, Anda dapat mengganti metode imputasi menjadi “bfill” pada contoh pengisian Forwarding.
import pandas as pd
= pd.DataFrame([[1,2,3],[4,None,5],[None,6,None]])
df print(df)
## 0 1 2
## 0 1.0 2.0 3.0
## 1 4.0 NaN 5.0
## 2 NaN 6.0 NaN
=df[0].fillna(method='bfill')
df0print(df0)
## 0 1.0
## 1 4.0
## 2 NaN
## Name: 0, dtype: float64
=df[1].fillna(method='bfill')
df1print(df1)
## 0 2.0
## 1 6.0
## 2 6.0
## Name: 1, dtype: float64
=df[2].fillna(method='bfill')
df2print(df2)
## 0 3.0
## 1 5.0
## 2 NaN
## Name: 2, dtype: float64
Periksa Nilai Duplikat
Salah satu alasan lain mengapa kinerja model Anda mungkin tidak akurat adalah karena adanya data yang terduplikasi, yang dapat membuat bias data dan hasil menjadi rusak. Pastikan Anda menjaga data tersebut juga.
import pandas as pd
= pd.DataFrame(['a','b','c','d','a','b','e'])
df3 =False)] df3[df3.duplicated(keep
## 0
## 0 a
## 1 b
## 4 a
## 5 b
Catatan:
- first: menandai data duplikat pertama
- last: menandai data duplikat terakhir
- False: menandai semua data yang terduplikat
Split Data Kategorikal dan Numerik
import numpy as np
= X_train.select_dtypes(include=[np.number]) # memilah data numerik
df_num = X_train.select_dtypes(exclude=[np.number]) # memilah data kategori df_kat
Menangani Data Numerik
Standardisasi
Standardisasi adalah proses transformasi data yang memusatkan data dengan menghilangkan nilai rata-rata dari setiap fitur dan kemudian menskalakannya dengan membagi fitur (non-konstan) dengan standar deviasinya. Ini mengasumsikan data Anda terdistribusi secara normal dalam setiap fitur, dengan rata-rata 0 dan standar deviasi 1.
\[ \begin{align} z & = {x-\mu \over \sigma} \\ \mu & = \text{rata-rata} \\ \sigma & = \text{standar deviasi} \end{align} \]
Anda dapat memeriksa distribusi data menggunakan berbagai perpustakaan (library) yang sudah disediakan oleh Python. Di bawah ini, saya memperlihatkan itu dengan perpustakaan seaborn
.
import pandas as pd # https://www.kite.com/python/docs/pandas
import seaborn as sns # https://www.kite.com/python/docs/seaborn
= pd.read_csv('data/week3/top50_sportify_songs.csv', encoding='latin-1', index_col=0)
df_train sns.pairplot(df_train)
Plot histogram yang ada pada diagonal gambar diatas menunjukkan distribusi datanya, dalam hal ini sebagian besar data tidak terlihat normal. Berikut ini, diperlihatkan bangaimana melakakukan standarisasi data.
= df_train.select_dtypes(include=[np.number]) # memilah data numerik df_num
from sklearn.preprocessing import StandardScaler # https://www.kite.com/python/docs/sklearn
= StandardScaler() # membentuk objek scalar standar
scaler = scaler.fit(df_num) scaler
# standarisasi dataset dan cetak 5 baris pertama
= scaler.transform(df_num)
normalized for i in range(5):
print(normalized[i])
## [-0.10003973 -0.64306057 0.3911946 -0.16701216 -0.6050936 0.92259536
## -0.25702919 -0.96571922 -0.85796387 -1.91168174]
## [-0.4923524 1.20236711 0.64521708 0.81541229 -0.6050936 0.28944168
## 2.6074527 -0.75300573 -0.31494876 1.0120668 ]
## [ 2.28652901 1.13138912 -2.65707504 0.81541229 0.12174556 0.69646905
## -0.3860599 -0.54029225 3.03364442 -0.56225933]
## [-0.88466507 0.06671931 -0.62489528 -1.14943661 -0.6050936 0.01809011
## -0.07638618 -0.54029225 0.59007642 -0.3373556 ]
## [ 0.97882011 0.06671931 -1.13294022 0.81541229 -0.33252891 -1.65524462
## -0.66992748 1.21459399 -0.4959538 1.46187427]
# transformasi invers dan cetak 5 baris pertama
= scaler.inverse_transform(normalized)
inversed for i in range(5):
print(inversed[i])
## [117. 55. 76. -6. 8. 75. 191. 4. 3. 79.]
## [105. 81. 79. -4. 8. 61. 302. 8. 9. 92.]
## [190. 80. 40. -4. 16. 70. 186. 12. 46. 85.]
## [ 93. 65. 64. -8. 8. 55. 198. 12. 19. 86.]
## [150. 65. 58. -4. 11. 18. 175. 45. 7. 94.]
Normalisasi
Normalisasi adalah proses transformasi data dengan menskalakan sampel individu untuk memiliki unit normal. Ini sering disebut sebagai penskalaan Min-Max yang pada dasarnya mengecilkan rentang nilai data antara 0 dan 1. Ini bekerja dengan baik ketika distribusinya tidak Gaussian atau Standar deviasinya cukup kecil. Proses ini sangat sensitif terhadap outlier, jadi pastikan untuk menggunakan teknik penskalaan ini agar data anda bebas dari outlier.
Selain itu, anda juga dapat menggunakan cara menormalkan rata-rata dengan hanya mengganti X-minimum di pembilang menjadi X-rata-rata.
\[ \begin{align} X_{normalisasi} = {(x-x_{min}) \over (x_{max}-x_{min})} \end{align} \]
Mari kita normalkan data menggunakan python menggunakan normalize dan library MinMaxScaler
dari sklearn.preprocessing
.
from sklearn.preprocessing import normalize
= normalize(df_num,norm='l2') normal
Penskalaan Robust
Penskalaannya mirip dengan normalisasi tetapi sebaliknya menggunakan rentang interkuartil, untuk membuatnya kuat terhadap outlier. Karena properti interkuartil, itu tidak memperhitungkan median dan hanya berfokus pada bagian di mana data massal berada.
\[ \begin{align} \text{Skala Robust} = {x_i-Q_1(x) \over Q_3(x)-Q_1(x)} \end{align} \]
from sklearn.preprocessing import RobustScaler
# Buat objek scaler
= RobustScaler()
scaler scaler.fit(df_num)
## RobustScaler()
scaler.transform(df_num)
## array([[ 0.30120482, -0.58974359, 0.19607843, 0. , -0.38709677,
## 0.624 , -0.17177914, -0.43137255, -0.4 , -1.89473684],
## [ 0.01204819, 0.74358974, 0.43137255, 0.72727273, -0.38709677,
## 0.176 , 2.55214724, -0.2745098 , 0.2 , 0.84210526],
## [ 2.06024096, 0.69230769, -2.62745098, 0.72727273, 0.64516129,
## 0.464 , -0.29447853, -0.11764706, 3.9 , -0.63157895],
## [-0.27710843, -0.07692308, -0.74509804, -0.72727273, -0.38709677,
## -0.016 , 0. , -0.11764706, 1.2 , -0.42105263],
## [ 1.09638554, -0.07692308, -1.21568627, 0.72727273, 0. ,
## -1.2 , -0.56441718, 1.17647059, 0. , 1.26315789],
## [-0.06024096, 0.07692308, 0.50980392, 0.36363636, -0.25806452,
## 0.912 , 0.5398773 , -0.23529412, -0.3 , -0.84210526],
## [ 1.81927711, -0.12820513, 0.11764706, 0. , -0.51612903,
## -1.04 , -1.64417178, -0.50980392, 2.2 , 0.84210526],
## [ 0.15662651, 0.07692308, -2. , 0.36363636, -0.38709677,
## -0.656 , 0.09815951, 0. , 0.2 , 0.42105263],
## [ 0.75903614, -0.23076923, 1.1372549 , 0. , 0. ,
## 0.272 , -1.00613497, -0.39215686, 0.3 , -0.21052632],
## [ 0.73493976, -1.20512821, -0.2745098 , -1.81818182, -0.12903226,
## 0.016 , -0.09815951, 0.70588235, 3.1 , 1.47368421],
## [ 1.72289157, -0.23076923, -0.98039216, 0.36363636, 1.67741935,
## -1.008 , 1.3006135 , 1.76470588, 2.4 , 1.05263158],
## [-0.20481928, 0.23076923, 0.66666667, 0.72727273, 0.51612903,
## -0.56 , -0.3190184 , 0.50980392, 0. , -0.42105263],
## [ 0.13253012, -1.30769231, -1.84313725, 0. , 0. ,
## -0.336 , -0.39263804, 2.35294118, -0.4 , 0. ],
## [ 1.72289157, 0.64102564, -0.03921569, 1.45454545, -0.64516129,
## 0.656 , 2.20858896, -0.31372549, 1.3 , -0.21052632],
## [-0.08433735, -0.84615385, 0.74509804, 0.72727273, 0.12903226,
## -1.456 , 0.17177914, -0.19607843, -0.2 , 0.84210526],
## [-0.27710843, -1.1025641 , -0.2745098 , -0.36363636, 0.64516129,
## -1.328 , 1.54601227, -0.11764706, 0.8 , -1.26315789],
## [ 1.72289157, -0.07692308, 0.11764706, 0. , 0. ,
## -0.4 , 1.10429448, 0. , 2.5 , 0.42105263],
## [-0.34939759, -0.94871795, 0.19607843, 0. , -0.51612903,
## 1.136 , -0.98159509, 1.60784314, -0.2 , 0.63157895],
## [ 0.61445783, -1.41025641, 0.82352941, -0.72727273, 0.38709677,
## -0.176 , -0.90797546, 0.11764706, 0.1 , 0. ],
## [ 1.28915663, -0.23076923, -0.11764706, 1.09090909, 0.12903226,
## -0.464 , -0.61349693, -0.15686275, 0.4 , 0.63157895],
## [ 0.46987952, 0.38461538, -0.43137255, -0.36363636, -0.51612903,
## 0.24 , -1.10429448, -0.43137255, -0.4 , 0.63157895],
## [ 1.19277108, -0.38461538, -0.2745098 , 0. , 0.12903226,
## -0.24 , -2.03680982, 0.74509804, 0.1 , 0.63157895],
## [-0.30120482, 0.64102564, 0.58823529, 0.72727273, -0.25806452,
## 0.08 , 2.72392638, -0.03921569, 0. , -1.05263158],
## [-0.30120482, 0.58974359, 0.50980392, 0.72727273, 4.25806452,
## 0.784 , 1.66871166, 0.82352941, -0.3 , 0.63157895],
## [ 0.73493976, -1.1025641 , -0.50980392, -1.81818182, 0.12903226,
## 0.4 , -0.07361963, 0.39215686, 2.3 , 0.21052632],
## [ 0.46987952, 0.79487179, -0.35294118, 0.72727273, 0.25806452,
## 1.008 , -0.17177914, 1.33333333, -0.1 , -3.78947368],
## [-0.15662651, -0.38461538, 0.66666667, 0. , 0.90322581,
## -0.048 , 0.29447853, 2.11764706, 0.3 , -1.05263158],
## [-0.20481928, -1.05128205, -0.03921569, -0.36363636, 1.03225806,
## -0.496 , 0.36809816, 0.8627451 , -0.4 , 0.21052632],
## [-0.25301205, 1. , 0.03921569, 1.09090909, -0.64516129,
## 0.336 , -0.12269939, -0.15686275, -0.1 , 0.63157895],
## [-0.27710843, 0.64102564, -0.74509804, 0.72727273, 3.22580645,
## 1.232 , 0.58895706, -0.47058824, 1.8 , 0.21052632],
## [-0.46987952, -0.79487179, -3.49019608, -0.72727273, -0.12903226,
## -0.624 , 0.29447853, -0.11764706, -0.3 , -0.84210526],
## [ 0.85542169, -1.76923077, 0.35294118, -1.81818182, -0.25806452,
## -0.72 , -0.46625767, 1.7254902 , 2.6 , 0.21052632],
## [-0.20481928, 0.23076923, 0.35294118, 0.36363636, -0.25806452,
## 0.4 , -0.5398773 , 0.2745098 , 2.1 , 0.21052632],
## [-0.15662651, -0.38461538, 0.50980392, -0.36363636, 0.25806452,
## -1.2 , 0.04907975, -0.50980392, 0.8 , 0.21052632],
## [-0.10843373, 1.1025641 , 0.2745098 , 0.36363636, 2.70967742,
## -0.528 , 0.63803681, 0.15686275, -0.1 , 0.21052632],
## [ 0.22891566, 0.28205128, -0.58823529, -0.36363636, 0.38709677,
## -0.752 , -0.83435583, 0.11764706, -0.1 , 0.21052632],
## [ 1.72289157, 0.17948718, 0.11764706, 0.36363636, 0. ,
## 0.208 , 0.68711656, -0.03921569, 2.7 , 0.63157895],
## [ 1.14457831, 0.79487179, -0.11764706, 0.36363636, 3.22580645,
## 1.136 , -0.88343558, -0.07843137, -0.2 , -0.21052632],
## [ 0.80722892, 0.33333333, 0.82352941, 0.36363636, 0. ,
## 1.264 , -0.41717791, -0.43137255, -0.1 , -1.68421053],
## [-0.22891566, -0.53846154, 0.58823529, 0. , -0.64516129,
## 0.4 , 0.02453988, 1.29411765, 0. , -2.10526316],
## [-0.01204819, 0.07692308, -0.35294118, -0.36363636, -0.12903226,
## -0.496 , 0.73619632, -0.50980392, -0.4 , 0. ],
## [-0.46987952, 0.07692308, 0.2745098 , 0. , -0.51612903,
## 0.56 , -0.66257669, -0.54901961, -0.2 , 0.42105263],
## [-0.20481928, -1.41025641, -1.29411765, 0. , 1.5483871 ,
## -0.752 , 0.44171779, 0.8627451 , -0.4 , -0.21052632],
## [ 0.75903614, -1.35897436, 1.29411765, -1.09090909, -0.64516129,
## -0.656 , 0. , -0.39215686, 0.6 , -0.84210526],
## [-0.15662651, 0.12820513, 1.1372549 , 0.72727273, -0.77419355,
## 0.624 , -0.88343558, 0.94117647, 0.5 , 0. ],
## [-0.39759036, -0.23076923, -0.58823529, 1.45454545, 6.06451613,
## -0.368 , -0.39263804, -0.31372549, -0.2 , 0. ],
## [ 1.72289157, 0.43589744, -0.50980392, 0.72727273, -0.38709677,
## 0.784 , 0.09815951, 0.35294118, -0.1 , 0. ],
## [-0.10843373, 0.64102564, -0.35294118, 1.09090909, 0.77419355,
## 0.368 , 0.39263804, 0.15686275, -0.2 , 0. ],
## [-0.01204819, 0.17948718, -1.1372549 , 0. , 3.87096774,
## -0.176 , 0.49079755, 0.31372549, -0.4 , 0. ],
## [-0.22891566, 0.64102564, 0.11764706, 0. , -0.51612903,
## 0.176 , 0.19631902, 0.23529412, 0.5 , -1.26315789]])
Penanganan Data Pencilan
Pencilan adalah salah satu masalah paling banyak dihadapi yang dapat dengan mudah memberikan hasil statistik yang menyesatkan dan juga merobohkan kinerja model jika tidak ditangani. Ini adalah salah satu bagian penting dari data yang sering dilihat oleh para ilmuwan data (data scientist) dan kebanyakan dari mereka bahkan kesulitan bagaimana menanganinya.
Metode statistik
Distribusi Gaussian
Jika kita tahu bahwa distribusi data adalah Gaussian atau seperti Gaussian dengan kata sederhana, apakah data Anda terdistribusi normal? jika jawabannya ya maka kita dapat menggunakan standar deviasi dari nilai data untuk mengidentifikasi outlier dengan menerapkan sifat sederhana dari distribusi normal.
Untuk rekap cakupan data distribusi normal :
- \(\sigma=1,\) 68% data ada disekitar \(\mu\)
- \(\sigma=2,\) 95% data ada disekitar \(\mu\)
- \(\sigma=3,\) artinya 99,7% data ada disekitar \(\mu\)
Catatan: Sebagian besar nilai sampel tercakup dalam \(\sigma=3,\), jika nilainya berada di luar maka dapat dianggap sebagai outlier yang merupakan kejadian yang tidak mungkin atau jarang terjadi pada sekitar 1 dari 400 sampel. \(\sigma=3,\) adalah aturan umum yang dapat ditingkatkan menurun berdasarkan jenis masalah yang dikerjakan, misalkan jika cakupan data 99,9% diperlukan, pertimbangkan \(\sigma=4\) sebagai gantinya.
Berikut saya berikan contoh penanganan data pencilan dengan Python.
# mengidentifikasi outlier dengan standar deviasi
import numpy as np
from numpy.random import randn
# seeting pembentuk nomor acak yang sama
42)
np.random.seed(
# menghasilkan pengamatan univariat
= 8 * randn(90000) + 100
sample
# menghitung ringkasan statistiknya
= np.mean(sample), np.std(sample)
sample_mean, sample_std
# mengidentifikasi pencilan (outlier)
= sample_std * 3
cut_off = sample_mean - cut_off, sample_mean + cut_off
lower, upper
# print pencilan
= [x for x in sample if x < lower or x > upper]
outliers print('Data pencilan: %d' % len(outliers))
# hapus pencilan
## Data pencilan: 232
= [x for x in sample if x >= lower and x <= upper]
outliers_removed print('Observasi non-pencilan: %d' % len(outliers_removed))
## Observasi non-pencilan: 89768
Contoh di atas adalah implementasi untuk data satu dimensi, tetapi bagaimana jika data di dalamnya adalah hyper-plane (data n-dimensi)? Nah, secara sederhana kita akan mengikuti pendekatan yang sama, bayangkan data 2-D dengan pertimbangkan cut-off untuk batas dan setiap titik yang terletak di luar batas akan dianggap sebagai outlier.
Boxplot atau Rentang Interkuartil (IQR)
Tidak semua data mengikuti distribusi normal, dalam hal ini kita dapat menggunakan metode IQR untuk data sampel. Untuk penjelesan lebih lengkap silahkan membaca teori Statistik Deskriptif. Mari kita lihat contoh implementasinya sebagai berikut:
# mengidentifikasi outlier dengan jangkauan interkuartil
import numpy as np
from numpy.random import randn
import pandas as pd
import matplotlib.pyplot as plt
# menghasilkan pengamatan univariat
= 8 * randn(90000) + 10
data
# menghitung jangkauan interkuartil
= np.percentile(data, 25), np.percentile(data, 75)
q25, q75 = q75 - q25
iqr print(f'Percentiles: 25th={np.round(q25)}, 75th={np.round(q75)}, IQR={np.round(iqr)}')
# menghitung cutoff outlier
## Percentiles: 25th=5.0, 75th=15.0, IQR=11.0
= iqr * 1.5
cut_off = q25 - cut_off, q75 + cut_off
lower, upper
# mengidentifikasi outlier
= [x for x in data if x < lower or x > upper]
outliers print('Data pencilan: %d' % len(outliers))
# hapus outlier
## Data pencilan: 610
= [x for x in data if x >= lower and x <= upper]
outliers_removed print('Observasi non-pencilan: %d' % len(outliers_removed))
## Observasi non-pencilan: 89390
= pd.DataFrame(data, columns=['data'])
df = df.boxplot(column=['data'], figsize=(10,10), return_type='axes')
boxplot plt.show()
Metode Mechine Learning
Penanganan data pencilan denga metode ini adalah pendekatan pengelompokan berbasis kepadatan, sangat umum digunakan dalam data yang tidak diawasi, dan bukan metode deteksi outlier semata tetapi karena pendekatan algoritma yang digunakan. Ini membentuk cluster berdasarkan radius dan jumlah tetangga dan setiap titik di luar cluster dianggap outlier. Titik-titik inti -titik-titik yang memiliki titik-titik minimum di sekitarnya- dan titik-titik yang cukup dekat dengan titik-titik inti tersebut bersama-sama membentuk sebuah cluster.
Algoritme memiliki dua parameter (epsilon: skala panjang, dan min_samples: jumlah minimum sampel yang diperlukan untuk suatu titik menjadi titik inti). Menemukan epsilon yang baik sangat penting.
import seaborn as sns
import pandas as pd
import numpy as np
= sns.load_dataset('titanic')
titanic
= titanic[["age", "fare"]]
ageAndFare = "age", y = "fare") ageAndFare.plot.scatter(x
sum() ageAndFare.isnull().
## age 177
## fare 0
## dtype: int64
= np.mean(ageAndFare.age)
mean =mean, inplace =True) ageAndFare.age.fillna(value
## C:\Users\Bakti\anaconda3\envs\py38\lib\site-packages\pandas\core\generic.py:6392: SettingWithCopyWarning:
## A value is trying to be set on a copy of a slice from a DataFrame
##
## See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
## return self._update_inplace(result)
from sklearn.preprocessing import MinMaxScaler
= MinMaxScaler()
scaler = scaler.fit_transform(ageAndFare)
ageAndFare = pd.DataFrame(ageAndFare, columns = ["age", "fare"]) ageAndFare
from sklearn.cluster import DBSCAN
= DBSCAN(
outlier_detection = 0.5,
eps ="euclidean",
metric= 3,
min_samples = -1)
n_jobs = outlier_detection.fit_predict(ageAndFare)
clusters
from matplotlib import cm
= cm.get_cmap('Accent')
cmap
ageAndFare.plot.scatter(= "age",
x = "fare",
y = clusters,
c = cmap,
cmap = False
colorbar )
Encoding Data Kategorikal
Penanganan data kategoris adalah proses mengubah kategori menjadi angka. Sangat umum untuk melihat data kategorikal yang dapat bertipe nominal atau ordinal dalam kumpulan data Anda. Karena algoritme mesin hanya bekerja pada angka, maka penting untuk mengubahnya, teknik yang digunakan disebut Encoding.
import pandas as pd
import numpy as np
# https://www.kaggle.com/c/cat-in-the-dat/overview
= pd.read_csv('data/week3/train.csv',nrows=20)
df_train print(df_train.shape)
## (20, 25)
5) df_train.head(
## id bin_0 bin_1 bin_2 bin_3 bin_4 ... ord_3 ord_4 ord_5 day month target
## 0 0 0 0 0 T Y ... h D kr 2 2 0
## 1 1 0 1 0 T Y ... a A bF 7 8 0
## 2 2 0 0 0 F Y ... h R Jc 7 2 0
## 3 3 0 1 0 F Y ... i D kW 2 1 1
## 4 4 0 0 0 F N ... a R qP 7 8 0
##
## [5 rows x 25 columns]
= df_train.select_dtypes(exclude=[np.number]) # memilah data kategori
df_kat sum() df_kat.isnull().
## bin_3 0
## bin_4 0
## nom_0 0
## nom_1 0
## nom_2 0
## nom_3 0
## nom_4 0
## nom_5 0
## nom_6 0
## nom_7 0
## nom_8 0
## nom_9 0
## ord_1 0
## ord_2 0
## ord_3 0
## ord_4 0
## ord_5 0
## dtype: int64
Pelabelan
Ini adalah teknik yang sangat sederhana yang mengubah setiap nilai dalam kolom/fitur tipe kategorikal menjadi angka. Setiap kategori diberi label unik mulai dari 0 dan berlanjut hingga n_kategori — 1 per fitur. Encoding label cocok untuk data ordinal karena data menunjukkan beberapa urutan dan pengkodean mempertimbangkan urutan secara alfabetis secara default, Anda juga dapat mengubah urutan menggunakan kamus/peta yang akan kita lihat dalam pemetaan khusus, tetapi menggunakannya untuk data nominal dapat menyesatkan misalnya saat mengonversi fitur nama menjadi numerik dapatkah Anda mengatakan nama saya secara numerik lebih besar dari Anda? Tidak benar, Enkode satu-panas atau pengkodean dummy akan menjadi pendekatan yang lebih tepat untuk nanti yang akan kita bahas selanjutnya.
Katakanlah sebuah fitur berbicara tentang nama hewan yang berisi 5 hewan kucing, sapi, anjing, kuda, zebra. Kami sedang mempelajari hubungan tinggi dari 5 hewan ini. Jadi mengingat masalah urutan kita dapat menyandikan kuda -> 0 , zebra ->1, sapi -> 2 , anjing ->3 dan kucing -> 4. Di bawah ini adalah pengkodean Label menggunakan python
from sklearn.preprocessing import LabelEncoder
= df_kat.apply(LabelEncoder().fit_transform)
label label.head()
## bin_3 bin_4 nom_0 nom_1 nom_2 ... ord_1 ord_2 ord_3 ord_4 ord_5
## 0 1 1 1 5 4 ... 2 1 5 1 13
## 1 1 1 1 4 2 ... 2 3 0 0 8
## 2 0 1 0 4 3 ... 1 4 5 8 3
## 3 0 1 2 4 4 ... 2 0 6 1 12
## 4 0 0 2 4 3 ... 2 2 0 8 15
##
## [5 rows x 17 columns]
Pemetaan Kustom
Metode encoding ini sangat berguna untuk variabel ordinal dimana urutan kategori sangat penting. Pada kondisi ini encoder Label tidak akan membantu karena hanya mempertimbangkan urutan abjad tetapi di sini kita memerlukan urutan kita sendiri. Seperti ukuran kaos dari besar ke kecil akan Negatif>Netral>Positif
. Untuk memastikan bahwa algoritma pembelajaran menginterpretasikan variabel ordinal dengan benar, kita dapat memetakan nilai kategorikal ke nilai integer secara manual.
import pandas as pd
= pd.DataFrame({'col1': [1, 2, 2, 3, 1],
df 'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']})
= {'negative': -1, 'neutral': 0, 'positive': 1}
conversion_dict 'converted_column'] = df['col2'].replace(conversion_dict)
df[
print(df.head())
## col1 col2 converted_column
## 0 1 negative -1
## 1 2 positive 1
## 2 2 neutral 0
## 3 3 neutral 0
## 4 1 positive 1
Variabel Dummy
Variabel Dummy (Encoding one-hot adalah salah satu skema pengkodean yang paling banyak digunakan. Ini bekerja dengan membuat kolom baru untuk setiap kategori yang ada di fitur dan menetapkan 1 atau 0 untuk menunjukkan keberadaan kategori dalam data. Kolom terpisah dibuat untuk setiap nilai yang mungkin. Nilai 1 dalam kolom mewakili keberadaan level tersebut dalam data asli.
Metode get_dummies
Panda dapat diterapkan ke bingkai data (data frame) dan hanya akan mengubah kolom string menjadi angka dan membiarkan yang lainnya apa adanya. Alternatif untuk metode get_dummies
adalah fungsi OneHotEncoder sklearn yang mengembalikan array. Bingkai data ini harus digabungkan dengan bingkai data asli. Encoding one-hot berkinerja lebih baik ketika kardinalitas kategori fitur tidak terlalu tinggi. Karena untuk fitur dengan kardinalitas tinggi, Encoding one-hot akan membuat sejumlah besar kolom yang dapat menyebabkan masalah memori.
= pd.get_dummies(df_kat, columns = list(df_kat.columns))
dummy print(dummy)
## bin_3_F bin_3_T bin_4_N bin_4_Y ... ord_5_qX ord_5_qo ord_5_su ord_5_wy
## 0 0 1 0 1 ... 0 0 0 0
## 1 0 1 0 1 ... 0 0 0 0
## 2 1 0 0 1 ... 0 0 0 0
## 3 1 0 0 1 ... 0 0 0 0
## 4 1 0 1 0 ... 0 0 0 0
## 5 0 1 1 0 ... 0 0 0 0
## 6 0 1 1 0 ... 0 0 0 1
## 7 0 1 0 1 ... 0 0 0 0
## 8 0 1 0 1 ... 0 1 0 0
## 9 1 0 0 1 ... 0 0 0 0
## 10 0 1 0 1 ... 1 0 0 0
## 11 0 1 0 1 ... 0 0 1 0
## 12 1 0 1 0 ... 0 0 0 0
## 13 1 0 0 1 ... 0 0 0 0
## 14 0 1 0 1 ... 0 0 0 0
## 15 1 0 1 0 ... 0 0 0 0
## 16 0 1 1 0 ... 0 0 0 0
## 17 0 1 0 1 ... 0 0 0 0
## 18 0 1 1 0 ... 0 0 0 0
## 19 1 0 1 0 ... 0 0 0 0
##
## [20 rows x 175 columns]
Kategori ke Statistik
Statistik pada dasarnya memberikan ringkasan hitungan/frekuensi dari suatu nilai atau variabel, konsep yang sama diperluas untuk pengkodean ini. Encoding Kategori ke Statistik bekerja dengan menggantikan setiap kategori dengan berapa kali kita melihatnya di dataset. Misalnya , dengan cara ini jika “Paris” dan “London” adalah kota besar, keduanya mungkin akan muncul berkali-kali dalam kumpulan data kami dan model akan mengetahui bahwa keduanya serupa.
=df_kat.copy()
df_statfor col in df_stat.columns:
=df_stat[col].astype('category')
df_stat[col]=df_stat[col].value_counts()
counts=counts.sort_index()
counts=counts.fillna(0)
counts+= np.random.rand(len(counts))/1000
counts =counts
df_stat[col].cat.categories
df_stat.head()
## bin_3 bin_4 nom_0 ... ord_3 ord_4 ord_5
## 0 12.000549 12.000225 7.000870 ... 3.000326 2.000066 1.000965
## 1 12.000549 12.000225 7.000870 ... 2.000127 1.000820 1.000538
## 2 8.000713 12.000225 7.000883 ... 3.000326 4.000704 1.000162
## 3 8.000713 12.000225 6.000894 ... 5.000828 2.000066 1.000597
## 4 8.000713 8.000467 6.000894 ... 2.000127 4.000704 1.000520
##
## [5 rows x 17 columns]
Fitur Siklik
Data seperti deret waktu, penjualan, terkait musiman, dan berisi fitur seperti waktu, bulan, hari, hari kerja, jam, menit, detik, dll. Encoding Fitur Siklik menggukan trigonometri sederhana untuk membantu kita dalam mentransformasikan data, metode umum untuk pengkodean data siklis adalah mengubah data menjadi dua dimensi menggunakan transformasi sinus dan kosinus.
= df_train.copy()
df_cyclic =['day','month']
columnsfor col in columns:
+'_sin']=np.sin((2*np.pi*df_cyclic[col])/max(df_cyclic[col]))
df_cyclic[col+'_cos']=np.cos((2*np.pi*df_cyclic[col])/max(df_cyclic[col]))
df_cyclic[col= df_cyclic.drop(columns,axis=1)
df_cyclic
'day_sin','day_cos']].head(20) df_cyclic[[
## day_sin day_cos
## 0 9.749279e-01 -0.222521
## 1 -2.449294e-16 1.000000
## 2 -2.449294e-16 1.000000
## 3 9.749279e-01 -0.222521
## 4 -2.449294e-16 1.000000
## 5 9.749279e-01 -0.222521
## 6 -9.749279e-01 -0.222521
## 7 -4.338837e-01 -0.900969
## 8 4.338837e-01 -0.900969
## 9 4.338837e-01 -0.900969
## 10 4.338837e-01 -0.900969
## 11 -2.449294e-16 1.000000
## 12 4.338837e-01 -0.900969
## 13 4.338837e-01 -0.900969
## 14 -2.449294e-16 1.000000
## 15 7.818315e-01 0.623490
## 16 9.749279e-01 -0.222521
## 17 -4.338837e-01 -0.900969
## 18 4.338837e-01 -0.900969
## 19 7.818315e-01 0.623490
Probabilitas Target
Metode di atas memiliki beberapa kelemahan seperti, Pengkodean label tidak berfungsi dengan baik dengan fitur kategoris non-ordinal. Dalam metode ini, kita mengganti setiap kategori dari variabel kategori dengan probabilitas target yang sesuai (jika kategoris) atau rata-rata target (jika numerik). Kelemahan utama dari metode ini adalah ketergantungannya pada distribusi target, kekuatan prediktabilitasnya yang lebih rendah dibandingkan dengan metode pengkodean biner, dan juga menerapkan pengkodean target secara naif dapat memungkinkan kebocoran data, yang mengarah ke overfitting dan kinerja prediksi yang buruk.
= df_train.copy()
df_target 'day'] = df_target['day'].astype('object')
df_target['month'] = df_target['month'].astype('object')
df_target[for col in df_target.columns:
if (df_target[col].dtype=='object'):
= dict ( df_target.groupby(col)['target'].agg('sum')/df_target.groupby(col)['target'].agg('count'))
target= df_target[col].replace(target).values
df_target[col]
'day','month']].head(10) df_target[[
## day month
## 0 0.250000 0.125
## 1 0.000000 0.000
## 2 0.000000 0.125
## 3 0.250000 1.000
## 4 0.000000 0.000
## 5 0.250000 0.125
## 6 0.000000 0.000
## 7 0.500000 0.125
## 8 0.333333 0.000
## 9 0.333333 0.125
K-fold/Cross-Fold
Untuk mengatasi masalah over-fitting dari pengkodean target, kita dapat membagi data menjadi lipatan-N dan menghitung rata-rata setiap kategori hingga lipatan ke-i menggunakan data di semua lipatan lainnya. k-fold atau metode pengkodean target cross fold, pada contoh berikut kita membagi dataset menjadi 5 fold. Gambar di bawah menunjukkan putaran pertama dari validasi silang 5 kali lipat. Kami menghitung target rata-rata untuk lipatan 2, 3, 4, dan 5 dan kami menggunakan nilai yang dihitung, mean_A = 0,556 dan mean_B = 0,285 untuk memperkirakan pengkodean rata-rata untuk lipatan-1.
= df_train.drop(['target','id'],axis=1).columns
columns
from sklearn.model_selection import KFold
= df_train.copy()
df_kfold 'ord_0','day','month']] = df_kfold[['ord_0','day','month']].astype('object')
df_kfold[['bin_3','bin_4']] = df_kfold[['bin_3','bin_4']].replace({'Y':1,'N':0,'T':1,"F":0})
df_kfold[[= KFold(n_splits = 5, shuffle = False)
kf for train_ind,val_ind in kf.split(df_kfold):
for col in columns:
if(df_kfold[col].dtype=='object'):
=dict(df_kfold.iloc[train_ind][[col,'target']].groupby(col)['target'].mean())
replaced= df_kfold.iloc[val_ind][col].replace(replaced).values
df_kfold.loc[val_ind,col]
'bin_3','bin_4','day','month','target']].head(10) df_kfold[[
## bin_3 bin_4 day month target
## 0 1 1 0.0 0.166667 0
## 1 1 1 0.0 0.0 0
## 2 0 1 0.0 0.166667 0
## 3 0 1 0.0 1.0 1
## 4 0 0 0.0 8.0 0
## 5 1 0 0.0 0.25 0
## 6 1 0 5.0 0.0 0
## 7 1 1 1.0 0.25 0
## 8 1 1 0.666667 4.0 0
## 9 0 1 0.666667 0.5 0
Catatan: Tidak ada aturan praktis pengkodean mana yang harus dnda ikuti, pada akhirnya pembelajaran mesin didasarkan pada persyaratan pernyataan masalah dan data. Apa yang ingin Anda capai dari kumpulan data itulah yang memutuskan opsi mana yang paling berhasil, saya akan menyerahkannya kepada Anda untuk mengerjakannya dan mencari tahu yang terbaik.
Referensi
- https://medium.com/analytics-vidhya/part-1-data-preparation-made-easy-with-python-e2c024402327
- https://medium.com/analytics-vidhya/part-2-data-preparation-made-easy-with-python-633027bf6f28
- https://medium.com/@nehakushwaha1308/part-3-data-preparation-made-easy-with-python-632f6647add2
- https://datacarpentry.org/python-ecology-lesson/03-index-slice-subset/
- https://www.analyticsvidhya.com/blog/2021/06/power-of-interpolation-in-python-to-fill-missing-values/