METODE STATISTIKA

~ Persiapan Data ~

Nb: Untuk segala bentuk diskusi, kritik dan saran mengenai materi silahkan hubungi admin!

Alamat \(\space \rightleftharpoons\) Sebagai Berikut : \(\downarrow\)
Email
Instagram 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
X_train=pd.read_csv('data/week3/X_train.csv') # import data training X
X_train.head()                                # print 5 data awal
##     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]
X_train.tail()                                # print 5 data akhir
##       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.

df_rm = X_train.dropna()                      # hapus baris yang berisi nilai yg hilang
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 
X_train['CoapplicantIncome'] = X_train['CoapplicantIncome'].fillna((X_train['CoapplicantIncome'].mean()))

# Mengisi nilai variabel karakter yang hilang  dengan mode 
X_train['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])

Interpolasi Linier

X_train['Loan_Amount_Term'] = X_train['Loan_Amount_Term'].fillna((X_train['Loan_Amount_Term'].interpolate()))

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
df = pd.DataFrame([[1,2,3],[None,None,4],[None,5,None]])
print(df)
##      0    1    2
## 0  1.0  2.0  3.0
## 1  NaN  NaN  4.0
## 2  NaN  5.0  NaN
df0=df[0].fillna(method='ffill')
print(df0)
## 0    1.0
## 1    1.0
## 2    1.0
## Name: 0, dtype: float64
df1=df[1].fillna(method='ffill')
print(df1)
## 0    2.0
## 1    2.0
## 2    5.0
## Name: 1, dtype: float64
df2=df[2].fillna(method='ffill')
print(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
df = pd.DataFrame([[1,2,3],[4,None,5],[None,6,None]])
print(df)
##      0    1    2
## 0  1.0  2.0  3.0
## 1  4.0  NaN  5.0
## 2  NaN  6.0  NaN
df0=df[0].fillna(method='bfill')
print(df0)
## 0    1.0
## 1    4.0
## 2    NaN
## Name: 0, dtype: float64
df1=df[1].fillna(method='bfill')
print(df1)
## 0    2.0
## 1    6.0
## 2    6.0
## Name: 1, dtype: float64
df2=df[2].fillna(method='bfill')
print(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
df3 = pd.DataFrame(['a','b','c','d','a','b','e'])
df3[df3.duplicated(keep='last')]
##    0
## 0  a
## 1  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 
df_num = X_train.select_dtypes(include=[np.number]) # memilah data numerik
df_kat = X_train.select_dtypes(exclude=[np.number]) # memilah data kategori

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

df_train = pd.read_csv('data/week3/top50_sportify_songs.csv', encoding='latin-1', index_col=0)
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_num = df_train.select_dtypes(include=[np.number]) # memilah data numerik
from sklearn.preprocessing import StandardScaler # https://www.kite.com/python/docs/sklearn
scaler = StandardScaler()                        # membentuk objek scalar standar 
scaler = scaler.fit(df_num)
# standarisasi dataset dan cetak 5 baris pertama
normalized = scaler.transform(df_num)
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
inversed = scaler.inverse_transform(normalized)
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
normal = normalize(df_num,norm='l2')

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 
scaler = RobustScaler()
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 
np.random.seed(42)

# menghasilkan pengamatan univariat 
sample = 8 * randn(90000) + 100

# menghitung ringkasan statistiknya 
sample_mean, sample_std = np.mean(sample), np.std(sample)

# mengidentifikasi pencilan (outlier) 
cut_off = sample_std * 3
lower, upper = sample_mean - cut_off, sample_mean + cut_off

# print pencilan 
outliers = [x for x in sample if x < lower or x > upper]
print('Data pencilan: %d' % len(outliers))

# hapus pencilan
## Data pencilan: 232
outliers_removed = [x for x in sample if x >= lower and x <= upper]
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. IQR atau Inter Quartile Range adalah ukuran statistik yang digunakan untuk mengukur variabilitas dalam data tertentu. Dalam istilah naif, ini memberi tahu kita di dalam kisaran berapa sebagian besar data kita berada. Ini dapat dihitung dengan mengambil perbedaan antara kuartil ketiga dan kuartil pertama dalam kumpulan data.

\[IQR = Q3 - Q1\]

Dimana, Q3 = nilai persentil ke-75 (ini adalah nilai tengah antara median dan nilai terbesar di dalam kumpulan data). Q1 = nilai persentil ke-25 (ini adalah nilai tengah antara median dan nilai terkecil di dalam kumpulan data). Juga, Q2 menunjukkan persentil ke-50 yaitu, median dari kumpulan data.

Mari kita mulai dengan mengimpor library penting yang akan kita perlukan untuk mengidentifikasi dan memfilter outlier.

# Mengimpor perpustakaan penting
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use('seaborn')

Sekarang, kita akan membaca dataset di mana kita ingin mendeteksi dan memfilter outlier

# Import Data
data = pd.read_csv('data/week3/Dataset.csv')
print("Jumlah baris dan kolom datanya adalah: ", data.shape)
## Jumlah baris dan kolom datanya adalah:  (20, 3)
print(data)
##     Height (in cm)  Width (in cm)  Area (in cm2)
## 0               38             16            608
## 1               36             14            504
## 2               38             13            494
## 3                5             23            115
## 4               34             30           1020
## 5               35             29           1015
## 6               39             34           1326
## 7               86             82           7052
## 8               30             28            840
## 9               33             29            957
## 10              39             36           1404
## 11               7              3             21
## 12               6              2             12
## 13              28             25            700
## 14              32             32           1024
## 15              90             76           6840
## 16              37             28           1036
## 17              39             30           1170
## 18              40             33           1320
## 19               6              8             48
data.describe()
##        Height (in cm)  Width (in cm)  Area (in cm2)
## count       20.000000      20.000000      20.000000
## mean        34.900000      28.550000    1375.300000
## std         21.975824      20.085279    1956.310574
## min          5.000000       2.000000      12.000000
## 25%         29.500000      15.500000     501.500000
## 50%         35.500000      28.500000     986.000000
## 75%         39.000000      32.250000    1207.500000
## max         90.000000      82.000000    7052.000000

Dapat diamati bahwa fitur seperti ‘Tinggi’, ‘Lebar’, ‘Area’ memiliki nilai maksimum yang sangat ditangguhkan dibandingkan dengan nilai 75%, sehingga kita dapat mengatakan ada pengamatan tertentu yang bertindak sebagai outlier dalam dataset. Demikian pula nilai minimum pada kolom-kolom tersebut sangat berbeda dengan nilai 25%, sehingga menandakan adanya outlier.

Ini dapat diverifikasi dengan memplot plot kotak fitur di atas, di sini saya memplot plot kotak untuk kolom Tinggi dan dengan cara yang sama plot kotak untuk fitur lain dapat diplot.

plt.figure(figsize=(6,4))
sns.boxplot(data['Height (in cm)'])
## <AxesSubplot:xlabel='Height (in cm)'>
## 
## C:\Users\Bakti\anaconda3\envs\py38\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
##   warnings.warn(
plt.show()

Untuk mengetahui dan memfilter outlier tersebut di dataset, kami akan membuat fungsi khusus yang akan membantu kami menghapus outlier. Dalam fungsi tersebut, pertama-tama kita perlu mencari nilai IQR yang dapat dihitung dengan mencari selisih antara nilai kuartil ketiga dan pertama. Kedua, kami akan menulis kueri untuk memilih pengamatan yang berada di luar wilayah IQR rentang_bawah dan rentang_atas dan menghapusnya. Itu dapat ditulis sebagai:

# Menghapus outlier 
def removeOutliers(data, col):
    Q3 = np.quantile(data[col], 0.75)
    Q1 = np.quantile(data[col], 0.25)
    IQR = Q3 - Q1
     
    print("Nilai IQR untuk setiap kolom dalam % adalah: %s" % (col, IQR))
    global outlier_free_list
    global filtered_data
     
    lower_range = Q1 - 1.5 * IQR
    upper_range = Q3 + 1.5 * IQR
    outlier_free_list = [x for x in data[col] if (
        (x > lower_range) & (x < upper_range))]
    filtered_data = data.loc[data[col].isin(outlier_free_list)]
 
 
for i in data.columns:
    removeOutliers(data, i)
 
# Assigning filtered data back to our original variable
## Nilai IQR untuk setiap kolom dalam 'Height (in cm)'dalah: 9.5
## Nilai IQR untuk setiap kolom dalam 'Width (in cm)'dalah: 16.75
## Nilai IQR untuk setiap kolom dalam 'Area (in cm2)'dalah: 706.0
data = filtered_data
print("Dimensi data setelah penghapusan outlier adalah: ", data.shape)
## Dimensi data setelah penghapusan outlier adalah:  (18, 3)

Mencetak data sesudahnya, kita dapat melihat dua pengamatan ekstrim kita yang bertindak sebagai outlier dihilangkan. Kita dapat mengamati baris dengan nomor indeks 7 dan 15 telah dihapus dari dataset asli.

print(data)
##     Height (in cm)  Width (in cm)  Area (in cm2)
## 0               38             16            608
## 1               36             14            504
## 2               38             13            494
## 3                5             23            115
## 4               34             30           1020
## 5               35             29           1015
## 6               39             34           1326
## 8               30             28            840
## 9               33             29            957
## 10              39             36           1404
## 11               7              3             21
## 12               6              2             12
## 13              28             25            700
## 14              32             32           1024
## 16              37             28           1036
## 17              39             30           1170
## 18              40             33           1320
## 19               6              8             48

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
titanic = sns.load_dataset('titanic')

ageAndFare = titanic[["age", "fare"]]
ageAndFare.plot.scatter(x = "age", y = "fare")

ageAndFare.isnull().sum()
## age     177
## fare      0
## dtype: int64
mean = np.mean(ageAndFare.age)
ageAndFare.age.fillna(value=mean, inplace =True)
## 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
scaler = MinMaxScaler()
ageAndFare = scaler.fit_transform(ageAndFare)
ageAndFare = pd.DataFrame(ageAndFare, columns = ["age", "fare"])
from sklearn.cluster import DBSCAN
outlier_detection = DBSCAN(
  eps = 0.5,
  metric="euclidean",
  min_samples = 3,
  n_jobs = -1)
clusters = outlier_detection.fit_predict(ageAndFare)

from matplotlib import cm
cmap = cm.get_cmap('Accent')
ageAndFare.plot.scatter(
  x = "age",
  y = "fare",
  c = clusters,
  cmap = cmap,
  colorbar = False
)

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
df_train = pd.read_csv('data/week3/train.csv',nrows=20) 
print(df_train.shape)
## (20, 25)
df_train.head(5)
##    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_kat = df_train.select_dtypes(exclude=[np.number]) # memilah data kategori
df_kat.isnull().sum()
## 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
label = df_kat.apply(LabelEncoder().fit_transform)
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

df = pd.DataFrame({'col1': [1, 2, 2, 3, 1],
            'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']})

conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1}
df['converted_column'] = df['col2'].replace(conversion_dict)

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.

dummy = pd.get_dummies(df_kat, columns = list(df_kat.columns))
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_stat=df_kat.copy()
for col in df_stat.columns:
    df_stat[col]=df_stat[col].astype('category')
    counts=df_stat[col].value_counts()
    counts=counts.sort_index()
    counts=counts.fillna(0)
    counts += np.random.rand(len(counts))/1000
    df_stat[col].cat.categories=counts
    
df_stat.head()
##        bin_3      bin_4     nom_0  ...     ord_3     ord_4     ord_5
## 0  12.000858  12.000305  7.000453  ...  3.000726  2.000056  1.000692
## 1  12.000858  12.000305  7.000453  ...  2.000885  1.000898  1.000945
## 2   8.000362  12.000305  7.000478  ...  3.000726  4.000852  1.000368
## 3   8.000362  12.000305  6.000897  ...  5.000106  2.000056  1.000558
## 4   8.000362   8.000814  6.000897  ...  2.000885  4.000852  1.000848
## 
## [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_cyclic = df_train.copy()
columns=['day','month']
for col in columns:
    df_cyclic[col+'_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 = df_cyclic.drop(columns,axis=1)

df_cyclic[['day_sin','day_cos']].head(20)
##          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_target = df_train.copy()
df_target['day'] = df_target['day'].astype('object')
df_target['month'] = df_target['month'].astype('object')
for col in df_target.columns:
    if (df_target[col].dtype=='object'):
        target= dict ( df_target.groupby(col)['target'].agg('sum')/df_target.groupby(col)['target'].agg('count'))
        df_target[col] = df_target[col].replace(target).values    

df_target[['day','month']].head(10)
##         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.

columns = df_train.drop(['target','id'],axis=1).columns

from sklearn.model_selection import KFold

df_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})
kf = KFold(n_splits = 5, shuffle = False)
for train_ind,val_ind in kf.split(df_kfold):
    for col in columns:
        if(df_kfold[col].dtype=='object'):
            replaced=dict(df_kfold.iloc[train_ind][[col,'target']].groupby(col)['target'].mean())
            df_kfold.loc[val_ind,col] = df_kfold.iloc[val_ind][col].replace(replaced).values

df_kfold[['bin_3','bin_4','day','month','target']].head(10)
##    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.