#!/usr/bin/env python # coding: utf-8 # # Demo Pos Hujan # # _Notebook_ ini akan mendemonstrasikan penggunaan module `hidrokit.prepkit` dan menunjukkan potensi penggunaan _python_ saat melakukan analisis hidrologi (atau data analisis). _Notebook_ ini diharapkan memberi bayangan apa yang bisa dilakukan oleh _python_ dan _jupyter notebook_. # ## Tentang `hidrokit.prepkit` # # `prepkit` merupakan module bagian dari hidrokit yang berisikan fungsi pengolahaan data mentah menjadi data yang siap di analisis (_data munging_). Saat ini `prepkit` dibuat dengan dasar berpikir mengolah data hidrologi berupa curah hujan, debit (AWLR), dll. Sehingga, penggunaan `prepkit` sekarang hanya dibatasi dengan tujuan penggunaan pengolahan data hidrologi. Akan tetapi, Anda bisa mengembangkan `prepkit` lebih lanjut untuk menyesuaikan kebutuhan Anda. # # # ## Penggunaan # # Saat ini penggunaan _script_ ini __tidak langsung pakai__, setidaknya pengguna __harus__ terbiasa dengan penggunaan _python_, serta memahami penggunaan `pandas` dan sifat `dataframe`. Berbeda dengan _software_ yang biasa digunakan, dengan dokumentasi terbatas, pengguna diharapkan mampu mengevaluasi kode yang telah dikembangkan. Akan tetapi, diharapkan kedepannya lebih mudah dievaluasi, praktis digunakan, dan teruji. # # ---- # # __Catatan__: data `../testdata/` tidak tersedia dalam github terkait legalitas penyebaran data informasi. # # Aksi `prepkit` # # ---- # # **Contoh dalam _notebook_ ini hanya untuk file excel, dengan _single sheet_, dan nama file menunjukkan tahun dan nama stasiun. (Penggunaan untuk _multi sheet_, _multi file_ akan dibahas di _notebook_ berikutnya).** # # **Data yang digunakan hanya sebagai contoh** # ## Import Library # # Melakukan import library yang akan digunakan: # - `numpy` : library utama dalam penggunaan pandas # - `pandas` : library untuk pengelolaan data # - `matplotlib.pyplot` : library utama dalam penggunaan plot # - `pathlib` : built-in library untuk navigasi sistem # - `prepkit` : module `hidrokit` untuk persiapan pengelolaan data # - `viewkit` : module `hidrokit` untuk penampilan data # In[1]: # INITIALIZATION, importing library import numpy as np import pandas as pd import matplotlib.pyplot as plt import pathlib from hidrokit import prepkit, viewkit import seaborn as sns get_ipython().run_line_magic('matplotlib', 'inline') # In[2]: ## USE THIS CODE FOR DEVELOPMENT ONLY # %load_ext autoreload # %autoreload 2 # %aimport hidrokit # In[3]: ## Temporary View Functions def viewp(df, fmt='en'): return viewkit.in_pivot(df, col=df.columns[0], month_fmt=fmt) # ## Menentukan dokumen # # Contoh dokumen berupa _single file_ dan _single sheet_. Berikut gambar isi excelnya: # # ![_Screenshot_ Excel](./img/contohxls01.png) # # Nama format dokumen ini saya sebut `phderi` singkatan `poshujan-deri` (Karena data excelnya saya dapat dari deri). Saat ini, format tersebut merupakan format _default_. # # Kode dibawah ini mendemokan bagaimana memperoleh tabel hujan dalam excel tanpa perlu membuka file tersebut (karena membuka excel hanya untuk memperoleh data hujan itu cukup merepotkan). # # `prepkit.get_rawdf(dokumen)`, fungsi melakukan pengambilan data mentah (_raw_) dalam bentuk `dataframe` (df) `pandas`. # In[4]: dokumen = '../testdata/xls/fmderi/PHTANJUNGBARU/2016 HUJAN TANJUNG BARU.xls' rawph = prepkit.get_rawdf(dokumen) rawph.index = [i for i in range(1,32)] rawph.columns = [i for i in range(1,13)] rawph # ### Contoh format lain # # Format pengambilan data berikut mengacu pada `'pdderi'` (untuk singkatan `'pos duga-deri'`). Untuk melakukan pengambilan spesifik, bisa menggunakaan argumen `format=nama_format`. Berikut _screenshot_ excelnya: # # ![_screenshot_ pos duga](./img/contohxls02.png) # In[5]: dokumenpd = '../testdata/xls/fmderi/PDAPALAKBERUNG/2016 PALAKBENGKERUNG.xls' rawxlpd = prepkit.get_rawdf(dokumenpd, format='pdderi') rawxlpd.index = [i for i in range(1,32)] rawxlpd # ## Ubah dalam bentuk kolom # # Tabel yang kita peroleh biasanya hanya cocok untuk laporan dan bukan untuk penggunaan analisis, sehingga tabel tersebut harus diubah dalam bentuk kolom dengan indexnya berupa tipe seri-waktu. # # Dalam `prepkit` sudah disiapkan fungsi `tf_rawdf()` untuk mengubah tabel tersebut dalam bentuk kolom tunggal. # Fungsi `tf_rawdf` memiliki 1 argumen posisi, dan 2 opsional yaitu `dataframe` mentah yang diperoleh dari `get_rawdf` (argumen posisi), `year` yang menunjukkan tahun datanya, `name` untuk nama stasiun (argumen opsional). # In[6]: dokumen = pathlib.Path(dokumen) # Mengubah menjadi object pathlib tahun = int(dokumen.stem.split()[0]) nama = ''.join(dokumen.stem.split()[-2:]) phdf = prepkit.tf_rawdf(rawph, year=tahun, name=nama) phdf.info() # In[7]: phdf.head(10) # ## Eksplorasi Data # # Karena `phdf` merupakan `dataframe` maka berbagai rekayasa `pandas` dapat dilakukan, seperti: # # - `phdf['20161001':'20161231']` : mengambil data dari bulan Oktober sampai akhir Desember. (Disarankan menggunakan `.loc` atau `.iloc`) # - `phdf.describe()` : memunculkan informasi statistik # - `phdf[phdf == '-'] = 100` : mengubah data yang memenuhi kondisi `== '-'` ke nilai `100` # - `phdf['TANJUNGBARU'] = pd.to_numeric(phdf['TANJUNGBARU'])` : mengubah ke tipe data numerik # # Penggunaan `viewkit` akan dibahas lebih lanjut, untuk sementara `viewkit.in_pivot()` mengubah `dataframe` kolom tunggal menjadi bentuk tabel yang biasanya ada di laporan. # ### Ubah ke Tabel Numerik # # Karena data yang diperoleh dari excel tidak otomatis terubah menjadi tipe data numerik (karena isian `-` dan kosong), maka perlu diubah tipe data `object` menjadi numerik `float64`. Berikut langkah yang akan dilakukan: # 1. Mengubah isian `-` menjadi `0`. # 2. Memeriksa apakah ada data kosong (data tak terukur/diragukan). # 3. Mengisi data kosong tersebut dengan metode yang digunakan. Untuk contoh ini, digunakan metode `ffill` (_forward fill_) yang nilainya diperoleh dari data hari sebelumnya. # 4. Pastikan kolom dalam bentuk tipe data numerik dengan melakukan metode `.info()`. # In[8]: # Mengecek jumlah data '-' print((phdf == '-').sum()) # Maka dapat dinyatakan bahwa pada tahun ini terjadi hujan sebanyak 211 hari. Diubah isian `-` menjadi `0.0`, dan menggunakan metode `infer_objects()` untuk mengubah data tersebut otomatis menjadi numerik. # In[9]: phdf[phdf == '-'] = 0. phdf = phdf.infer_objects() phdf.info() # Cek apakah ada data yang kosong (diragukan/tidak diisi/bukan `-`) dengan menggunakan metode `.isnull` atau `.isna`. # In[10]: phdf.isna().values.any() # In[11]: phdf[phdf['TANJUNGBARU'].isnull()] # Maka, diketahui bahwa pada tanggal 11 Desember 2016, data tidak tercatat. Data tersebut akan diisi dengan cara `ffill` dari metode `.fillna`. # In[12]: phdf.loc['20161205':'20161215'].T # In[13]: phdf.fillna(method='ffill', inplace=True) phdf.loc['20161205':'20161215'].T # Setelah data kosong tersebut diisi, dilakukan pengecekan kembali. # # __Catatan__: Pengisian data kosong tersebut bisa dikembangkan lebih lanjut kembali dengan menggunakan metode pengisian data hilang hidrologi, semisal data rata-rata hujan pada bulan tersebut, rata-rata stasiun lain pada DAS yang sama, dll. # In[14]: phdf.isna().values.any() # ### Mengambil data pada periode tertentu # # Dengan index yang telah bertipe data `pd.TimeStamp`, maka melakukan pengambilan dengan periode tertentu akan lebih mudah juga. Format tanggal ditulis `YYYYMMDD` (terdapat juga format penulisan yang diterima oleh `pandas`, lihat dokumentasinya untuk lebih lanjut). # # Catatan: Abaikan penggunaan `viewp` (fungsi yang dideklarasikan di awal notebook). Penggunaan `viewp` hanya sebatas menampilkan data berbentuk kolom tunggal menjadi tabel yang biasa ditampilkan dalam laporan. __`viewp` tidak mengubah data__. # In[15]: # Jika ditampilkan dalam bentuk kolom, maka akan menghabiskan tempat. viewp() digunakan untuk mengatasi masalah tersebut. viewp(phdf).head(15) # In[16]: # Mengambil data dari periode 10 oktober 2016 sampai 13 Desember 2016. viewp(phdf['20161010':'20161213']) # ### Menampilkan data statistik dengan `.describe` # In[17]: phdf.describe() # Dari perintah menghasilkan informasi statistik berupa jumlah data dalam dataframe, rata-rata, standar deviasi, nilai minimum dan maksimum, kuartial bawah dan atas, dan median. Fungsi `describe` juga dapat digunakan untuk melihat statistik untuk setiap bulannya dengan bantuan `viewp`. # In[18]: viewp(phdf).describe() # ### _Plotting_ distribusi untuk setiap bulan # In[19]: phdf_month = phdf.assign(month=phdf.index.month) g = sns.FacetGrid(phdf_month[phdf_month['month'] <= 4], col='month') g.map(sns.distplot, 'TANJUNGBARU') g = sns.FacetGrid( phdf_month[(phdf_month['month'] > 4) & (phdf_month['month'] <= 8)], col='month') g.map(sns.distplot, 'TANJUNGBARU') g = sns.FacetGrid(phdf_month[(phdf_month['month'] > 8)], col='month') g.map(sns.distplot, 'TANJUNGBARU') ### Abaikan peringatan dibawah, hal tersebut tidak mempengaruhi hasil perhitungan/plotting. ### Gunakan paket warnings untuk menghilangkan peringatan tersebut. # # ## Plotting # Plotting dengan periode seluruh yang ada di `dataframe` # In[20]: phdf.plot(); # Plotting dengan periode tertentu # In[21]: phdf['20160501':'20161001'][:-1].plot(); # In[22]: phdf.plot.hist(bins=10) # In[23]: plt.figure(figsize=(15,8)) g = sns.heatmap(viewp(phdf), cmap='plasma', annot=True, fmt='.2f') g.set_title('Heatmap Data Hujan'); # In[24]: plt.figure(figsize=(15,10)) g = sns.heatmap(viewp(phdf).iloc[:,1::2], cmap='viridis', annot=True, fmt='.2f') g.set_title('Heatmap Data Hujan'); plt.tight_layout() # In[25]: viewp(phdf, fmt='id').plot.bar(stacked=True, figsize=(20,10)) # ini plot untuk coba-coba saja, # kenyataannya gak mungkin dalam bentuk seperti ini untuk representasi hujan dalam satu tahun. # In[26]: g = phdf.loc['20160501':'20160801',:][:-1].plot(legend=False) pddf = prepkit.tf_rawdf(rawxlpd, 2016, name='PALAKBENGKERUNG') g = pddf.loc['20160501':'20160801',:][:-1].plot(secondary_y=True, ax=g, legend=False) # # Update Notes # # ``` # > 20190109 # - koreksi penulisan dan tata bahasa, menambahkan keterangan. # > 20181019 # - fix typo, add info. # > 20181018 # - struktur folder baru # > 20181015 # - tambah grafik # - viewp dapat menampilkan dengan bulan # > 20181014 # - merombak penulisan dan struktur notebook # - tambah sns plot # > 20181012 # - initial commit # ```