Berdasarkan isu #151: Uji Outlier
Referensi Isu:
Deksripsi Isu:
Strategi:
rel_Kn_n
, hubungan $K_n$ dengan jumlah data $N$.import numpy as np
import pandas as pd
# contoh diambil dari buku
# Limantara, Lily M. (2018): Rekayasa Hidrologi, Edisi Revisi.
# Penerbit Andi Offset, Yogyakarta. (hal. 90-91)
_hujan = np.array([2818, 2542, 1949, 1842, 1748, 1737, 1605, 1558, 1433, 1264])
_index = np.array([2010, 2013, 2008, 2012, 2011, 2014, 2009, 2007, 2015, 2006])
data = pd.DataFrame(
data=np.stack([_index, _hujan], axis=1),
columns=['Tahun','Hujan']
)
# ubah kolom tahun jadi datetime, dan index
data.Tahun = pd.to_datetime(data.Tahun, format="%Y")
data.set_index('Tahun', inplace=True)
data
Hujan | |
---|---|
Tahun | |
2010-01-01 | 2818 |
2013-01-01 | 2542 |
2008-01-01 | 1949 |
2012-01-01 | 1842 |
2011-01-01 | 1748 |
2014-01-01 | 1737 |
2009-01-01 | 1605 |
2007-01-01 | 1558 |
2015-01-01 | 1433 |
2006-01-01 | 1264 |
Nilai tabel mengikuti referensi buku.
t_rel_Kn_n
diambil pada buku Te Chow, V. (2010). Applied Hydrology. p404.Tabel yang digunakan dalam perhitungan dibangkitkan dengan kode dibawah ini:
_N = np.array(
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 120,
130, 140]
)
_Kn = np.array(
[2.036, 2.088, 2.134, 2.175, 2.213, 2.247, 2.279, 2.309, 2.335, 2.361,
2.385, 2.408, 2.429, 2.448, 2.467, 2.486, 2.502, 2.519, 2.534, 2.549,
2.563, 2.577, 2.591, 2.604, 2.616, 2.628, 2.639, 2.65, 2.661, 2.671,
2.682, 2.692, 2.7, 2.71, 2.719, 2.727, 2.736, 2.744, 2.753, 2.76,
2.768, 2.804, 2.837, 2.866, 2.893, 2.917, 2.94, 2.961, 2.981, 3,
3.017, 3.049, 3.078, 3.104, 3.129]
)
t_rel_Kn_n = pd.DataFrame(np.stack((_N, _Kn), axis=1), columns=['N', 'Kn'])
t_rel_Kn_n.head()
N | Kn | |
---|---|---|
0 | 10.0 | 2.036 |
1 | 11.0 | 2.088 |
2 | 12.0 | 2.134 |
3 | 13.0 | 2.175 |
4 | 14.0 | 2.213 |
def find_Kn(n, table=t_rel_Kn_n):
if n < 10 or n > 140:
raise ValueError('Jumlah data diluar batas bawah (10) / batas atas (140)')
else:
N = table['N'].to_numpy()
Kn = table['Kn'].to_numpy()
return np.interp(n, N, Kn)
def calc_boundary(df, col=None, result='value', show_stat=False):
col = df.columns[0] if col is None else col
x = df[col].to_numpy()
n = x.size
xlog = np.log10(x)
xlogmean = xlog.mean()
xlogstd = xlog.std(ddof=1)
Kn = find_Kn(n)
# higher
y_h = xlogmean + Kn*xlogstd
val_h = 10**y_h
# lower
y_l = xlogmean - Kn*xlogstd
val_l = 10**y_l
if show_stat:
print(
f'Statistik:',
f'N = {n}',
f'Mean (log) = {xlogmean:.5f}',
f'Std (log) = {xlogstd:.5f}',
f'Lower (val) = {val_l:.5f}',
f'Higher (val) = {val_h:.5f}',
sep='\n', end='\n\n'
)
if result.lower() == 'value':
return (val_l, val_h)
elif result.lower() == 'log':
return (y_l, y_h)
def find_outlier(df, col=None, verbose=False, **kwargs):
low, high = calc_boundary(df, col, **kwargs)
col = df.columns[0] if col is None else col
masklow = df[col] < low
maskhigh = df[col] > high
mask = masklow | maskhigh
if verbose and masklow.sum():
print(f'Ada outlier dibawah batas bawah sebanyak {masklow.sum()}.')
if verbose and maskhigh.sum():
print(f'Ada outlier diatas batas atas sebanyak {maskhigh.sum()}.')
def check_outlier(x):
if x < low:
return "lower"
elif x > high:
return "higher"
else:
return pd.NA
if mask.sum() != 0:
new_df = df.copy()
new_df['outlier'] = df[col].apply(check_outlier)
return new_df[[col, 'outlier']]
else:
print("Tidak ada Outlier")
return None
find_Kn(n)
¶Fungsi ini digunakan untuk mencari nilai $K_n$ untuk perhitungan uji outlier.
n
: jumlah data $\left(10 \le \mathbb{N} \le 140\right)$. Diluar batasan tersebut akan menghasilkan peringatan ValueError
.find_Kn(n=10)
2.036
try:
find_Kn(141)
except ValueError:
print("Hasil akan error")
Hasil akan error
calc_boundary(df, col=None, result='value', show_stat=False)
¶Fungsi calc_boundary(...)
digunakan untuk mencari nilai batas bawah dan batas atas outlier dari data. Keluaran fungsi ini berupa tuple dengan bentuk (low_boundary, high_boundary)
.
df
: dataset dalam objek pandas.DataFrame
.col=None
: nama kolom data yang akan dicek outlier. Jika None
maka dipilih kolom pertama dari dataframe.result="value"
: keluaran berupa nilai batasan aktual dengan skala original. Jika menggunakan log
, keluaran berupa nilai batasan dalam skala logaritmik.show_stat=False
: jika True
akan menampilkan nilai statistik berupa jumlah data, rata-rata, standar deviasi, batasan bawah dan atas dalam skala original.calc_boundary(data)
(1092.1254115165966, 2961.0550928195808)
calc_boundary(data, col='Hujan', result='log', show_stat=True)
Statistik: N = 10 Mean (log) = 3.25486 Std (log) = 0.10638 Lower (val) = 1092.12541 Higher (val) = 2961.05509
(3.038272512363497, 3.471446487863784)
find_outlier(df, col=None, verbose=False, **kwargs)
¶Fungsi find_outlier(...)
digunakan untuk memeriksa apakah data memiliki outlier atau tidak dan memberi keluaran berupa dataframe yang telah ditandai data mana saja yang dikategorikan outlier.
df
: dataset dalam objek pandas.DataFrame
.col=None
: nama kolom data yang akan dicek outlier. Jika None
maka dipilih kolom pertama dari dataframe.verbose=False
: memberi informasi tambahan jika memiliki outlier dan seberapa banyak.**kwargs
: keyword arguments dari fungsi .calc_boundary()
.find_outlier(data)
Tidak ada Outlier
find_outlier(data, show_stat=True)
Statistik: N = 10 Mean (log) = 3.25486 Std (log) = 0.10638 Lower (val) = 1092.12541 Higher (val) = 2961.05509 Tidak ada Outlier
# contoh data dengan outlier
data2 = data.copy()
data2.loc['2012'] = 4000
find_outlier(data2, 'Hujan', verbose=True)
Ada outlier diatas batas atas sebanyak 1.
Hujan | outlier | |
---|---|---|
Tahun | ||
2010-01-01 | 2818 | <NA> |
2013-01-01 | 2542 | <NA> |
2008-01-01 | 1949 | <NA> |
2012-01-01 | 4000 | higher |
2011-01-01 | 1748 | <NA> |
2014-01-01 | 1737 | <NA> |
2009-01-01 | 1605 | <NA> |
2007-01-01 | 1558 | <NA> |
2015-01-01 | 1433 | <NA> |
2006-01-01 | 1264 | <NA> |
data2.loc['2012'] = 40
find_outlier(data2, show_stat=True)
Statistik: N = 10 Mean (log) = 3.08854 Std (log) = 0.53301 Lower (val) = 100.77150 Higher (val) = 14918.85009
Hujan | outlier | |
---|---|---|
Tahun | ||
2010-01-01 | 2818 | <NA> |
2013-01-01 | 2542 | <NA> |
2008-01-01 | 1949 | <NA> |
2012-01-01 | 40 | lower |
2011-01-01 | 1748 | <NA> |
2014-01-01 | 1737 | <NA> |
2009-01-01 | 1605 | <NA> |
2007-01-01 | 1558 | <NA> |
2015-01-01 | 1433 | <NA> |
2006-01-01 | 1264 | <NA> |
- 20220303 - 1.0.0 - Initial
Source code in this notebook is licensed under a MIT License. Data in this notebook is licensed under a Creative Common Attribution 4.0 International.