Deret harian 549 baris dari Bagian 1 terlalu halus untuk membaca arah penjualan: lonjakan akhir pekan dan derau harian menutupi pergerakan yang sedang berlangsung. Agregasi per periode menyingkirkan derau itu dengan meringkas banyak baris harian menjadi satu angka per minggu atau per bulan. Pada bagian ini kita memakai resample() di atas groupby() untuk menghasilkan rekap mingguan (“W”) dan bulanan (“ME”) per outlet, membandingkannya dengan pola pd.Grouper, lalu menyusun pivot outlet x bulan yang siap dibaca. Tabel bulanan itulah bahan mentah analisis tren pada Bagian 3.
Rekap Mingguan dan Bulanan per Outlet #
Skrip berikut memuat dataset bersih lewat muat_bersih() dari buat_dataset.py, lalu membangun rekap mingguan, rekap bulanan, dan dua pivot outlet x bulan (total dan rata-rata harian).
"""Mengagregasi deret waktu harian Toko Roti Manis per periode.
Meringkas 549 baris harian menjadi rekap mingguan (resample "W") dan
bulanan (resample "ME") per outlet, membandingkan pola groupby().resample()
dengan pd.Grouper, lalu menyusun pivot outlet x bulan.
"""
import pandas as pd
from buat_dataset import muat_bersih
if __name__ == "__main__":
bersih = muat_bersih()
print("== Deret harian bersih ==")
print(f"{bersih.shape[0]} baris x {bersih.shape[1]} kolom "
f"| index: {bersih.index.dtype}")
print("\n== Rekap mingguan per outlet ==")
mingguan = bersih.groupby("outlet").resample("W").agg(
omzet=("omzet", "sum"),
unit_rata=("unit_terjual", "mean"),
)
print(f"{len(mingguan)} baris | minggu per outlet: "
f"{mingguan.groupby(level=0).size().to_dict()}")
print(mingguan.xs("Cihampelas", level=0).head(3).round(1).to_string())
print("\n== Rekap bulanan per outlet ==")
bulanan = bersih.groupby("outlet").resample("ME").agg(
omzet=("omzet", "sum"),
unit_rata=("unit_terjual", "mean"),
)
print(f"{len(bulanan)} baris (3 outlet x 6 bulan)")
print(bulanan.round(1).to_string())
alt = bersih.groupby(["outlet", pd.Grouper(freq="ME")])["omzet"].sum()
print(f"pola pd.Grouper hasil sama: {alt.equals(bulanan['omzet'])}")
print("\n== Pivot outlet x bulan, total omzet (juta rupiah) ==")
harian = bersih.copy()
harian["bulan"] = harian.index.strftime("%Y-%m")
tabel = harian.pivot_table(
index="outlet", columns="bulan", values="omzet",
aggfunc="sum", margins=True,
)
print((tabel / 1_000_000).round(1).to_string())
print("\n== Pivot outlet x bulan, rata-rata harian (juta rupiah) ==")
rata = harian.pivot_table(
index="outlet", columns="bulan", values="omzet", aggfunc="mean",
)
print((rata / 1_000_000).round(2).to_string())Output yang Dihasilkan:
== Deret harian bersih ==
549 baris x 3 kolom | index: datetime64[us]
== Rekap mingguan per outlet ==
81 baris | minggu per outlet: {'Cihampelas': 27, 'Kemang': 27, 'Malioboro': 27}
omzet unit_rata
tanggal
2026-04-05 17689900 352.0
2026-04-12 25827950 366.9
2026-04-19 24477100 355.4
== Rekap bulanan per outlet ==
18 baris (3 outlet x 6 bulan)
omzet unit_rata
outlet tanggal
Cihampelas 2026-04-30 105114750 354.3
2026-05-31 107153200 351.6
2026-06-30 108114000 364.7
2026-07-31 110241700 359.4
2026-08-31 109858650 362.2
2026-09-30 107684850 368.1
Kemang 2026-04-30 135818450 427.6
2026-05-31 148975300 456.0
2026-06-30 151803400 480.5
2026-07-31 159417250 490.5
2026-08-31 167735700 521.2
2026-09-30 168660450 538.9
Malioboro 2026-04-30 81247050 292.8
2026-05-31 82091950 287.5
2026-06-30 75397400 272.2
2026-07-31 76721300 269.6
2026-08-31 74595400 264.2
2026-09-30 72182400 259.2
pola pd.Grouper hasil sama: True
== Pivot outlet x bulan, total omzet (juta rupiah) ==
bulan 2026-04 2026-05 2026-06 2026-07 2026-08 2026-09 All
outlet
Cihampelas 105.1 107.2 108.1 110.2 109.9 107.7 648.2
Kemang 135.8 149.0 151.8 159.4 167.7 168.7 932.4
Malioboro 81.2 82.1 75.4 76.7 74.6 72.2 462.2
All 322.2 338.2 335.3 346.4 352.2 348.5 2042.8
== Pivot outlet x bulan, rata-rata harian (juta rupiah) ==
bulan 2026-04 2026-05 2026-06 2026-07 2026-08 2026-09
outlet
Cihampelas 3.50 3.46 3.60 3.56 3.54 3.59
Kemang 4.53 4.81 5.06 5.14 5.41 5.62
Malioboro 2.71 2.65 2.51 2.47 2.41 2.41Mari kita telaah bagian-bagian pentingnya:
bersih.groupby("outlet").resample("W"):GroupBy.resample()memotong deret tiap outlet ke bin mingguan; label bin adalah hari Minggu penutup minggu, dan hasilnya 27 minggu per outlet (81 baris untuk tiga outlet)..agg(omzet=("omzet", "sum"), unit_rata=("unit_terjual", "mean")): named aggregation menjalankan dua agregasi berbeda dalam satu panggilan — total omzet dan rata-rata unit harian per minggu.resample("ME"): alias"ME"(month end) menghasilkan enam bin berlabel akhir bulan, 30 April sampai 30 September, sehingga rekap bulanan berisi 18 baris. Alias"M"sudah tidak didukung pandas 3.0 dan memunculkanValueError.pd.Grouper(freq="ME"): pola kedua yang setara —groupby(["outlet", pd.Grouper(freq="ME")])menghasilkan angka yang persis sama (equalsbernilai True), memakaiGrouperbila Anda lebih senang mengelompokkan lewat satu daftar kunci.harian.index.strftime("%Y-%m"): kolombulandibuat dari index datetime, lalupivot_table()menyusun baris outlet x kolom bulan;margins=Truemenambahkan baris dan kolomAllberisi total jaringan (2.042,8 juta rupiah).- Dua pivot dengan
aggfuncberbeda:aggfunc="sum"menunjukkan ukuran total per bulan, sedangkanaggfunc="mean"menunjukkan rata-rata harian yang menghilangkan pengaruh panjang bulan.
Membaca Hasil Agregasi dengan Benar #
Dua tabel pivot terakhir memperlihatkan mengapa keduanya perlu ada. Untuk Kemang, total bulanan dan rata-rata harian sama-sama naik: 135,8 juta dengan 4,53 juta per hari pada April, menjadi 168,7 juta dengan 5,62 juta per hari pada September. Untuk Cihampelas, keduanya bisa berlawanan arah.
| Periode | Argumen freq | Label bin | Hasil di proyek ini |
|---|---|---|---|
| Mingguan | "W" | Minggu penutup minggu | 27 minggu per outlet |
| Bulanan | "ME" | akhir bulan | 6 bulan per outlet |
Teori resampling sudah dibahas tuntas pada chapter Resampling Data dan Frekuensi dan Offset pada section Data Waktu dan Deret Waktu; di proyek ini kita fokus merangkainya dengan groupby() dan pivot_table() untuk data multi-outlet. Tabel bulanan outlet x bulan yang baru terbentuk adalah bahan mentah Bagian 3: dari situ kita menghitung perubahan antar bulan, menghaluskan deret dengan rata-rata bergerak, dan menyimpulkan arah tren tiap outlet.
Sumber bacaan resmi: pandas.DataFrame.resample , pandas.Grouper , dan pandas.DataFrame.pivot_table .