TL;DR
Pandas resample ngelompokkin data time series ke frekuensi waktu tertentu, kayak harian jadi bulanan, lalu ngeagregasi tiap kelompok. Syarat utamanya, DataFrame harus punya indeks bertipe datetime. Aturan frekuensi ditulis sebagai kode singkat: D harian, W mingguan, ME akhir bulan, QE akhir kuartal. Setelah resample, kamu bisa pakai sum, mean, atau agg buat banyak kolom sekaligus.
Pandas resample ngelompokkin data time series ke frekuensi waktu tertentu, kayak harian jadi bulanan, lalu ngeagregasi tiap kelompok. Satu method buat ngeringkas data transaksi yang terlalu ramai jadi angka yang kebaca.
Data penjualan harian itu detail, tapi susah dilihat polanya. 365 baris setahun bikin grafik penuh sesak. Yang bos kamu mau biasanya sederhana: total per bulan, atau rata-rata per minggu.
resample ngerjain itu dalam satu baris, asal indeksnya tanggal. Ini pekerjaan yang di SQL butuh GROUP BY dengan fungsi tanggal, di pandas cukup satu method.
resample adalah method pandas buat ngelompokkin data berdasarkan interval waktu, lalu ngejalanin agregasi kayak sum atau mean di tiap interval. Anggap aja GROUP BY khusus waktu. Bedanya, resample ngerti kalender, jadi dia tau akhir bulan, akhir kuartal, dan minggu tanpa kamu hitung manual.
Syarat wajibnya, DataFrame harus punya indeks datetime. Ini alasan langkah pertama selalu benerin tipe tanggal dulu.
resample butuh DatetimeIndex. Kalau tanggal masih kolom teks, ubah dulu pakai pd.to_datetime, lalu jadikan indeks.
import pandas as pd
df['tanggal'] = pd.to_datetime(df['tanggal'])
df = df.set_index('tanggal')
Kalau nggak mau ubah indeks, pakai argumen on buat nunjuk kolom tanggal langsung:
df.resample('ME', on='tanggal')['omzet'].sum()
Kolom yang ditunjuk tetap harus bertipe datetime. Proses ngubah bentuk data kayak gini bagian dari data transformation yang jadi rutinitas harian analis.
Ini kasus paling umum. Data transaksi harian, mau jadi total per bulan.
omzet_bulanan = df.resample('ME')['omzet'].sum()
Kode 'ME' artinya month-end, tiap kelompok berakhir di hari terakhir bulan. Hasilnya satu baris per bulan dengan total omzetnya.
Aturan frekuensi lain yang sering kepakai:
| Kode | Frekuensi |
|---|---|
| D | Harian |
| W | Mingguan (default berakhir Minggu) |
| ME | Akhir bulan |
| QE | Akhir kuartal |
| YE | Akhir tahun |
Catatan versi: mulai pandas 2.2, kode bulanan berubah dari 'M' jadi 'ME' dan kuartal dari 'Q' jadi 'QE'. Kode lama masih jalan tapi ngasih peringatan. Kalau pakai pandas lama, 'M' masih valid.
Kalau mau lebih dari satu ringkasan, pakai agg dengan dictionary. Tiap kolom bisa dapet fungsi berbeda.
ringkasan = df.resample('ME').agg({
'omzet': 'sum',
'id_transaksi': 'count',
'harga_satuan': 'mean'
})
ringkasan.columns = ['total_omzet', 'jml_transaksi', 'rata_harga']
Satu resample, tiga metrik bulanan sekaligus. Ini jauh lebih ringkas daripada nulis tiga resample terpisah.
resample ngasih baris buat tiap periode di rentang, termasuk yang nggak ada datanya. Periode kosong itu isinya NaN. Cara ngisinya tergantung makna data.
# Penjualan kosong = nol
omzet_bulanan = df.resample('ME')['omzet'].sum().fillna(0)
# Saldo kosong = sama dengan periode sebelumnya
saldo = df.resample('D')['saldo'].last().ffill()
Salah pilih cara isi bisa bikin angka menyesatkan. Penjualan yang kosong artinya nol. Tapi saldo rekening yang kosong artinya sama dengan hari sebelumnya, bukan nol.
Toko Berkah, UMKM kelontong di dataset latihan ngulikdata, punya 1.240 transaksi harian selama 6 bulan (Januari sampai Juni 2026). Dilihat harian, datanya naik turun tiap hari dan susah dibaca.
Setelah resample('ME') buat total bulanan, polanya langsung kelihatan. Omzet naik stabil dari Januari (Rp58 juta) sampai puncaknya di April (Rp94 juta), lalu turun di Mei dan Juni. April yang tinggi itu bertepatan dengan Ramadan, dan kenaikannya 62% dibanding rata-rata bulan lain.
Yang lebih menarik muncul dari resample('W') mingguan. Dari 26 minggu, minggu ke-2 tiap bulan konsisten jadi yang terendah, rata-rata 22% di bawah minggu pertama. Ini pola pasca-gajian: belanja rame di awal bulan, sepi di pertengahan. Temuan ini bikin pemilik toko mindahin promo diskon ke minggu kedua, buat ngangkat titik terlemahnya.
Error paling sering: resample dipanggil tapi indeksnya masih angka biasa. Pesannya "Only valid with DatetimeIndex". Solusinya set_index ke kolom tanggal dulu, atau pakai argumen on.
Kalau tanggal belum dikonversi pd.to_datetime, set_index tetap jalan tapi resample gagal. Cek df.index.dtype, harus datetime64, bukan object.
Di pandas 2.2 ke atas, 'M' dan 'Q' ngasih peringatan deprecation. Ganti ke 'ME' dan 'QE' biar aman di versi baru.
Periode kosong ngasih NaN. Kalau langsung dipakai buat persentase atau chart tanpa fillna, hasilnya bolong. Tentuin dulu apakah kosong berarti nol atau lanjutan.
Buat daftar lengkap aturan frekuensi, cek dokumentasi resample di pandas.
DataFrame harus punya indeks bertipe datetime. Kalau tanggal masih jadi kolom biasa, ubah dulu pakai pd.to_datetime, lalu jadikan indeks dengan set_index. Tanpa DatetimeIndex, resample bakal error. Alternatifnya, pakai argumen on='nama_kolom' buat nunjuk kolom tanggal langsung tanpa harus set_index dulu, tapi kolom itu tetap harus bertipe datetime.
groupby ngelompokkin berdasarkan nilai kolom apa pun, sedangkan resample khusus ngelompokkin berdasarkan interval waktu di indeks datetime. resample otomatis ngisi periode yang kosong dengan NaN, jadi minggu tanpa data tetap muncul. groupby biasa nggak ngasih baris buat periode yang nggak ada datanya. Buat data waktu berkala, resample lebih pas.
Kode itu aturan frekuensi. D harian, W mingguan, ME akhir bulan, QE akhir kuartal, YE akhir tahun, dan H per jam. Mulai pandas 2.2, kode bulanan berubah dari M jadi ME dan kuartal dari Q jadi QE, sedangkan yang lama masih jalan tapi ngasih peringatan. Kamu bisa gabung angka, misalnya 2W buat tiap dua minggu.
Pakai method agg dengan dictionary. Contohnya df.resample('ME').agg({'omzet': 'sum', 'transaksi': 'count', 'harga': 'mean'}). Tiap kolom bisa dikasih fungsi agregasi berbeda. Ini lebih ringkas daripada resample terpisah tiap kolom. Kamu juga bisa kasih list fungsi ke satu kolom, misalnya 'omzet': ['sum', 'mean'] buat dua hasil sekaligus.
Periode tanpa data ngasih NaN setelah resample. Buat total penjualan, ganti jadi nol pakai fillna(0). Buat data yang sifatnya kontinu kayak saldo, isi pakai ffill yang nyalin nilai terakhir ke periode kosong. Pilih cara isi sesuai makna datanya. Penjualan yang kosong artinya nol, tapi saldo yang kosong artinya sama dengan hari sebelumnya.
Coba sekarang: ambil satu file transaksi harian, ubah tanggalnya jadi indeks, lalu resample('ME') buat lihat total bulanan. Pola musiman yang nggak kelihatan di data harian sering langsung muncul.
Mau bandingin caranya di SQL? Baca moving average SQL buat teknik haluskan tren yang sering dipakai bareng agregasi waktu.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Nama toko ketik campur huruf besar-kecil, spasi nyasar di ujung, atau kode produk nempel jadi satu. Accessor .str di pandas ngerapiin semua itu tanpa loop.
Model machine learning cuma ngerti angka, bukan teks kayak merah atau biru. get_dummies ngubah kolom kategori jadi kolom 0/1 dalam satu baris kode.
Cara pakai pandas crosstab buat bikin tabel silang yang menghitung frekuensi antar dua kategori. Contoh analisis kategori produk per kota UMKM.