Data pelanggan, transaksi, dan hasil survei sering dikumpulkan dari lebih dari satu sumber. Ketika berkas digabung, baris yang sama bisa ma...

Data pelanggan, transaksi, dan hasil survei sering dikumpulkan dari lebih dari satu sumber. Ketika berkas digabung, baris yang sama bisa masuk dua kali: pengguna mengunggah ulang laporan, sistem mengirim catatan berulang, atau dua tim mencatat entitas yang sama dengan format berbeda. Dampaknya tidak berhenti pada tabel yang terlihat penuh. Hitungan pelanggan, ringkasan transaksi, dan bahan untuk analisis data mining dapat ikut menyimpang.
Dalam artikel ini kita membangun alur deduplikasi sederhana menggunakan Python dan Pandas di komputer lokal. Fokusnya bukan sekadar menghapus baris, melainkan memahami apa yang disebut duplikat, memeriksa kandidat, menentukan baris yang dipertahankan, dan menyimpan hasil tanpa menimpa sumber. Contoh memakai data sintetis untuk laboratorium lokal; sesuaikan aturan dengan konteks data dan kebijakan organisasi sebelum digunakan pada data sebenarnya.
Mengapa duplikasi penting dalam data mining?
Data mining mencari pola atau informasi yang berguna dari data. Apabila satu kejadian dicatat beberapa kali, pola yang ditemukan dapat mencerminkan proses pencatatan, bukan fenomena yang hendak dipahami. Contohnya, laporan jumlah pendaftaran dapat membesar karena satu formulir diimpor berulang. Pada pemodelan, duplikasi juga perlu ditinjau sebelum membagi data agar salinan catatan yang sama tidak tanpa sengaja tersebar di bagian pelatihan dan pengujian.
Namun, tidak semua baris yang tampak mirip adalah kesalahan. Dua pembelian dengan nilai dan waktu berdekatan bisa merupakan dua transaksi yang sah. Sebaliknya, dua nama berbeda penulisan mungkin merujuk pada orang yang sama. Aturan deduplikasi karena itu harus berangkat dari makna data, bukan hanya kesamaan tampilan. Sebelum memproses data, tanyakan siapa pemilik data, apa satuan satu baris, dan kolom apa yang layak dijadikan identitas.
Duplikat persis dan duplikat berdasarkan kunci
Duplikat persis memiliki nilai yang sama pada semua kolom yang diperiksa. Duplikat berdasarkan kunci memiliki kesamaan pada kolom tertentu, misalnya ID pelanggan, meski kolom lain berbeda. Perbedaan itu bisa menunjukkan pembaruan data, konflik, atau catatan salah. Memilih kolom kunci tanpa pemahaman bisnis berisiko menggabungkan entitas yang seharusnya tetap terpisah.
Deduplikasi berbeda pula dari entity resolution: mencocokkan entitas ketika tidak ada kunci tepercaya biasanya memerlukan aturan tambahan atau peninjauan manusia. Di sini kita membatasi diri pada kecocokan persis setelah normalisasi sederhana, bukan menebak identitas dari nama yang mirip.
Siapkan laboratorium lokal yang aman
Gunakan lingkungan Python yang dikelola secara lokal dan instal Pandas sesuai kebutuhan lingkungan Anda. Buat direktori kerja terpisah dengan izin yang sesuai, lalu gunakan data sintetis berikut. Simpan cuplikan ini sebagai latihan_deduplikasi.py. Tidak ada kebutuhan mengunggah data ke layanan eksternal untuk mengikuti contoh.
import pandas as pd
records = [
{"id_pelanggan": "P001", "nama": "Ayu", "email": "[email protected]", "diperbarui": "2026-11-01"},
{"id_pelanggan": "P002", "nama": "Bima", "email": "[email protected]", "diperbarui": "2026-11-02"},
{"id_pelanggan": "P001", "nama": "Ayu", "email": "[email protected]", "diperbarui": "2026-11-01"},
{"id_pelanggan": "P002", "nama": "Bima", "email": "[email protected] ", "diperbarui": "2026-11-05"},
{"id_pelanggan": None, "nama": "Citra", "email": None, "diperbarui": "2026-11-03"},
]
df = pd.DataFrame(records)
print(df.to_string(index=False))
Alamat dengan domain .test hanya contoh, bukan identitas pelanggan. Pada data nyata, batasi akses direktori, hindari menampilkan informasi pribadi pada log bersama, dan ikuti aturan retensi serta pencadangan yang berlaku. Bekerja secara lokal mengurangi kebutuhan pengiriman data, tetapi tidak otomatis menjamin keamanan perangkat atau akses pengguna lain.
Temukan kandidat duplikat dengan Pandas
Metode duplicated() menghasilkan penanda Boolean untuk baris yang dianggap duplikat. Secara default, kemunculan pertama dipertahankan sebagai bukan duplikat dan kemunculan berikutnya ditandai. Untuk melihat seluruh anggota kelompok, termasuk baris pertama, gunakan keep=False. Tambahkan potongan berikut setelah pembuatan DataFrame.
persis = df[df.duplicated(keep=False)]
print("Kandidat duplikat persis:")
print(persis.to_string(index=False))
punya_id = df[df["id_pelanggan"].notna()].copy()
kandidat = punya_id[punya_id.duplicated(subset=["id_pelanggan"], keep=False)]
print("Kandidat berdasarkan ID:")
print(kandidat.sort_values("id_pelanggan").to_string(index=False))
Mengapa hasil dua pemeriksaan berbeda?
Pemeriksaan pertama membandingkan semua kolom. Dua baris P001 identik sehingga menjadi kandidat duplikat persis. Dua baris P002 memiliki ID sama, tetapi tanggal dan format email berbeda; keduanya muncul dalam pemeriksaan berdasarkan ID, bukan sebagai baris persis. Perhatikan bahwa hasil pemeriksaan ID adalah kandidat untuk ditinjau, bukan bukti otomatis bahwa baris lama aman dihapus.
Kode sengaja mengeluarkan ID kosong dari pemeriksaan kunci. Nilai hilang tidak membuktikan bahwa dua baris merujuk ke entitas yang sama; memperlakukan seluruh ID kosong sebagai satu kelompok dapat membuang data yang tidak berkaitan. Catatan tanpa kunci sebaiknya masuk antrean peninjauan atau diproses dengan aturan terpisah yang disetujui.
Normalisasi dan pilih aturan penyimpanan
Sebelum membandingkan data teks, tentukan variasi mana yang memang tidak bermakna. Spasi di awal atau akhir dan perbedaan huruf besar-kecil pada sebagian kode bisnis mungkin hanya persoalan format. Akan tetapi, jangan mengubah nilai asli secara diam-diam: buat kolom bantu agar keputusan dapat ditelusuri. Dalam contoh ini, email dinormalisasi sebagai demonstrasi pemeriksaan, bukan dijadikan bukti tunggal bahwa dua orang sama.
Buat kolom bantu tanpa merusak sumber
kerja = df.copy()
kerja["email_normal"] = kerja["email"].astype("string").str.strip().str.lower()
kerja["waktu"] = pd.to_datetime(kerja["diperbarui"], errors="coerce")
print(kerja[["id_pelanggan", "email", "email_normal", "waktu"]].to_string(index=False))
if kerja["waktu"].isna().any():
raise ValueError("Tanggal kosong atau tidak valid; periksa sebelum memilih baris terbaru.")
Konversi tanggal dengan errors="coerce" menjadikan tanggal yang gagal dibaca sebagai nilai hilang. Pemeriksaan berikutnya menghentikan alur alih-alih diam-diam memilih baris berdasarkan tanggal yang tidak dapat dipercaya. Untuk produksi, tetapkan pula format tanggal, zona waktu bila ada jam, serta kebijakan atas nilai yang tidak valid. Normalisasi email di atas hanyalah aturan demonstrasi; pastikan kebijakan aplikasi Anda memang mengizinkan perlakuan tersebut.
Tentukan baris yang dipertahankan
Misalkan pemilik data menyetujui satu baris per ID dan memilih catatan dengan tanggal pembaruan terbaru. Urutkan dulu secara stabil agar keputusan untuk tanggal yang sama mengikuti urutan masukan, lalu gunakan drop_duplicates. Pilihan ini bukan kebenaran universal: tanggal terbaru bisa menyimpan data yang kurang lengkap, dan urutan masukan belum tentu prioritas bisnis. Konflik tanggal sama perlu aturan tambahan atau pemeriksaan manual.
ber_id = kerja[kerja["id_pelanggan"].notna()].copy()
tanpa_id = kerja[kerja["id_pelanggan"].isna()].copy()
ber_id = ber_id.sort_values("waktu", ascending=False, kind="stable")
# Simpan kandidat yang tidak dipilih untuk audit sebelum ekspor.
dibuang = ber_id[ber_id.duplicated(subset=["id_pelanggan"], keep="first")]
dipilih = ber_id.drop_duplicates(subset=["id_pelanggan"], keep="first")
hasil = pd.concat([dipilih, tanpa_id], ignore_index=True)
print("Jumlah masukan:", len(kerja))
print("Jumlah dipertahankan:", len(hasil))
print("Jumlah kandidat dikeluarkan:", len(dibuang))
Pada data sintetis, P002 dengan tanggal lebih baru dipilih. Dua salinan P001 memiliki tanggal sama dan identik pada kolom sumber, sehingga salah satu tersisa. Baris tanpa ID tetap dipertahankan. Jika ada perbedaan isi pada tanggal yang sama, jangan menganggap urutan masukan cukup: catat konflik dan minta keputusan pemilik data.
Validasi hasil dan ekspor dengan jejak audit
Setelah deduplikasi, periksa bahwa tidak ada ID terisi yang berulang dan bahwa jumlah baris dapat dipertanggungjawabkan. Ekspor hasil serta kandidat yang dikeluarkan ke berkas berbeda. Berkas audit dapat mengandung data pribadi yang sama sensitifnya dengan sumber; lindungi dan hapus sesuai kebijakan retensi, bukan membagikannya secara sembarangan.
assert not hasil.loc[hasil["id_pelanggan"].notna(), "id_pelanggan"].duplicated().any()
assert len(kerja) == len(hasil) + len(dibuang)
kolom_asal = list(df.columns)
hasil[kolom_asal].to_csv("hasil_deduplikasi.csv", index=False)
dibuang[kolom_asal].to_csv("audit_kandidat_dikeluarkan.csv", index=False)
print("Hasil dan berkas audit tersimpan di direktori kerja.")
Jalankan skrip dari direktori laboratorium dengan python latihan_deduplikasi.py. Untuk masukan CSV nyata, baca menggunakan pd.read_csv dengan tipe kolom ID yang sesuai; ID yang memiliki nol di depan sebaiknya diperlakukan sebagai teks. Pastikan nama kolom dan aturan tanggal cocok sebelum menjalankan bagian lainnya. Penulisan CSV pada nama yang sama akan menimpa berkas keluaran yang sudah ada, jadi gunakan direktori kerja baru atau tetapkan nama unik.
Uji kasus tepi sebelum memakai data nyata
Periksa ID kosong, spasi pada ID, nilai tanggal tidak valid, dan dua catatan berbeda dengan tanggal sama. Pertimbangkan juga ID yang dipakai ulang, perubahan skema, serta file yang terlalu besar untuk memori perangkat. Dua pernyataan assert membantu memeriksa contoh, tetapi tidak membuktikan bahwa kunci atau keputusan bisnisnya benar. Untuk pengawasan produksi, gunakan pemeriksaan eksplisit yang tetap berjalan sesuai konfigurasi Python dan dokumentasikan siapa yang menyetujui aturan.
Contoh ini adalah rancangan laboratorium lokal berbasis data sintetis. Alur belum diuji pada dataset pengguna, volume besar, variasi versi Pandas, atau kebutuhan regulasi tertentu; karena itu jangan menganggapnya sebagai hasil pengukuran kinerja maupun jaminan kepatuhan. Sebelum penerapan, uji dengan salinan yang berwenang, evaluasi kasus konflik, dan siapkan prosedur pemulihan.
Peninjauan audit sebaiknya membandingkan baris yang dikeluarkan dengan baris yang dipertahankan, bukan hanya menghitung jumlahnya. Misalnya, bila sebuah ID memiliki nama berbeda, periksa apakah perubahan tersebut memang pembaruan yang sah atau justru menandakan kesalahan identitas. Sediakan jalur untuk mengoreksi aturan dan menjalankan ulang proses dari sumber yang utuh. Hindari menyunting hasil secara manual tanpa mencatat perubahan, karena keputusan tersebut sulit diulang pada pemrosesan berikutnya.
Perlu juga dibedakan antara hasil yang dapat diulang dan hasil yang benar. Menggunakan algoritme dan masukan yang sama dapat menghasilkan keluaran konsisten, tetapi konsistensi itu tidak memastikan bahwa aturan pemilihan sesuai kebutuhan bisnis. Dokumentasikan tanggal pemrosesan, versi alat, sumber data, definisi kunci, dan keputusan untuk konflik. Informasi ini membantu rekan lain memahami bagaimana sebuah baris terpilih tanpa harus menebak-nebak.
Jika data berasal dari beberapa sistem, petakan arti kolom sebelum menggabungkan berkas. ID yang unik di satu aplikasi belum tentu unik di aplikasi lain. Anda mungkin perlu memakai kombinasi sumber dan ID sebagai kunci, asalkan kombinasi tersebut memang menjelaskan identitas yang ingin dianalisis. Jangan menggunakan gabungan nama dan tanggal lahir sebagai pengganti tanpa mempertimbangkan risiko tabrakan dan dampak privasi.
Periksa pula cara membaca dan menyimpan data. Pemisah, pengodean karakter, dan penulisan nilai kosong dapat berbeda antara sistem. Salin sejumlah kecil contoh sintetis yang mewakili variasi tersebut, lalu bandingkan kembali jumlah baris dan tipe kolom setelah dibaca. Pada dataset sebenarnya, hindari mencetak seluruh tabel ke terminal yang direkam atau dapat dilihat pengguna lain. Ringkasan jumlah dan identifikasi masalah yang sudah disamarkan biasanya lebih aman untuk laporan operasional.
Terakhir, sepakati apa yang terjadi terhadap keluaran audit setelah proses selesai. Jika perlu disimpan untuk penelusuran, tetapkan penanggung jawab, lokasi terlindungi, dan masa retensi. Jika tidak lagi diperlukan, lakukan penghapusan sesuai prosedur organisasi. Pengelolaan salinan dan audit sama pentingnya dengan menjaga file sumber, karena keduanya dapat mengungkap informasi yang serupa.
Untuk pekerjaan berkala, catat pula penanggung jawab yang memeriksa perubahan aturan dan hasil setiap proses. Mulailah dengan kasus sederhana, lalu perluas cakupan hanya setelah contoh konflik ditinjau dan disepakati.
Langkah berikutnya dan referensi
Mulailah dengan mendefinisikan satuan baris dan kunci, lalu pisahkan deteksi kandidat dari keputusan penghapusan. Normalisasi yang dapat ditelusuri, pengecualian nilai hilang, validasi hasil, dan audit keluaran membuat proses lebih mudah diperiksa. Bila identitas tidak pasti, tinjauan manusia lebih tepat daripada memaksakan kecocokan otomatis.
Untuk memperdalam metode dan perilaku versi yang Anda gunakan, lihat dokumentasi resmi Pandas dan dokumentasi resmi Python 3. Keduanya menyediakan rujukan untuk pengolahan tabel, tipe data, penanganan berkas, serta perilaku fungsi yang dipakai dalam contoh.
COMMENTS