Chapter-chapter pada section Data Waktu dan Deret Waktu sudah membedah tiap jendela satu per satu: rolling() untuk statistik bergerak, expanding() untuk statistik kumulatif, dan ewm() untuk bobot eksponensial. Chapter ini merangkainya kembali sebagai satu sistem pemilihan: ketiganya disandingkan pada data yang sama agar perbedaan karakternya terlihat jelas, lalu melengkapi perangkat itu dengan kemampuan yang belum dibahas sebelumnya, yaitu memasang fungsi kustom di dalam jendela lewat apply() beserta parameter raw. Data contohnya sepuluh hari penjualan harian dalam ribu rupiah.
Tiga Keluarga Window pada Data yang Sama #
Script berikut membangun satu Series penjualan, lalu menghitung rata-rata dengan ketiga jenis window dan menyandingkannya dalam satu DataFrame.
import pandas as pd
penjualan = pd.Series(
[120, 135, 150, 90, 180, 200, 210, 130, 145, 160],
index=pd.date_range("2026-03-02", periods=10, freq="D", name="tanggal"),
name="penjualan",
)
# tiga keluarga window pada data yang sama, disandingkan
ringkas = pd.DataFrame({
"rolling3": penjualan.rolling(window=3).mean(),
"expanding": penjualan.expanding().mean(),
"ewm_span3": penjualan.ewm(span=3).mean(),
})
print(ringkas.round(1))
print()
# fungsi kustom di dalam jendela: rentang max-min per jendela
def rentang(arr):
return arr.max() - arr.min()
print(penjualan.rolling(window=3).apply(rentang, raw=True))
print()
# raw=True mengirim ndarray, raw=False mengirim Series
tipe_argumen = []
def catat_tipe(arr):
tipe_argumen.append(type(arr).__name__)
return arr.max() - arr.min()
penjualan.rolling(window=3).apply(catat_tipe, raw=True)
print("raw=True :", tipe_argumen[0])
tipe_argumen.clear()
penjualan.rolling(window=3).apply(catat_tipe, raw=False)
print("raw=False :", tipe_argumen[0])
print()
# hasil raw=True dan raw=False identik; bedanya hanya performa
a = penjualan.rolling(window=3).apply(rentang, raw=True)
b = penjualan.rolling(window=3).apply(rentang, raw=False)
print("hasil identik:", a.equals(b))
print()
# min_periods=1: fungsi kustom mulai sejak jendela belum penuh
print(penjualan.rolling(window=3, min_periods=1).apply(rentang, raw=True))
# groupby().rolling(): jendela dihitung per kelompok, bukan per kolom
df = pd.DataFrame(
{
"toko": ["Gambir", "Gambir", "Gambir", "Cihampelas", "Cihampelas", "Cihampelas"],
"omzet": [100, 120, 140, 200, 190, 210],
}
)
per_toko = df.groupby("toko").rolling(window=2, on="omzet")["omzet"].mean()
print()
print(per_toko.round(1))Output yang Dihasilkan:
rolling3 expanding ewm_span3
tanggal
2026-03-02 NaN 120.0 120.0
2026-03-03 NaN 127.5 130.0
2026-03-04 135.0 135.0 141.4
2026-03-05 125.0 123.8 114.0
2026-03-06 140.0 135.0 148.1
2026-03-07 156.7 145.8 174.4
2026-03-08 196.7 155.0 192.4
2026-03-09 180.0 151.9 161.1
2026-03-10 161.7 151.1 153.0
2026-03-11 145.0 152.0 156.5
tanggal
2026-03-02 NaN
2026-03-03 NaN
2026-03-04 30.0
2026-03-05 60.0
2026-03-06 90.0
2026-03-07 110.0
2026-03-08 30.0
2026-03-09 80.0
2026-03-10 80.0
2026-03-11 30.0
Freq: D, Name: penjualan, dtype: float64
raw=True : ndarray
raw=False : Series
hasil identik: True
tanggal
2026-03-02 0.0
2026-03-03 15.0
2026-03-04 30.0
2026-03-05 60.0
2026-03-06 90.0
2026-03-07 110.0
2026-03-08 30.0
2026-03-09 80.0
2026-03-10 80.0
2026-03-11 30.0
Freq: D, Name: penjualan, dtype: float64
toko omzet
Cihampelas 200 NaN
190 195.0
210 200.0
Gambir 100 NaN
120 110.0
140 130.0
Name: omzet, dtype: float64Mari kita bedah bagian pentingnya:
- Baris 10-14 (penyandingan): ketiga hasil menjadi kolom satu DataFrame; karena semua index bertanggal, penyandingan berjalan otomatis tanpa reindex.
- Kolom
rolling3: dua baris pertamaNaNkarena jendela 3 hari belum penuh — perilakumin_periodsdefault yang sama dengan ukuran jendela. - Kolom
expanding: terisi sejak baris pertama karena jendelanya tumbuh dari satu observasi; nilai baris terakhir152.0adalah rata-rata seluruh data. - Kolom
ewm_span3: bereaksi paling cepat; pada baris 2026-03-05 yang turun ke90, nilainya langsung jatuh ke114.0, jauh di bawahrolling3yang masih125.0.
Memilih Window yang Tepat #
Tabel berikut merangkum kapan masing-masing window paling pantas dipakai.
| Aspek | rolling() | expanding() | ewm() |
|---|---|---|---|
| Ukuran jendela | tetap, argumen window | tumbuh sampai seluruh data | tidak berujung, bobot menurun |
| Bobot observasi | sama rata di dalam jendela | sama rata | terbesar pada data terbaru |
| Baris awal | NaN sampai min_periods terpenuhi | terisi sejak min_periods (default 1) | terisi sejak baris pertama |
| Kasus khas | moving average, volatilitas bergerak | rekor, rata-rata sejak awal | tren yang harus responsif |
Aturan praktisnya: pilih rolling() bila definisi statistik memang mengikat periode tertentu (misalnya “rata-rata 7 hari”), expanding() bila pertanyaannya “sejauh ini”, dan ewm() bila data terbaru lebih bermakna daripada data lama. Parameter span dan alpha pada ewm() serta mode adjust sudah dibahas pada chapter Exponentially Weighted Window; di sini cukup span=3 yang berarti alpha = 2/(span+1) = 0.5.
Fungsi Kustom di Dalam Jendela #
Statistik bawaan seperti mean() dan std() tidak mencakup semua kebutuhan; apply() menerima fungsi apa pun dan menjalankannya per jendela. Baris 19-22 mendefinisikan rentang (selisih maksimum–minimum) dan menerapkannya dengan raw=True. Parameter raw menentukan tipe argumen yang diterima fungsi: raw=True mengirim array NumPy mentah, raw=False mengirim Series lengkap dengan index. Blok catat_tipe membuktikannya lewat output ndarray dan Series, sedangkan blok terakhir menegaskan bahwa keduanya menghasilkan angka yang identik. Pilih raw=True bila fungsi hanya berhitung dengan nilai; pilih raw=False bila label index dibutuhkan, misalnya untuk mencatat tanggal akhir jendela.
Mengatur Awal Perhitungan dengan min_periods #
Blok terakhir memakai min_periods=1 pada apply(): fungsi kustom mulai dipanggil sejak jendela pertama walau isinya baru satu nilai, sehingga dua baris awal berisi 0.0 dan 15.0 alih-alih NaN. Nilai default-nya sama dengan ukuran jendela, jadi setiap kali Anda melihat kepala hasil rolling yang kosong, itu pilihan perhitungan — bukan kecacatan data.
Jendela juga bisa berjalan per kelompok: df.groupby("toko").rolling(window=2) menghitung rata-rata bergerak dalam batas masing-masing toko, sehingga jendela tidak menyeret angka dari toko lain. Pola groupby().rolling() ini adalah penyambung langsung antara section Groupby dan section ini.
Dengan ketiga window dan fungsi kustomnya dalam genggaman, perangkat analisis kita sudah lengkap untuk pertanyaan berbasis waktu. Chapter berikutnya beralih ke persoalan skala: menulis ekspresi seleksi dan aritmetika yang ringkas dengan query() dan eval(), dua fasilitas yang berkilau ketika DataFrame membesar.
Referensi resmi untuk chapter ini: user guide Windowing operations , pandas.DataFrame.rolling , dan pandas.DataFrame.ewm .