Monday, June 22, 2020

Menghapus dan mengganti data NaN pada Numpy

Data NaN (Not a Number) sangat menjengkelkan; bisa dibilang sampah. Data ini, bisa dari pengukuran atau simulasi, tidak dipakai dalam pengolahan data dan perlu dihilangkan atau diganti. Ya, dua cara tersebut (menghapus atau mengganti data NaN) merupakan dua cara agar data yang terkontaminasi NaN bisa diproses. Oya, data NaN ini juga bisa merupakan data outlier, misal ketika mengukur suhu rentang 23-27 derajat celcius kita mendapatkan data pengukuran 127 celcius yang tentu saja tidak masuk akal. Bisa juga data NaN ini berupa nilai "0" karena kegagalan sensor pengukuran.

Menghapus Data NaN di Numpy

Misalkan kita memiliki 10 data pengukuran dari tiga sensor.  Pertama, kita mencari elemen NaN sebagai berikut.
In [1]: import numpy as np 
In [2]: a = np.array([[1, 2, 4], [1, 2, 1], [np.nan, 1, 2], [1, 2, np.nan], [2, 1, 1]])
In [3]: np.isnan(a).any()
Out[3]: True
In [4]: np.where(np.isnan(a))                                                                           
Out[4]: (array([2, 3]), array([0, 2]))

Dari output ipython tersebut kita mengetahui bahwa data NaN berada pada (2, 0) dan (3, 2). Ingat Python mengindeks dari 0. Untuk menghapus baris (row) yang berisi NaN, gunakan perintah berikut:

In [3]: b = a[~np.isnan(a).any(axis=1)] 

Algoritma menghapus NaN pada satu baris di atas dapat dijelaskan sbb:
1. Mencari indeks data NaN dengan np.isnan.
2. Mencari data jika ada NaN dengan np.any.
3. Mencari data jika ada NaN pada kolom (axis=1, karena yang kita hapus barisnya).
4. Membalik hasil pencarian pada (1-3) dengan ~, dengan kata lain, cari data yang bukan NaN.

Untuk lebih jelasnya, perhatikan setiap output perintah berikut:
In [57]: np.isnan(a)                                                                                     
Out[57]: 
array([[False, False, False],
       [False, False, False],
       [ True, False, False],
       [False, False,  True],
       [False, False, False]])
In [58]: np.isnan(a).any()                                                                               
Out[58]: True
In [59]: np.isnan(a).any(axis=1)                                                                         
Out[59]: array([False, False,  True,  True, False])
In [60]: ~np.isnan(a).any(axis=1)                                                                        
Out[60]: array([ True,  True, False, False,  True])

In [61]: a[~np.isnan(a).any(axis=1)]                                                                     
Out[61]: 
array([[1., 2., 4.],
       [1., 2., 1.],
       [2., 1., 1.]])
Baris untuk memfilter data NaN disebut fancy indexing. Inilah salah satu hal yang paling membedakan Numpy dengan List python. Dengan teknik ini kita bisa memfilter suatu array dengan array lainnya. Contohnya data dengan index NaN ini. Permasalahan menghapus data yang berisi NaN selesai.

Mengganti Data Nan di Numpy

Bagaimana jika kita tidak ingin menghapus dana NaN, tapi mengubahnya..? Misal, dalam pengukuran suhu, suhu yang tidak terbaca sensor kita anggap sebagai suhu 25 derajat celcius.
Berikut data dummy pengukuran tiga sensor suhu.

In [52]: a = np.random.uniform(23, 28, [10, 3])                                 

In [53]: a                                                                      
Out[53]: 
array([[27.78837233, 23.24395001, 23.57374599],
       [24.19978931, 23.25094801, 24.49294423],
       [26.73693715, 23.16475293, 25.96576384],
       [26.70315233, 24.85865614, 25.3510446 ],
       [25.31885087, 27.42903322, 25.26193883],
       [25.68032566, 27.06242615, 27.0408585 ],
       [26.64473586, 27.56036335, 24.49159284],
       [24.90196938, 26.00082306, 25.70781393],
       [26.58828295, 25.36263426, 27.6251521 ],
       [24.63801191, 24.23193679, 26.99034562]])

Kita tambahkan 5 data NaN secara acak.
In [54]: a.ravel()[np.random.choice(a.size, 5, replace=False)] = np.nan         

In [55]: a                                                                      
Out[55]: 
array([[27.78837233,         nan,         nan],
       [24.19978931, 23.25094801, 24.49294423],
       [26.73693715, 23.16475293, 25.96576384],
       [26.70315233, 24.85865614, 25.3510446 ],
       [        nan, 27.42903322, 25.26193883],
       [25.68032566, 27.06242615, 27.0408585 ],
       [26.64473586, 27.56036335,         nan],
       [24.90196938, 26.00082306, 25.70781393],
       [26.58828295,         nan, 27.6251521 ],
       [24.63801191, 24.23193679, 26.99034562]])

Terlihat 5 data NaN pada baris 0, 4, 6, dan 8 (indeks mulai dari 0). Kita ganti data NaN tersebut dengan 25.0 derajat celcius. Perintah yang digunakan adalan np.nan_to_num(a, nan=25.0).

In [56]: np.nan_to_num(a, nan=25.0)                                             
Out[56]: 
array([[27.78837233, 25.        , 25.        ],
       [24.19978931, 23.25094801, 24.49294423],
       [26.73693715, 23.16475293, 25.96576384],
       [26.70315233, 24.85865614, 25.3510446 ],
       [25.        , 27.42903322, 25.26193883],
       [25.68032566, 27.06242615, 27.0408585 ],
       [26.64473586, 27.56036335, 25.        ],
       [24.90196938, 26.00082306, 25.70781393],
       [26.58828295, 25.        , 27.6251521 ],
       [24.63801191, 24.23193679, 26.99034562]])

Cukup sederhana, jika argumen nan=25.0 tidak ditambahkan, maka data NaN akan diganti dengan angka "0" (default). Jika ingin mengganti dengan angka lain, misal 25.5, tinggal mengganti nan=25.5. Selesai permasalahan mengganti data NaN pada Numpy array.
 
Untuk Pandas (dataframe) silahkan baca di sini.
Related Posts Plugin for WordPress, Blogger...