Kunci Join dan Validasi

Parameter on, suffixes, dan validate, serta bahaya duplikasi kunci many-to-many.

Daftar isi

Kualitas sebuah join ditentukan oleh kuncinya, yaitu kolom yang dicocokkan antara dua tabel. Topik ini membahas pemilihan kunci dengan on maupun left_on dan right_on ketika namanya berbeda, pemeriksaan bentuk hubungan antartabel dengan parameter validate, serta bahaya many-to-many yang melipatgandakan baris tanpa pesan apa pun. Setelah topik ini selesai, hasil merge dapat diverifikasi bentuk kuncinya sebelum kesalahan duplikasi menyebar ke analisis berikutnya.

Kunci dengan nama yang berbeda#

Parameter on mensyaratkan kolom kunci bernama sama pada kedua tabel. Apabila namanya berbeda, gunakan left_on untuk kolom kunci tabel kiri dan right_on untuk kolom kunci tabel kanan. Blok berikut menyiapkan log dan meta yang sama dengan topik merge, mengganti nama kolom ruang pada meta menjadi nama_ruang, lalu menggabungkan keduanya.

python Contoh: left_on dan right_on
import pandas as pd

log_mini = pd.DataFrame({
    "ruang": ["Lab A", "Lab B", "Ruang Arsip", "Lab A", "Lab B", "Lab A", "Ruang Arsip", "Gudang"],
    "suhu_c": [23.4, 24.1, 22.8, 24.6, 23.9, 25.0, 23.1, 21.7],
    "lembap_pct": [58.2, 61.3, 63.8, 60.4, 62.7, 57.9, 64.5, 55.3],
})
sensor_meta = pd.DataFrame({
    "ruang": ["Lab A", "Lab B", "Ruang Arsip", "Lobi"],
    "model": ["T-100", "T-100", "T-200", "T-300"],
    "tanggal_kalibrasi": pd.to_datetime(["2025-12-01", "2025-12-10", "2025-11-20", "2025-10-05"]),
})
log_mini.to_csv("log_kunci.csv", index=False)  # disimpan agar blok berikutnya cukup membaca berkas ini
sensor_meta.to_csv("meta_kunci.csv", index=False)
sensor_meta_lain = sensor_meta.rename(columns={"ruang": "nama_ruang"})
hasil = pd.merge(log_mini, sensor_meta_lain, left_on="ruang", right_on="nama_ruang", how="left")
print(hasil[["ruang", "nama_ruang", "model"]].head(3))
print(hasil[["ruang", "nama_ruang", "model"]].tail(1))
text Keluaran
         ruang   nama_ruang  model
0        Lab A        Lab A  T-100
1        Lab B        Lab B  T-100
2  Ruang Arsip  Ruang Arsip  T-200
    ruang nama_ruang model
7  Gudang        NaN   NaN

Kedua kolom kunci dipertahankan pada hasil, sehingga tabel gabungan memuat ruang sekaligus nama_ruang dengan isi yang sama pada baris yang cocok. Baris Gudang tetap muncul berkat how="left" dengan kolom meta berisi NaN. Sesudah verifikasi, salah satu kolom kunci dibuang melalui drop agar tabel tidak memuat dua kolom berisi nilai yang sama. Pencocokan tetap dilakukan berdasarkan nilai, bukan berdasarkan nama, sehingga kombinasi left_on dan right_on setara dengan on pada data yang sudah disamakan namanya.

Validasi bentuk hubungan dengan validate#

Parameter validate memeriksa keunikan kunci pada kedua tabel tanpa mengubah isi hasil. Nilai yang tersedia adalah one_to_one untuk hubungan satu ke satu, m:1 ketika tabel kiri boleh berulang tetapi tabel kanan harus unik, 1:m untuk kebalikannya, dan many_to_many yang tidak melakukan pemeriksaan berarti. Apabila bentuk yang dijanjikan terlanggar, pd.merge melempar MergeError alih-alih menghasilkan tabel yang salah. Blok berikut memvalidasi gabungan log ke meta sebagai hubungan banyak-ke-satu.

python Contoh: validate m:1 pada log dan meta
import pandas as pd

log_mini = pd.read_csv("log_kunci.csv")
sensor_meta = pd.read_csv("meta_kunci.csv", parse_dates=["tanggal_kalibrasi"])
hasil_m1 = pd.merge(log_mini, sensor_meta, on="ruang", validate="m:1")
print(len(log_mini), len(hasil_m1))
text Keluaran
8 7

Log berisi delapan baris dengan ruang yang berulang, sedangkan meta unik per ruang, sehingga validate="m:1" lolos dan hasilnya tujuh baris karena Gudang tidak cocok. Pemeriksaan ini murni verifikasi bentuk dan tidak menambah atau mengurangi baris. Janji bentuk yang terlanjur salah akan berhenti sebagai error, dan itulah tujuan parameter ini.

Blok berikut menguji validate="one_to_one" terhadap meta yang berisi Lab A dua kali, dengan log yang lebih dahulu diringkas menjadi satu baris per ruang agar tabel kiri unik.

python Contoh: validate one_to_one melempar MergeError
import pandas as pd

log_mini = pd.read_csv("log_kunci.csv")
sensor_meta = pd.read_csv("meta_kunci.csv", parse_dates=["tanggal_kalibrasi"])
meta_duplikat = pd.concat([
    sensor_meta,
    pd.DataFrame({
        "ruang": ["Lab A"],
        "model": ["T-150"],
        "tanggal_kalibrasi": pd.to_datetime(["2026-01-02"]),
    }),
], ignore_index=True)
ringkasan = log_mini.groupby("ruang", as_index=False)["suhu_c"].mean().round(1)
print(ringkasan)
try:
    pd.merge(ringkasan, meta_duplikat, on="ruang", validate="one_to_one")
except pd.errors.MergeError as e:
    print(type(e).__name__)
    print(e)
try:
    pd.merge(ringkasan, meta_duplikat, on="ruang", validate="m:1")
except pd.errors.MergeError as e:
    print("m:1 juga menolak:", type(e).__name__)
hasil_aman = pd.merge(ringkasan, sensor_meta, on="ruang", validate="one_to_one")
print(len(ringkasan), len(hasil_aman))
text Keluaran
         ruang  suhu_c
0       Gudang    21.7
1        Lab A    24.3
2        Lab B    24.0
3  Ruang Arsip    23.0
MergeError
Merge keys are not unique in right dataset; not a one-to-one merge
Duplicates in right:
 ruang
Lab A ...
m:1 juga menolak: MergeError
4 3

Pesan MergeError menyebut tepat bagian yang tidak unik, yaitu Lab A pada tabel kanan, sehingga penyebabnya dapat diperbaiki tanpa menebak. Pilihan m:1 pun ditolak karena justru tabel kanan yang berduplikasi, sesuai aturan bahwa tabel kanan pada m:1 harus unik. Pada meta yang bersih, validate="one_to_one" lolos dan hasilnya tiga baris karena Gudang kembali tidak cocok.

Bahaya many-to-many#

Hubungan many-to-many terjadi ketika kunci berduplikasi pada kedua tabel sekaligus, dan bentuk inilah bug penggabungan yang paling sering tidak terlihat. Setiap pasangan baris dengan kunci yang sama dipertahankan seluruhnya, sehingga jumlah baris hasil menjadi perkalian kecocokan per kunci tanpa satu pun error atau peringatan. Blok berikut menggabungkan log dengan tabel catatan yang memuat Lab A dua kali.

python Contoh: kunci berduplikasi di kedua tabel
import pandas as pd

log_mini = pd.read_csv("log_kunci.csv")
catatan_ruang = pd.DataFrame({
    "ruang": ["Lab A", "Lab A"],
    "catatan": ["cek ulang kalibrasi", "ganti baterai"],
})
hasil_m2m = pd.merge(log_mini, catatan_ruang, on="ruang", how="left")
print(len(log_mini), len(hasil_m2m))
print(hasil_m2m[hasil_m2m["ruang"] == "Lab A"][["suhu_c", "catatan"]])
text Keluaran
8 11
   suhu_c              catatan
0    23.4  cek ulang kalibrasi
1    23.4        ganti baterai
4    24.6  cek ulang kalibrasi
5    24.6        ganti baterai
7    25.0  cek ulang kalibrasi
8    25.0        ganti baterai

Delapan baris log menjadi sebelas baris hasil tanpa pesan apa pun. Setiap pembacaan Lab A kini tampil dua kali, sekali dengan setiap catatan yang tersedia, padahal pencatatan sensornya hanya satu. Statistik yang dihitung dari tabel semacam ini membengkak secara diam-diam. Biasakan membandingkan len sebelum dan sesudah merge, dan bersihkan duplikasi kunci dengan drop_duplicates sebagaimana dibahas pada topik Duplikat di modul Pembersihan.

Kesalahan umum#

Kesalahan pada pemilihan kunci tidak selalu berhenti sebagai error, sehingga pemeriksaan manual tetap diperlukan. Tiga kebiasaan berikut menutup celah yang paling sering terjadi.

  • Menganggap validate memperbaiki data. Parameter ini hanya memeriksa bentuk kunci dan melempar MergeError, sedangkan pembersihan duplikat tetap menjadi tugas drop_duplicates sebelum merge.
  • Memilih validate="one_to_one" karena terdengar paling aman. Pada data log yang wajar berulang, bentuk yang tepat adalah m:1, sehingga pilihlah nilai sesuai data, bukan menurut dugaan.
  • Membiarkan hasil many-to-many tanpa pemeriksaan. Bandingkan len sebelum dan sesudah merge pada setiap alur kerja karena tidak ada error yang menolong.

Ringkasan#

  • on dipakai bila nama kolom kunci sama, sedangkan left_on dan right_on dipakai bila berbeda, dan kedua kolom kunci tetap ada pada hasil.
  • validate memeriksa bentuk hubungan tanpa mengubah hasil, dan pelanggaran bentuk melempar MergeError yang menyebut tabel dan kunci yang bermasalah.
  • Kunci yang berduplikasi pada kedua tabel melipatgandakan baris tanpa pesan apa pun, sehingga len wajib dibandingkan sebelum dan sesudah merge.

Referensi#