Saat memprediksi hari ini, informasi paling berharga biasanya bukan hari ini itu sendiri, melainkan kemarin. Penjualan kemarin, penjualan hari yang sama minggu lalu, dan rata-rata beberapa hari terakhir membentuk gambaran momentum yang tak bisa ditangkap feature kalender mana pun. Pembuatan fitur deret waktu menyusun gambaran itu secara sistematis lewat tiga alat: lag (menggeser nilai ke masa lalu), rolling window (meringkas jendela beberapa hari), dan diff (selisih antar waktu). Satu aturan menjaganya: jendela hanya boleh mengintip masa lalu — melanggarnya berarti membocorkan jawaban kepada model.
Fitur Lag: Membawa Kemarin ke Hari Ini #
Data kita adalah penjualan empat belas hari berturut-turut. Fitur lag dibuat dengan shift(n): nilai pada baris ke-i digeser ke bawah n langkah, sehingga baris hari ini menerima nilai hari ke-i-n:
import pandas as pd
deret = pd.DataFrame({
"gelas_terjual": [120, 135, 110, 128, 142, 168, 175, 130,
125, 118, 138, 150, 172, 180],
})
fitur = deret.copy()
fitur["lag_1"] = fitur["gelas_terjual"].shift(1)
fitur["lag_7"] = fitur["gelas_terjual"].shift(7)
fitur["naik_dari_kemarin"] = fitur["gelas_terjual"].diff()
print(fitur.round(1))Output yang Dihasilkan:
gelas_terjual lag_1 lag_7 naik_dari_kemarin
0 120 NaN NaN NaN
1 135 120.0 NaN 15.0
2 110 135.0 NaN -25.0
3 128 110.0 NaN 18.0
4 142 128.0 NaN 14.0
5 168 142.0 NaN 26.0
6 175 168.0 NaN 7.0
7 130 175.0 120.0 -45.0
8 125 130.0 135.0 -5.0
9 118 125.0 110.0 -7.0
10 138 118.0 128.0 20.0
11 150 138.0 142.0 12.0
12 172 150.0 168.0 22.0
13 180 172.0 175.0 8.0Mari kita amati cara kerjanya:
- Baris 9 (
shift(1)): kolom digeser satu baris ke bawah. Baris ke-2 kini berpasangan dengan nilai baris ke-1 — kemarin menyapa hari ini. Baris pertama kehilangan pasangannya dan menjadiNaN. - Baris 10 (
shift(7)): pergeseran tujuh baris menangkap “hari yang sama minggu lalu” untuk data harian. Perhatikan bahwa tujuh baris pertama kosong — fitur lag n menuntut setidaknya n baris riwayat sebelum baris tersebut. - Baris 11 (
diff()): selisihhari_ini - kemarin, pembungkus ringkas darishift(1)lalu dikurangkan. Nilai +26 pada baris ke-5 berarti hari itu naik 26 gelas dari sehari sebelumnya — arah pergerakan yang tidak terlihat pada angka mentah. - Kolom
lag_7: mulai baris ke-7, nilainya (120, 135, 110, …) persis menyalin tujuh baris pertama — persis perilaku yang kita harapkan.
Pemilihan lag yang tepat mengikuti ritme datanya: data harian bernada mingguan cocok dengan lag_7, data penjualan bulanan sering memakai lag_12 (tahun lalu), dan data per jam bisa memakai lag_24.
Rolling Window: Merangkum Ritme Beberapa Hari #
Satu angka kemarin bisa saja hari yang sial. Rata-rata tiga hari terakhir lebih tenang — dan itulah pekerjaan rolling window. Kombinasi shift(1).rolling(3).mean() berarti: geser dulu satu langkah, lalu rata-ratakan tiga hari yang tersisa. Kita bandingkan berdampingan dengan versi tanpa shift yang keliru:
import pandas as pd
deret = pd.DataFrame({
"gelas_terjual": [120, 135, 110, 128, 142, 168, 175, 130,
125, 118, 138, 150, 172, 180],
})
fitur = deret.copy()
fitur["rata_3_hari_sebelumnya"] = (
fitur["gelas_terjual"].shift(1).rolling(3, min_periods=1).mean()
)
fitur["rata_3_termasuk_hari_ini"] = (
fitur["gelas_terjual"].rolling(3, min_periods=1).mean()
)
print(fitur.round(2))Output yang Dihasilkan:
gelas_terjual rata_3_hari_sebelumnya rata_3_termasuk_hari_ini
0 120 NaN 120.00
1 135 120.00 127.50
2 110 127.50 121.67
3 128 121.67 124.33
4 142 124.33 126.67
5 168 126.67 146.00
6 175 146.00 161.67
7 130 161.67 157.67
8 125 157.67 143.33
9 118 143.33 124.33
10 138 124.33 127.00
11 150 127.00 135.33
12 172 135.33 153.33
13 180 153.33 167.33Dua kolom di kanan tampak serupa padahal berbeda nasib:
- Baris 9-11 (
shift(1).rolling(3, min_periods=1).mean()): urutannya penting — geser dulu, baru rata-rata. Baris hari ini kini merangkum tiga hari sebelum hari itu: baris ke-7 mencatat 161,67 yaitu rata-rata hari ke-4 sampai ke-6 (142, 168, 175). Argumenmin_periods=1mengizinkan jendela terisi sebagian: baris kedua cukup dengan satu nilai kemarin (120,00). - Baris 12-14 (
rolling(3).mean()tanpa shift): kolom pembanding ini memuat nilai hari ini di dalam jendelanya sendiri. Baris ke-7 mencatat 161,67 juga — kebetulan sama — tetapi baris ke-6 (146,00) sudah memakai angka 168 milik hari itu sendiri. - Mengapa kedua kolom bisa berangka sama di beberapa baris? Karena rata-rata bergeser satu langkah: jendela termasuk hari ini pada baris ke-i berisi hari ke-i-2 sampai ke-i, sedangkan jendela masa lalu pada baris ke-i+1 berisi hari ke-i-2 sampai ke-i juga — isi sama, pemilik baris berbeda.
Rangkuman #
shift(n)membuat fitur lag: kemarin (lag_1), minggu lalu (lag_7), atau periode mana pun yang mengikuti ritme data.diff()menghasilkan perubahan antar periode — arah dan laju pergerakan yang tidak terlihat pada nilai mentah.shift(1).rolling(k, min_periods=1).mean()merangkum k hari terakhir tanpa menyentuh hari ini;min_periodsmenjaga baris awal tetap terisi.- Aturan emas jendela: hanya masa lalu. Rolling yang memuat nilai hari ini membocorkan jawaban dan menggelembungkan skor evaluasi secara palsu.
Nilai kemarin dan rata-rata seminggu membuat tiap baris hari kini kaya konteks. Berikutnya kita berpindah sudut pandang: dari tiap baris ke tiap pelanggan — meringkas puluhan transaksi menjadi beberapa fitur identitas lewat agregasi.