DataFrame.join adalah kenyamanan penggabungan yang mencocokkan baris melalui index, bukan melalui kolom biasa, sedangkan combine_first melengkapi nilai hilang pada satu tabel dengan nilai dari tabel kedua. Topik ini membahas kapan join lebih ringkas daripada merge, kegagalan yang terjadi bila index belum diset, dan pengisian nilai hilang antar dua catatan sensor yang saling melengkapi. Setelah topik ini selesai, penggabungan berbasis index dapat dipilih dengan sengaja dan nilai hilang antartabel dapat dilengkapi tanpa menimpa data yang sudah ada.
join sebagai merge berbasis index#
DataFrame.join menempelkan kolom dari tabel lain dengan mencocokkan label index, sehingga kerjanya setara dengan pd.merge yang memakai left_index=True dan right_index=True. Karena pencocokannya berbasis label, tabel yang akan digabung perlu diset indexnya terlebih dahulu melalui set_index. Blok berikut menyiapkan data yang sama dengan topik merge.
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_join.csv", index=False) # disimpan agar blok berikutnya cukup membaca berkas ini
sensor_meta.to_csv("meta_join.csv", index=False)
print(len(log_mini), len(sensor_meta))8 4Blok berikut meringkas log menjadi satu baris per ruang, menjadikan ruang sebagai index, lalu menggabungkannya dengan meta yang juga diset indexnya.
import pandas as pd
log_mini = pd.read_csv("log_join.csv")
sensor_meta = pd.read_csv("meta_join.csv", parse_dates=["tanggal_kalibrasi"])
ringkasan = log_mini.groupby("ruang", as_index=False)["suhu_c"].mean().round(1)
ringkasan = ringkasan.set_index("ruang")
meta_index = sensor_meta.set_index("ruang")
hasil_join = ringkasan.join(meta_index)
print(ringkasan)
print(hasil_join) suhu_c
ruang
Gudang 21.7
Lab A 24.3
Lab B 24.0
Ruang Arsip 23.0
suhu_c model tanggal_kalibrasi
ruang
Gudang 21.7 NaN NaT
Lab A 24.3 T-100 2025-12-01
Lab B 24.0 T-100 2025-12-10
Ruang Arsip 23.0 T-200 2025-11-20Hasilnya identik dengan merge pada kolom kunci. Baris Gudang dipertahankan dengan kolom meta berisi NaN karena join secara default berperilaku left join, sedangkan Lobi tidak muncul karena tidak ada pada ringkasan. join lebih ringkas ditulis ketika kunci memang seharusnya menjadi index, misalnya sesudah set_index untuk pencarian berbasis label. Apabila kunci masih berupa kolom biasa, pd.merge dengan on tetap menjadi pilihan yang lebih jelas.
join pada index yang belum diset#
join mencocokkan label, sehingga index yang belum diset menghasilkan kecocokan kosong tanpa pesan error apa pun. Blok berikut menggabungkan ringkasan yang masih memakai index bilangan dengan meta yang indexnya sudah berupa nama ruang.
import pandas as pd
log_mini = pd.read_csv("log_join.csv")
sensor_meta = pd.read_csv("meta_join.csv", parse_dates=["tanggal_kalibrasi"])
ringkasan_baris = log_mini.groupby("ruang", as_index=False)["suhu_c"].mean().round(1)
meta_index = sensor_meta.set_index("ruang")
hasil_salah = ringkasan_baris.join(meta_index)
print(hasil_salah.head(3))
print(hasil_salah["model"].isna().all()) ruang suhu_c model tanggal_kalibrasi
0 Gudang 21.7 NaN NaT
1 Lab A 24.3 NaN NaT
2 Lab B 24.0 NaN NaT
TrueKolom model dan tanggal_kalibrasi hadir tetapi seluruh selnya kosong, sebagaimana ditunjukkan nilai True dari isna().all(). Penyebabnya adalah perbedaan label, yaitu bilangan 0 sampai 3 pada ringkasan berhadapan dengan nama ruang pada meta, sehingga tidak ada satu pun kecocokan. Hasil seperti ini tidak melempar error dan baru ketahuan ketika analisis berikutnya menghasilkan angka kosong. Perbaikannya adalah menyamakan index kedua tabel dengan set_index sebelum join dipanggil.
combine_first untuk melengkapi nilai hilang#
Metode combine_first membentuk tabel baru yang berisi nilai tabel pertama, dengan bagian NaN-nya diisi dari tabel kedua. Kasus yang cocok adalah dua catatan sensor pada deret waktu yang sama yang masing-masing kehilangan pengukuran pada jam berbeda, sehingga keduanya saling melengkapi. Blok berikut menggabungkan catatan sensor A dan sensor B.
import numpy as np
import pandas as pd
waktu = pd.to_datetime(["2026-01-05 07:00", "2026-01-05 07:15", "2026-01-05 07:30", "2026-01-05 07:45"])
sensor_a = pd.DataFrame({
"suhu_c": [23.4, np.nan, 24.1, np.nan],
"lembap_pct": [58.2, 61.3, np.nan, 60.4],
}, index=waktu)
sensor_b = pd.DataFrame({
"suhu_c": [np.nan, 23.9, np.nan, 24.6],
"lembap_pct": [np.nan, np.nan, 62.7, 59.8],
}, index=waktu)
lengkap = sensor_a.combine_first(sensor_b)
print(lengkap) suhu_c lembap_pct
2026-01-05 07:00:00 23.4 58.2
2026-01-05 07:15:00 23.9 61.3
2026-01-05 07:30:00 24.1 62.7
2026-01-05 07:45:00 24.6 60.4Pada jam 07.15, suhu sensor A hilang sehingga diambil dari sensor B, sedangkan kelembapannya tetap milik A karena tidak hilang. Nilai yang sudah tersedia pada tabel pertama tidak pernah ditimpa, sehingga metode ini aman untuk melengkapi data dan bukan untuk menggantinya. Index hasil merupakan gabungan label kedua tabel, sehingga baris yang hanya dimiliki salah satu catatan tetap hadir. Kebutuhan serupa pada satu kolom dapat memakai fillna sebagaimana dibahas pada topik Pengisian Nilai Hilang di modul Pembersihan, sedangkan combine_first menangani banyak kolom antar dua tabel sekaligus.
Kesalahan umum#
Kesalahan pada topik ini menyangkut prasyarat yang tidak terpenuhi, yaitu index yang belum diset dan pemakaian combine_first pada data yang saling bertentangan. Dua kebiasaan berikut mencegah keduanya.
- Melakukan
joinketika kunci masih berupa kolom biasa. Hasilnya kolom penuhNaNtanpa error. Set index kedua tabel denganset_indexterlebih dahulu, atau gunakanpd.mergedenganon. - Menggunakan
combine_firstpadahal kedua tabel memiliki nilai pada sel yang sama. Tabel pertama selalu menang secara diam-diam, sehingga metode ini hanya untuk data yang saling melengkapi, bukan untuk rekonsiliasi dua sumber yang bertentangan.
Ringkasan#
DataFrame.joinmenggabungkan berdasarkan label index dan secara default berperilaku left join, sehingga index diset lebih dahulu melaluiset_index.joinlebih ringkas daripadapd.mergeketika kunci memang sudah menjadi index, sedangkanmergedenganonlebih jelas untuk kolom biasa.combine_firstmengisiNaNtabel pertama dari tabel kedua tanpa menimpa nilai yang sudah ada.
Referensi#
- pandas.DataFrame.join — pandas documentation
— Dokumentasi resmi
joinbeserta parameterondanhowversi index. - pandas.DataFrame.combine_first — pandas documentation — Dokumentasi resmi penggabungan dua DataFrame dengan pengisian nilai hilang.