Pada Chapter Mengisi Nilai Kosong di section Data Cleaning, ffill() sudah kita sentuh sekilas sebagai salah satu strategi fillna(). Chapter ini membedah kedua method tersebut secara tuntas: ke mana arah pengisiannya, apa yang terjadi pada lubang di ujung deret, dan bagaimana parameter limit serta limit_area mengendalikan seberapa jauh pandas boleh mengisi. Bahan latihannya tetap data harian suhu Sensor Utara di Gudang Kopi Aroma Nusantara selama 1-14 Januari 2026, kali ini dengan index tanggal.
Dua Arah Pengisian #
ffill() (forward fill) meneruskan nilai terakhir yang terlihat ke bawah, sedangkan bfill() (backward fill) menarik nilai dari baris berikutnya ke atas. Keduanya bekerja sesuai urutan baris atau index, sehingga paling tepat untuk data yang urutannya bermakna seperti log sensor, deret waktu, atau catatan transaksi berurutan. Skrip berikut menjalankan keduanya pada deret suhu yang sama agar perbedaannya terlihat jelas:
"""Mengisi kekosongan suhu gudang dengan ffill(), bfill(), dan parameter limit."""
import pandas as pd
import numpy as np
kalender = pd.date_range("2026-01-01", periods=14, freq="D")
suhu = pd.Series(
[
22.5, 23.1, np.nan, 24.0, 24.8, np.nan, np.nan,
25.5, 41.0, 25.2, 12.0, 23.8, 24.1, np.nan,
],
index=kalender,
name="suhu",
)
print("Data asli (suhu Sensor Utara, 1-14 Januari 2026):")
print(suhu)
print()
print("ffill() meneruskan nilai terakhir yang terlihat:")
print(suhu.ffill())
print()
print("bfill() menarik nilai dari pembacaan berikutnya:")
print(suhu.bfill())
print()
terbatas = suhu.ffill(limit=1)
print("ffill(limit=1), hari yang masih kosong:", end=" ")
print(terbatas.index[terbatas.isna()].strftime("%d Jan").tolist())
dalam = suhu.ffill(limit_area="inside")
print("ffill(limit_area='inside'), hari masih kosong:", end=" ")
print(dalam.index[dalam.isna()].strftime("%d Jan").tolist())
print()
status = pd.Series([None, "normal", "normal", None, "cek"], name="status")
print("bfill() pada kolom status bertipe str:")
print(status.bfill())Output yang Dihasilkan:
Data asli (suhu Sensor Utara, 1-14 Januari 2026):
2026-01-01 22.5
2026-01-02 23.1
2026-01-03 NaN
2026-01-04 24.0
2026-01-05 24.8
2026-01-06 NaN
2026-01-07 NaN
2026-01-08 25.5
2026-01-09 41.0
2026-01-10 25.2
2026-01-11 12.0
2026-01-12 23.8
2026-01-13 24.1
2026-01-14 NaN
Freq: D, Name: suhu, dtype: float64
ffill() meneruskan nilai terakhir yang terlihat:
2026-01-01 22.5
2026-01-02 23.1
2026-01-03 23.1
2026-01-04 24.0
2026-01-05 24.8
2026-01-06 24.8
2026-01-07 24.8
2026-01-08 25.5
2026-01-09 41.0
2026-01-10 25.2
2026-01-11 12.0
2026-01-12 23.8
2026-01-13 24.1
2026-01-14 24.1
Freq: D, Name: suhu, dtype: float64
bfill() menarik nilai dari pembacaan berikutnya:
2026-01-01 22.5
2026-01-02 23.1
2026-01-03 24.0
2026-01-04 24.0
2026-01-05 24.8
2026-01-06 25.5
2026-01-07 25.5
2026-01-08 25.5
2026-01-09 41.0
2026-01-10 25.2
2026-01-11 12.0
2026-01-12 23.8
2026-01-13 24.1
2026-01-14 NaN
Freq: D, Name: suhu, dtype: float64
ffill(limit=1), hari yang masih kosong: ['07 Jan']
ffill(limit_area='inside'), hari masih kosong: ['14 Jan']
bfill() pada kolom status bertipe str:
0 normal
1 normal
2 normal
3 cek
4 cek
Name: status, dtype: strMari kita telaah hasilnya:
- Baris 5-13 (deret
suhu): Series berindex tanggal dengan empat lubang, yaitu 3, 6, 7, dan 14 Januari; dua lubang 6-7 Januari berurutan sengaja dibuat untuk menguji lubang panjang. - Baris 20 (
suhu.ffill()): 3 Januari terisi23.1dari 2 Januari, 6 dan 7 Januari sama-sama terisi24.8dari 5 Januari, dan 14 Januari terisi24.1dari 13 Januari. - Baris 24 (
suhu.bfill()): 3 Januari kini terisi24.0dari 4 Januari, 6 dan 7 Januari terisi25.5dari 8 Januari, sedangkan 14 Januari tetapNaNkarena tidak ada pembacaan setelahnya.
Perhatikan lubang 3 Januari: ffill() memberi 23.1 sedangkan bfill() memberi 24.0. Keduanya benar secara mekanisme, tetapi menjawab pertanyaan berbeda — “suhu terakhir yang diketahui” berbanding “suhu berikutnya yang diketahui”. Lubang di akhir deret justru hanya bisa diisi ffill(), dan itu semacam ekstrapolasi: angkanya terlihat sah padahal hanya nilai lama yang disalin. Sebaliknya, bfill() tidak pernah bisa mengisi kekosongan di ujung bawah data.
Mengendalikan Seberapa Jauh Mengisi #
Pengisian tanpa batas berisiko menyalin nilai basi ke banyak baris. Dua parameter berikut menahan langkah pandas:
| Parameter | Fungsi | Hasil pada data kita |
|---|---|---|
limit=n | Mengisi maksimal n sel kosong berurutan per lubang | ffill(limit=1) mengisi 6 Januari, membiarkan 7 Januari kosong |
limit_area="inside" | Hanya mengisi lubang yang diapit dua nilai terisi | 14 Januari (di ujung) dibiarkan kosong |
Baris 27-33 pada skrip memakai keduanya dan mencetak daftar tanggal yang tetap kosong: ['07 Jan'] untuk limit=1 dan ['14 Jan'] untuk limit_area="inside". Pola kombinasi ffill(limit_area="inside") praktis ketika kita tidak ingin menambah klaim data di ujung deret, misalnya hari ini yang memang belum selesai tercatat. Dokumentasi resmi pandas.DataFrame.ffill
dan pandas.DataFrame.bfill
merinci parameter yang tersedia, dan pada Series kedua method berperilaku sama.
Mengisi Kolom Teks #
Kekosongan tidak hanya terjadi pada angka. Pada pandas 3.0, kolom teks bertipe str dengan sel kosong NaN juga bisa diisi ffill() dan bfill(), asalkan nilai pengisinya memang string. Baris 36-38 skrip mendemonstrasikan bfill() pada kolom status: sel kosong pertama yang menempel di ujung atas terisi "normal" dari baris berikutnya, dan sel kosong sebelum "cek" turut terisi. Method pandas.Series.bfill
menyalin nilai tanpa mengubah dtype kolom.
Sekarang kita bisa mengisi lubang dengan nilai tetangga terdekat. Pertanyaannya, bila besaran berubah landai seperti suhu, apakah menyalin satu nilai lama memang paling realistis? Chapter berikutnya menjawabnya dengan interpolate(), yang menghitung nilai tengah di antara dua titik terisi alih-alih menyalin salah satunya.