Bagian 1 berakhir dengan daftar lima masalah pada penjualan.csv: enam baris duplikat, enam harga tidak valid, delapan kategori kosong, 37 tanggal berformat campur, dan 26 baris label kategori yang tidak seragam. Data dalam keadaan seperti ini belum boleh dipakai menghitung omzet, karena satu baris ganda saja sudah menggelembungkan hasil. Pada bagian ini kita membersihkan kelima masalah itu dalam satu urutan langkah yang alasannya jelas, memeriksa jumlah baris pada setiap langkah, lalu mengemas seluruh proses menjadi fungsi bersihkan() yang akan dipanggil Bagian 3 dan Bagian 4. Pendekatan langkah demi langkah ini merupakan penerapan langsung materi section Data Cleaning pada dataset proyek.
Urutan Langkah Pembersihan #
Urutan langkah bukan pengaturan sewenang-wenang; setiap langkah membuat langkah berikutnya lebih sederhana.
drop_duplicates()menghapus enam salinan persis. Dua transaksi denganid_transaksisama hanyalah satu penjualan, sehingga penghitungan omzet tidak boleh menghitungnya dua kali.- Filter
harga > 0membuang enam transaksi dengan harga 0 atau negatif. Nilai seperti ini tidak bisa “diperbaiki” ke harga sebenarnya tanpa informasi tambahan, maka barisnya dibuang — keputusan yang dibahas pada chapter Menangani Nilai Tidak Valid. pd.to_datetime(..., format="mixed")mengubah kolomtanggaldaristrmenjadidatetime64. Kolom ini memuat dua format sekaligus,2025-01-15dan15/01/2025, sehingga butuh argumenformat="mixed"yang mem-parse tiap elemen dengan formatnya masing-masing. Perilaku ini sejalan dengan chapter Memperbaiki Tipe Data.str.strip().str.title()menyeragamkanBahan Pokok,BAHAN POKOK, danbahan pokokmenjadiBahan Pokok, sesuai materi Standardisasi Label Kategori.fillna()dengan peta produk ke kategori mengisi delapan kategori kosong. Karena satu produk selalu berada di satu kategori, nilai yang benar bisa dikembalikan dari nama produknya — polamap()pada chapter Mengisi Nilai Kosong.
Langkah terakhir berupa reset_index(drop=True) merapikan index setelah dua langkah pembuangan baris, agar DataFrame hasil akhir kembali bernomor 0 sampai 233.
Implementasi Langkah demi Langkah #
Skrip berikut menulis ulang dataset mentah dari Bagian 1, menjalankan kelima langkah sambil mencetak efek masing-masing, lalu membandingkan hasilnya dengan fungsi bersihkan() yang tersedia pada buat_dataset.py.
"""Membersihkan penjualan.csv langkah demi langkah sampai siap analisis."""
from pathlib import Path
import tempfile
import pandas as pd
from pandas.testing import assert_frame_equal
from buat_dataset import PRODUK_KATEGORI, bersihkan, buat_dataset
if __name__ == "__main__":
with tempfile.TemporaryDirectory() as folder:
berkas = Path(folder) / "penjualan.csv"
buat_dataset().to_csv(berkas, index=False)
mentah = pd.read_csv(berkas)
print(f"data mentah : {len(mentah)} baris, duplikat {mentah.duplicated().sum()}")
df = mentah.drop_duplicates()
print(f"1) drop_duplicates -> {len(df)} baris")
df = df[df["harga"] > 0]
print(f"2) filter harga > 0 -> {len(df)} baris")
df["tanggal"] = pd.to_datetime(df["tanggal"], format="mixed")
print(
f"3) to_datetime mixed -> {df['tanggal'].dtype}, "
f"NaT {df['tanggal'].isna().sum()}"
)
df["kategori"] = df["kategori"].str.strip().str.title()
print(f"4) strip + title -> {sorted(df['kategori'].dropna().unique())}")
df["kategori"] = df["kategori"].fillna(df["produk"].map(PRODUK_KATEGORI))
print(f"5) fillna dari peta produk -> NaN kategori sisa {df['kategori'].isna().sum()}")
df = df.reset_index(drop=True)
print(
f"hasil akhir: {df.shape[0]} baris x {df.shape[1]} kolom, "
f"duplikat {df.duplicated().sum()}, NaN total {df.isna().sum().sum()}"
)
assert_frame_equal(df, bersihkan(mentah))
print("validasi: hasil langkah manual == bersihkan() pada buat_dataset.py -> identik")Output yang Dihasilkan:
data mentah : 246 baris, duplikat 6
1) drop_duplicates -> 240 baris
2) filter harga > 0 -> 234 baris
3) to_datetime mixed -> datetime64[us], NaT 0
4) strip + title -> ['Bahan Pokok', 'Kebersihan', 'Minuman', 'Perawatan']
5) fillna dari peta produk -> NaN kategori sisa 0
hasil akhir: 234 baris x 7 kolom, duplikat 0, NaN total 0
validasi: hasil langkah manual == bersihkan() pada buat_dataset.py -> identikBeberapa baris perlu digarisbawahi:
mentah = pd.read_csv(berkas): dataset 246 baris dimuat ulang dari CSV agar latihan realistis; berkas ditulis dan dihapus dalamTemporaryDirectoryyang sama.df[df["harga"] > 0]: filtering boolean mengembalikan DataFrame baru; dengan Copy-on-Write yang selalu aktif di pandas 3.0, penugasan pada DataFrame hasil filter ini aman tanpa perlu khawatir memengaruhi data asal.format="mixed": hasil parse berupadatetime64[us]— resolusi mikrodetik adalah bawaan pandas 3.0 — dan pemeriksaanNaTmenghasilkan 0, artinya seluruh 234 tanggal berhasil dikonversi. Tanggal berformat DD/MM/YYYY pada dataset ini sengaja hanya hari 13 sampai 31 sehingga tidak ada keraguan urutan bulan-hari.str.strip().str.title(): kedua method string dihubungkan langsung; accessor.strmembiarkan sel NaN tetap NaN, jadi baris kategori kosong tidak ikut berubah menjadi teks aneh.fillna(df["produk"].map(PRODUK_KATEGORI)):map()menerjemahkan nama produk menjadi kategori, lalufillna()mengisinya persis pada baris yang kosong.
Memvalidasi Hasil Pembersihan #
Output skrip menunjukkan jejak jumlah baris: 246 mentah, 240 setelah drop_duplicates(), dan 234 setelah filter harga — total 12 baris dibuang, tepat enam duplikat ditambah enam harga tidak valid dari daftar Bagian 1. Kategori akhir hanya empat nilai: Bahan Pokok, Kebersihan, Minuman, Perawatan. Kategori kosong tersisa 0, dan total NaN pada seluruh DataFrame juga 0.
Baris validasi paling penting adalah assert_frame_equal(df, bersihkan(mentah)): hasil langkah manual yang baru saja kita jalankan dibandingkan dengan fungsi bersihkan() di buat_dataset.py, dan keduanya identik. Fungsi kemasan inilah yang membuat Bagian 3 dan Bagian 4 tidak perlu mengulang lima langkah tersebut. Pola perbandingan dua jalur seperti ini Anda kenal dari section Pengujian dan Debugging, hanya saja kini dipakai sebagai gerbang mutu proses pembersihan.
Dataset 234 baris yang bersih sudah siap dianalisis. Bagian 3 akan menambah kolom omzet, menggabungkan data dengan tabel harga modal, lalu menjawab pertanyaan inti proyek: produk, kategori, dan kota mana yang paling berkontribusi terhadap penjualan Toko Sembako Berkah.
Sumber bacaan resmi: pandas.DataFrame.drop_duplicates , pandas.to_datetime , dan pandas.Series.str.strip .