Chapter sebelumnya menambal lubang antar tabel, sedangkan kebutuhan audit mengajukan pertanyaan sebaliknya: sel mana persisnya yang berubah antara dua versi data. Membandingkan dua DataFrame dengan == menghasilkan tabel boolean, tetapi pembaca masih harus mencari sendiri posisi False-nya. Method DataFrame.compare() dirancang untuk pertanyaan ini: method tersebut menampilkan hanya sel yang berbeda, berpasangan berdampingan antara nilai lama dan baru. Chapter ini membahas struktur hasil compare(), pelabelan kolom lewat result_names, serta parameter keep_shape untuk pemeriksaan berbentuk penuh.

Struktur Hasil compare() #

df1.compare(df2) mengembalikan tabel yang kolomnya menjadi MultiIndex dua lapis: lapis pertama nama kolom asli, lapis kedua pasangan self dan other. Baris yang seluruh selnya sama tidak muncul sama sekali, sehingga hasil langsung menunjukkan lokasi perbedaan. Pada contoh penjualan April dan Mei, hanya Kopi Gayo dan Gula Aren yang tampil, sementara Teh Melati yang tidak berubah dikeluarkan dari hasil. NaN pada hasil bukan berarti data hilang; NaN hanya menandai bahwa pasangan nilai tersebut tidak diperbandingkan karena selnya identik.

python
import pandas as pd

penjualan_april = pd.DataFrame(
    {
        "unit": [120, 85, 60],
        "omzet": [5_400_000, 3_570_000, 1_920_000],
    },
    index=["Kopi Gayo", "Teh Melati", "Gula Aren"],
)
penjualan_mei = pd.DataFrame(
    {
        "unit": [135, 85, 58],
        "omzet": [6_075_000, 3_570_000, 1_840_000],
    },
    index=["Kopi Gayo", "Teh Melati", "Gula Aren"],
)

# compare() hanya menampilkan sel yang berbeda, berpasangan (self, other)
selisih = penjualan_april.compare(penjualan_mei)
print(selisih)

# result_names memberi label kolom yang mudah dibaca
berlabel = penjualan_april.compare(penjualan_mei, result_names=("april", "mei"))
print("\ndengan result_names:")
print(berlabel)

# keep_shape mempertahankan seluruh baris dan kolom
lengkap = penjualan_april.compare(penjualan_mei, keep_shape=True)
print("\nkeep_shape=True (sel sama tampil NaN):")
print(lengkap)

Output yang Dihasilkan:

text
            unit             omzet           
            self  other       self      other
Kopi Gayo  120.0  135.0  5400000.0  6075000.0
Gula Aren   60.0   58.0  1920000.0  1840000.0

dengan result_names:
            unit             omzet           
           april    mei      april        mei
Kopi Gayo  120.0  135.0  5400000.0  6075000.0
Gula Aren   60.0   58.0  1920000.0  1840000.0

keep_shape=True (sel sama tampil NaN):
             unit             omzet           
             self  other       self      other
Kopi Gayo   120.0  135.0  5400000.0  6075000.0
Teh Melati    NaN    NaN        NaN        NaN
Gula Aren    60.0   58.0  1920000.0  1840000.0

Mari kita telaah baris-baris kuncinya:

  1. Baris 18-19: compare() tanpa parameter menampilkan dua baris yang berbeda saja, dengan pasangan self (pemanggil, April) dan other (argumen, Mei).
  2. Baris 22-24: result_names=("april", "mei") mengganti label self/other menjadi label bermakna sehingga hasil bisa langsung dilampirkan ke laporan.
  3. Baris 27-29: keep_shape=True mempertahankan seluruh baris dan kolom; sel yang sama kini tampil sebagai pasangan NaN, dan baris Teh Melati kembali muncul.

Membaca Hasil sebagai Alat Audit #

Pola penggunaan compare() di dunia nyata biasanya berupa rekonsiliasi: membandingkan batch hari ini dengan batch kemarin, atau data sebelum dan sesudah transformasi. Bila jumlah baris hasil kecil, tabel berpasangan itu sendiri sudah cukup; bila perbedaan menyebar luas, df.compare(df2).shape memberi ukuran cepat berapa banyak posisi yang berubah. Untuk pipeline, hasil compare() bisa diuji kosong-tidaknya dengan .empty — hasil kosong berarti dua tabel identik, ganti pernyataan pemeriksaan yang lebih berat. Section Pengujian dan Debugging nanti memakai assert_frame_equal untuk keperluan yang sama dengan gaya pengujian unit; compare() adalah versi interaktifnya yang hasilnya bisa dibaca manusia.

Kedua method ini bekerja pada sel, bukan pada kunci gabungan. Chapter berikutnya berpindah ke penggabungan yang urut waktunya: merge_ordered() untuk dua tabel berbasis tanggal, plus anti-join baru pandas 3.0 untuk menemukan baris yang tidak punya pasangan.

Dokumentasi resmi yang relevan: pandas.DataFrame.compare untuk parameter keep_shape, keep_equal, dan result_names, serta User Guide: Merge, join, concatenate and compare yang menempatkan compare berdampingan dengan keluarga merge.