Proyek analisis jarang dimulai dari data yang rapi, dan dataset latihan yang bersih biasanya sudah melewati pekerjaan ini tanpa terlihat. Topik ini membahas pipeline pembersihan data, yaitu rangkaian langkah berurutan yang dapat dijalankan ulang, untuk dataset peminjaman perpustakaan yang berantakan. Langkahnya mencakup pemuatan, inspeksi, perbaikan tipe, penanganan duplikat dan nilai yang hilang, validasi, serta penyimpanan hasil bersih. Setelah topik ini, satu berkas mentah yang berantakan berubah menjadi berkas bersih yang siap dianalisis.
Data mentah yang berantakan#
Data contoh berupa catatan peminjaman buku perpustakaan selama satu semester yang diinput oleh beberapa petugas berbeda. Berkas peminjaman-berantakan.csv berikut memuat kekacauan yang paling sering ditemui, yaitu format tanggal yang tidak konsisten, kapitalisasi nama yang acak, satu judul dengan spasi terdepan, satu baris tercatat dua kali, dan satu kolom lama pinjam yang tidak terisi.
tanggal_pinjam,nama,kategori,judul,lama_hari
2026-08-04,ali,Sains,Ensiklopedia Sains,6
04/08/2026,Budi,Sains,Atlas Tubuh Manusia,7
2026-08-19,budi,Sejarah,Sejarah Kerajaan Nusantara,9
2026-09-02,CITRA,Sains,Eksperimen Sederhana,
2026-09-10,Dewi,Sejarah, Jalur Rempah Nusantara,8
2026-09-23,Dewi,Fiksi,Kumpulan Dongeng Nusantara,12
2026-09-23,Dewi,Fiksi,Kumpulan Dongeng Nusantara,12
2026-10-01,Citra,Fiksi,Petualangan di Pulau Tengah,10
2026-10-14,budi,Fiksi,Cerita Legenda Gunung,11
2026-11-03,Dewi,Sains,Atlas Tubuh Manusia,7
2026-11-12,CITRA,Sains,Eksperimen Sederhana,5
2026-11-20,ali,Sains,Kamus Biologi,10
2026-11-28,Dewi,Sejarah,Sejarah Kerajaan Nusantara,8
2026-12-02,ALI,Fiksi,Cerita Legenda Gunung,8Inspeksi pertama#
Pembersihan dimulai dari inspeksi, bukan dari perbaikan. Fungsi read_csv memuat berkas mentah ke dalam DataFrame, lalu bentuk, isi, tipe kolom, sel kosong, dan duplikat diperiksa sebelum keputusan apa pun diambil. Blok berikut menjalankan pemeriksaan pembuka itu sekaligus.
import pandas as pd
pinjam = pd.read_csv("peminjaman-berantakan.csv")
print(pinjam.shape)
print()
print(pinjam)
print()
print(pinjam.dtypes)
print()
print("sel kosong per kolom:")
print(pinjam.isna().sum())
print("baris duplikat:", pinjam.duplicated().sum())(14, 5)
tanggal_pinjam nama kategori judul lama_hari
0 2026-08-04 ali Sains Ensiklopedia Sains 6.0
1 04/08/2026 Budi Sains Atlas Tubuh Manusia 7.0
2 2026-08-19 budi Sejarah Sejarah Kerajaan Nusantara 9.0
3 2026-09-02 CITRA Sains Eksperimen Sederhana NaN
4 2026-09-10 Dewi Sejarah Jalur Rempah Nusantara 8.0
5 2026-09-23 Dewi Fiksi Kumpulan Dongeng Nusantara 12.0
6 2026-09-23 Dewi Fiksi Kumpulan Dongeng Nusantara 12.0
7 2026-10-01 Citra Fiksi Petualangan di Pulau Tengah 10.0
8 2026-10-14 budi Fiksi Cerita Legenda Gunung 11.0
9 2026-11-03 Dewi Sains Atlas Tubuh Manusia 7.0
10 2026-11-12 CITRA Sains Eksperimen Sederhana 5.0
11 2026-11-20 ali Sains Kamus Biologi 10.0
12 2026-11-28 Dewi Sejarah Sejarah Kerajaan Nusantara 8.0
13 2026-12-02 ALI Fiksi Cerita Legenda Gunung 8.0
tanggal_pinjam object
nama object
kategori object
judul object
lama_hari float64
dtype: object
sel kosong per kolom:
tanggal_pinjam 0
nama 0
kategori 0
judul 0
lama_hari 1
dtype: int64
baris duplikat: 1Keluarannya menunjukkan 14 baris dengan 5 kolom, dan setiap kekacauan yang disebut sebelumnya kini tampak pada tabelnya. Kolom tanggal_pinjam terbaca sebagai teks biasa karena formatnya campuran, sedangkan kolom lama_hari berubah menjadi bilangan desimal karena sel kosong terbaca sebagai Not a Number (NaN), yaitu penanda sel kosong pada kolom numerik. Penghitung duplicated().sum() menemukan satu baris duplikat, sehingga daftar pekerjaan pembersihan sudah lengkap sebelum langkah perbaikan pertama dijalankan.
Memperbaiki tipe tanggal dan teks#
Langkah pertama memperbaiki tipe dan teks yang salah format. Tanggal campuran diubah menjadi tipe tanggal dengan to_datetime dan argumen format="mixed", yaitu mode yang mengurai setiap nilai dengan formatnya sendiri, sedangkan dayfirst=True menegaskan bahwa tanggal bergaya 04/08/2026 berarti hari lebih dahulu. Nama siswa dirapikan dengan str.strip().str.title(), dan spasi tepi judul dihilangkan dengan str.strip().
import pandas as pd
pinjam = pd.read_csv("peminjaman-berantakan.csv")
print("judul dengan spasi terdepan:", pinjam["judul"].str.startswith(" ").sum())
pinjam["tanggal_pinjam"] = pd.to_datetime(
pinjam["tanggal_pinjam"], format="mixed", dayfirst=True
)
pinjam["nama"] = pinjam["nama"].str.strip().str.title()
pinjam["judul"] = pinjam["judul"].str.strip()
print("judul dengan spasi terdepan:", pinjam["judul"].str.startswith(" ").sum())
print()
print(pinjam.dtypes)
print()
print(pinjam.head(6))judul dengan spasi terdepan: 1
judul dengan spasi terdepan: 0
tanggal_pinjam datetime64[ns]
nama object
kategori object
judul object
lama_hari float64
dtype: object
tanggal_pinjam nama kategori judul lama_hari
0 2026-08-04 Ali Sains Ensiklopedia Sains 6.0
1 2026-08-04 Budi Sains Atlas Tubuh Manusia 7.0
2 2026-08-19 Budi Sejarah Sejarah Kerajaan Nusantara 9.0
3 2026-09-02 Citra Sains Eksperimen Sederhana NaN
4 2026-09-10 Dewi Sejarah Jalur Rempah Nusantara 8.0
5 2026-09-23 Dewi Fiksi Kumpulan Dongeng Nusantara 12.0Keluarannya menunjukkan kolom tanggal_pinjam kini bertipe datetime64, baris 04/08/2026 terurai menjadi 2026-08-04, dan nama seperti ali serta CITRA menjadi Ali dan Citra. Penghitung spasi terdepan turun dari satu menjadi nol, sehingga judul yang semula tersembunyi di ujung kolom ikut terverifikasi. Perbaikan tipe dilakukan lebih dahulu karena langkah pengurutan dan pengelompokan berikutnya bergantung padanya.
Menangani duplikat dan nilai yang hilang#
Duplikat dicari dengan duplicated, ditampilkan terlebih dahulu untuk diperiksa, lalu dibuang dengan drop_duplicates. Baris yang tampil adalah catatan 2026-09-23 yang tercatat dua kali secara persis, dan bentuk data menyusut dari 14 menjadi 13 baris. Pemeriksaan sebelum pembuangan penting karena kemiripan yang tampak kadang justru dua kejadian yang sah, misalnya peminjaman ulang pada tanggal yang berbeda.
import pandas as pd
pinjam = pd.read_csv("peminjaman-berantakan.csv")
print("bentuk sebelum:", pinjam.shape)
print(pinjam[pinjam.duplicated()])
pinjam = pinjam.drop_duplicates()
print("bentuk sesudah:", pinjam.shape)bentuk sebelum: (14, 5)
tanggal_pinjam nama kategori judul lama_hari
6 2026-09-23 Dewi Fiksi Kumpulan Dongeng Nusantara 12.0
bentuk sesudah: (13, 5)Nilai yang hilang pada kolom lama_hari diisi median dari nilai yang terisi, karena nilainya berkisar sempit, yaitu 5 sampai 12 hari, dan kolom ini hanya berperan sebagai konteks. Median dipilih sebagai nilai isian karena tahan terhadap nilai ekstrem, dan jumlahnya hanya satu sel sehingga pengaruhnya kecil. Setelah pengisian, kolom dikembalikan menjadi bilangan bulat dengan astype agar tabel bersihnya rapi.
import pandas as pd
pinjam = pd.read_csv("peminjaman-berantakan.csv").drop_duplicates()
median_lama = pinjam["lama_hari"].median()
print("median lama_hari:", median_lama)
pinjam["lama_hari"] = pinjam["lama_hari"].fillna(median_lama).astype("int64")
print()
print(pinjam[pinjam["nama"].str.lower() == "citra"])median lama_hari: 8.0
tanggal_pinjam nama kategori judul lama_hari
3 2026-09-02 CITRA Sains Eksperimen Sederhana 8
7 2026-10-01 Citra Fiksi Petualangan di Pulau Tengah 10
10 2026-11-12 CITRA Sains Eksperimen Sederhana 5Keluarannya menunjukkan median 8.0 dan baris Citra tanggal 2026-09-02 yang kosong kini terisi 8. Pencarian barisnya tetap menggunakan str.lower(), karena pada blok ini kapitalisasi nama belum dirapikan, sehingga baris CITRA dan Citra sama-sama ditemukan. Nilai isian median berbeda dari data asli, dan perbedaan itu dicatat sebagai bagian dari keputusan pembersihan.
Validasi dan pipeline lengkap#
Langkah terakhir sebelum menyimpan adalah validasi, yaitu serangkaian pemeriksaan yang menyatakan lolos atau tidak. Validasi berikut memeriksa jumlah baris, duplikat tersisa, sel kosong tersisa, rentang tanggal, dan daftar kategori. Semua langkah sebelumnya diulang dalam blok ini agar pemeriksaannya berdiri sendiri dari berkas mentah.
import pandas as pd
pinjam = pd.read_csv("peminjaman-berantakan.csv")
pinjam["tanggal_pinjam"] = pd.to_datetime(
pinjam["tanggal_pinjam"], format="mixed", dayfirst=True
)
pinjam["nama"] = pinjam["nama"].str.strip().str.title()
pinjam["judul"] = pinjam["judul"].str.strip()
pinjam = pinjam.drop_duplicates()
pinjam["lama_hari"] = pinjam["lama_hari"].fillna(pinjam["lama_hari"].median()).astype("int64")
print("jumlah baris:", len(pinjam))
print("duplikat tersisa:", pinjam.duplicated().sum())
print("sel kosong tersisa:", pinjam.isna().sum().sum())
print("rentang tanggal:", pinjam["tanggal_pinjam"].min().date(), "sampai", pinjam["tanggal_pinjam"].max().date())
print("kategori:", sorted(pinjam["kategori"].unique()))jumlah baris: 13
duplikat tersisa: 0
sel kosong tersisa: 0
rentang tanggal: 2026-08-04 sampai 2026-12-02
kategori: ['Fiksi', 'Sains', 'Sejarah']Semua pemeriksaan menghasilkan nilai yang diharapkan, sehingga data layak disimpan. Karena setiap langkah sudah teruji, keseluruhan prosesnya kini dirangkai menjadi satu skrip utuh bernama pembersihan.py yang dapat dijalankan ulang kapan pun berkas mentahnya diperbarui. Skrip semacam inilah bentuk akhir sebuah pipeline, yaitu pekerjaan pembersihan yang tidak lagi berupa percobaan, melainkan berkas yang dirawat.
import pandas as pd
# muat data mentah
pinjam = pd.read_csv("peminjaman-berantakan.csv")
# perbaiki tipe tanggal dan rapikan teks
pinjam["tanggal_pinjam"] = pd.to_datetime(
pinjam["tanggal_pinjam"], format="mixed", dayfirst=True
)
pinjam["nama"] = pinjam["nama"].str.strip().str.title()
pinjam["judul"] = pinjam["judul"].str.strip()
# buang baris duplikat
pinjam = pinjam.drop_duplicates()
# isi lama_hari yang hilang dengan median
pinjam["lama_hari"] = pinjam["lama_hari"].fillna(pinjam["lama_hari"].median()).astype("int64")
# urutkan berdasarkan tanggal, lalu simpan hasil bersih
pinjam = pinjam.sort_values("tanggal_pinjam").reset_index(drop=True)
pinjam.to_csv("peminjaman-bersih.csv", index=False)
print("peminjaman-bersih.csv tersimpan,", len(pinjam), "baris")peminjaman-bersih.csv tersimpan, 13 barisMemeriksa hasil bersih#
Berkas bersih dimuat kembali sebagai pemeriksaan penutup, sekaligus memastikan tanggalnya terbaca langsung sebagai tipe tanggal. Blok berikut memuat peminjaman-bersih.csv yang baru saja dibuat oleh skrip pembersihan.
import pandas as pd
bersih = pd.read_csv("peminjaman-bersih.csv")
bersih["tanggal_pinjam"] = pd.to_datetime(bersih["tanggal_pinjam"])
print(bersih)
print()
print(bersih.dtypes) tanggal_pinjam nama kategori judul lama_hari
0 2026-08-04 Ali Sains Ensiklopedia Sains 6
1 2026-08-04 Budi Sains Atlas Tubuh Manusia 7
2 2026-08-19 Budi Sejarah Sejarah Kerajaan Nusantara 9
3 2026-09-02 Citra Sains Eksperimen Sederhana 8
4 2026-09-10 Dewi Sejarah Jalur Rempah Nusantara 8
5 2026-09-23 Dewi Fiksi Kumpulan Dongeng Nusantara 12
6 2026-10-01 Citra Fiksi Petualangan di Pulau Tengah 10
7 2026-10-14 Budi Fiksi Cerita Legenda Gunung 11
8 2026-11-03 Dewi Sains Atlas Tubuh Manusia 7
9 2026-11-12 Citra Sains Eksperimen Sederhana 5
10 2026-11-20 Ali Sains Kamus Biologi 10
11 2026-11-28 Dewi Sejarah Sejarah Kerajaan Nusantara 8
12 2026-12-02 Ali Fiksi Cerita Legenda Gunung 8
tanggal_pinjam datetime64[ns]
nama object
kategori object
judul object
lama_hari int64
dtype: objectTabel bersih berisi 13 baris yang terurut menurut tanggal, kapitalisasi nama yang seragam, dan kolom lama_hari berupa bilangan bulat. Ringkasan perubahannya sebagai berikut.
| Aspek | Sebelum | Sesudah |
|---|---|---|
| jumlah baris | 14 | 13 |
| baris duplikat | 1 | 0 |
| sel kosong | 1 | 0 |
| tipe tanggal | teks campuran | datetime64 |
| kapitalisasi nama | acak | seragam |
Berkas peminjaman-bersih.csv tersimpan di folder yang sama dengan berkas mentahnya, dan keduanya dirawat berpasangan. Apabila data mentah bertambah, skrip pembersihan.py dijalankan ulang, dan hasil bersihnya terbentuk kembali dengan langkah yang sama. Data yang berubah tanpa skrip yang menjelaskannya akan kehilangan jejaknya hanya dalam beberapa pekan.
Ringkasan#
- Inspeksi mendahului perbaikan, yaitu bentuk, tipe, duplikat, dan sel kosong diperiksa sebelum keputusan apa pun diambil.
to_datetimedenganformat="mixed"dandayfirst=Truemengurai tanggal campuran tanpa salah baca yang diam-diam.- Duplikat diperiksa sebelum dibuang, sedangkan sel kosong diisi median bila nilainya berkisar sempit.
- Pipeline lengkap tersimpan sebagai skrip
pembersihan.pyyang disertai validasi dan dapat dijalankan ulang.
Referensi#
- pandas user guide — Pandas
— Panduan resmi pandas untuk
read_csv,to_datetime,drop_duplicates, danfillnayang digunakan sepanjang pipeline. - pandas documentation — Pandas
— Dokumentasi resmi pandas yang memuat rincian argumen format pada
to_datetime.