Dekomposisi Time Series: Tren, Musiman, dan Sisa pada Data Penjualan
Blog/Tips & Trik/Dekomposisi Time Series: Tren, Musiman, dan Sisa pada Data Penjualan

Dekomposisi Time Series: Tren, Musiman, dan Sisa pada Data Penjualan

BimaBima
·23 Oktober 2025·11 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Dekomposisi time series misahin satu deret angka jadi tiga bagian: tren (arah jangka panjang), musiman (pola yang berulang di periode tetap), dan sisa (yang gak kejelasin dua-duanya). Model aditif dipakai kalau ayunan musimannya tetap dalam satuan rupiah, model multiplikatif kalau ayunannya membesar seiring naiknya level penjualan. Di Python, dua baris pakai seasonal_decompose dari statsmodels udah cukup buat lihat ketiganya.

Dekomposisi time series adalah cara misahin satu deret angka berurut waktu jadi tiga bagian: tren, pola musiman, dan sisa yang gak kejelasin dua-duanya.

Gunanya buat jawab pertanyaan yang sering bikin ribut di rapat. Penjualan bulan ini naik 12 persen, itu beneran tumbuh atau cuma karena bulan ini ada dua tanggal gajian?

Di sini aku tunjukin cara misahin ketiganya pakai Python, cara milih model yang benar, dan gimana tiap komponen dipakai buat keputusan.

Apa itu dekomposisi time series?

Dekomposisi time series memecah satu deret waktu jadi komponen yang bisa ditafsirkan terpisah. Tren nunjukin arah jangka panjang, musiman nunjukin pola yang berulang di jarak tetap, dan sisa nampung sesuatu yang gak masuk dua kategori itu. Dengan misahin ketiganya, kamu bisa lihat pertumbuhan asli tanpa terganggu ayunan musiman.

Ada dua bentuk rumus yang dipakai:

Aditif        : Y = Tren + Musiman + Sisa
Multiplikatif : Y = Tren x Musiman x Sisa

Bedanya di cara komponen musimannya diukur. Aditif nganggap efek Sabtu itu tambahan Rp 1,2 juta, berapa pun besar penjualan hariannya.

Multiplikatif nganggap efek Sabtu itu 1,34 kali hari biasa. Kalau penjualan tumbuh, tambahan rupiahnya ikut membesar.

Ciri dataModel yang cocok
Lebar ayunan musiman tetap dari awal sampai akhirAditif
Ayunan makin lebar seiring level naikMultiplikatif
Ada nilai nol atau negatifAditif (multiplikatif gak bisa)
Penjualan tumbuh stabil bertahun-tahunMultiplikatif

Gimana nyiapin data sebelum didekomposisi?

Dekomposisi minta deret yang rapat dan berjarak sama. Satu tanggal bolong bikin perhitungan periodenya meleset, dan hasilnya kelihatan acak padahal datanya sebenernya berpola.

Empat langkah persiapan yang wajib:

  1. Agregasi transaksi jadi satu baris per tanggal
  2. Ubah kolom tanggal jadi tipe datetime lalu jadiin index
  3. Isi tanggal yang bolong, pakai nol kalau toko tutup atau interpolasi kalau datanya emang hilang
  4. Tentukan panjang satu putaran musiman
import pandas as pd

df = pd.read_csv("toko_berkah_transaksi.csv", parse_dates=["tanggal"])

harian = (
    df.groupby("tanggal")["nominal"]
      .sum()
      .sort_index()
)

# rapatkan deret, tanggal yang gak ada transaksi diisi nol
harian = harian.asfreq("D", fill_value=0)

print(harian.head())
print(f"Jumlah hari: {len(harian)}")

Metode asfreq("D") bikin index tanggalnya berurut tiap hari tanpa lompatan. Dokumentasi lengkap soal frekuensi dan penanganan deret waktu di pandas ada di panduan time series pandas.

Pengisian nol cuma benar kalau toko emang tutup. Kalau datanya hilang gara-gara sistem error, pakai interpolate(), soalnya nol palsu bakal narik tren turun.

Gimana cara dekomposisi time series di Python?

Fungsi seasonal_decompose dari statsmodels ngerjain semuanya dalam satu panggilan. Kamu cuma perlu nentuin model dan panjang periodenya.

from statsmodels.tsa.seasonal import seasonal_decompose
import matplotlib.pyplot as plt

hasil = seasonal_decompose(harian, model="additive", period=7)

fig = hasil.plot()
fig.set_size_inches(11, 8)
plt.tight_layout()
plt.show()

# tiap komponen bisa diambil terpisah
tren = hasil.trend
musiman = hasil.seasonal
sisa = hasil.resid

Argumen period=7 artinya satu putaran musiman panjangnya 7 titik data. Buat data harian dengan pola mingguan, ini angkanya.

Buat data bulanan dengan pola tahunan, isi 12. Buat data harian dengan pola tahunan, isi 365, tapi kamu butuh minimal dua tahun data.

Kenapa ujung garis trennya kosong

Tren dihitung pakai rata-rata bergerak terpusat sepanjang satu periode. Buat period 7, dia butuh 3 titik sebelum dan 3 titik sesudah.

Jadi 3 hari pertama dan 3 hari terakhir gak punya nilai tren. Ini normal, bukan tanda ada yang salah.

Cara baca komponen musimannya

import numpy as np

pola = musiman.groupby(musiman.index.dayofweek).mean()
pola.index = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
print(pola.round(0))

Di model aditif, angka positif artinya hari itu biasanya di atas rata-rata sebesar sekian rupiah. Di model multiplikatif, angka 1,34 artinya hari itu biasanya 34 persen di atas hari normal.

Kapan pakai STL dibanding seasonal_decompose?

STL adalah metode dekomposisi yang pakai penghalusan bertahap, jadi pola musimannya boleh berubah pelan-pelan sepanjang waktu. Dia juga lebih tahan terhadap satu dua nilai ekstrem kalau opsi robust diaktifkan. Buat data penjualan Indonesia yang polanya bergeser tiap Ramadan, STL biasanya kasih hasil yang lebih masuk akal.

from statsmodels.tsa.seasonal import STL

stl = STL(harian, period=7, robust=True)
hasil_stl = stl.fit()

fig = hasil_stl.plot()
fig.set_size_inches(11, 8)
plt.show()

Opsi robust=True ngurangin pengaruh hari-hari ekstrem kayak H-1 Lebaran. Tanpa itu, satu hari dengan penjualan tiga kali lipat bisa ngerusak estimasi pola musiman buat seluruh deret.

Aspekseasonal_decomposeSTL
Pola musimanDianggap tetap sepanjang waktuBoleh berubah bertahap
Tahan nilai ekstremGakYa, kalau robust=True
Ujung deretKosong sepanjang setengah periodeTerisi penuh
KecepatanCepat bangetSedikit lebih lambat
Model multiplikatifTersedia lewat argumen modelPerlu log dulu, hasilnya di-eksponen balik

Buat model multiplikatif di STL, ubah datanya jadi log dulu. Setelah dekomposisi, hasil aditif di ruang log setara dengan multiplikatif di ruang asli.

harian_log = np.log(harian.replace(0, np.nan)).interpolate()
stl_log = STL(harian_log, period=7, robust=True).fit()

musiman_faktor = np.exp(stl_log.seasonal)  # 1,34 artinya 34% di atas normal

Contoh kasus: penjualan harian toko_berkah 14 bulan

Data ngulikdata untuk toko_berkah punya 11.407 transaksi dalam 421 hari operasional. Setelah diagregasi jadi total harian dan didekomposisi pakai STL dengan period 7 dan model multiplikatif, hasilnya begini.

Komponen musiman mingguan:

HariFaktor musimanArtinya
Senin0,946% di bawah hari normal
Selasa0,7822% di bawah, hari paling sepi
Rabu0,8614% di bawah
Kamis0,955% di bawah
Jumat1,099% di atas
Sabtu1,3434% di atas, hari paling ramai
Minggu1,044% di atas

Selisih Sabtu lawan Selasa itu 1,72 kali lipat. Pemilik toko sebelumnya nempatin jumlah pegawai yang sama tiap hari.

Komponen tren: naik dari sekitar Rp 7,1 juta per hari di bulan pertama ke Rp 8,6 juta di bulan ke-14. Pertumbuhan bersih 21 persen dalam 14 bulan, atau sekitar 1,4 persen per bulan.

Angka pertumbuhan itu jauh lebih kecil dari yang dirasain pemiliknya. Dia ngira tokonya tumbuh 40 persen, soalnya dia bandingin bulan Ramadan sama bulan biasa.

Komponen sisa: simpangan bakunya Rp 610.000, atau sekitar 7,6 persen dari rata-rata harian. Ada 9 hari dengan sisa lebih dari 3 kali simpangan baku, dan 7 di antaranya jatuh di sekitar libur nasional.

Sisa inilah yang paling berguna buat pemantauan otomatis. Setelah tren dan musiman dikeluarkan, yang tersisa emang layak ditanyain.

Tiap komponen dipakai buat keputusan apa?

KomponenPertanyaan yang dijawabKeputusan yang dipengaruhi
TrenBisnisnya tumbuh atau nggakTarget tahunan, keputusan buka cabang
MusimanKapan ramai dan kapan sepiJadwal shift, jadwal restok, waktu promo
SisaApa ada yang aneh hari iniPeringatan otomatis, investigasi

Buat toko_berkah, komponen musiman langsung jadi tiga perubahan: tambah satu kasir tiap Sabtu, kirim promo tiap Selasa pagi, dan geser jadwal restok dari Sabtu ke Rabu.

Sisa dipakai buat aturan peringatan yang sama polanya kayak deteksi anomali penjualan dengan SQL, cuma di sini baseline-nya udah bersih dari efek hari dalam seminggu.

Kesalahan umum waktu dekomposisi time series

Salah isi period. Ini penyebab nomor satu hasil yang kelihatan acak. Data harian dengan pola mingguan pakai 7, bukan 30 atau 365.

Tanggal bolong dibiarkan. Kalau deretnya gak rapat, posisi hari dalam seminggu jadi geser dan pola musimannya ancur. Selalu jalanin asfreq dulu.

Pakai aditif buat data yang tumbuh cepat. Kalau penjualan naik dua kali lipat dalam setahun, efek Sabtu dalam rupiah juga ikut membesar. Model aditif bakal ninggalin pola sisa yang berbentuk gelombang.

Nafsirin sisa sebagai kesalahan. Sisa bukan berarti data salah. Dia nampung semuanya yang gak dijelasin tren dan musiman, termasuk promo, cuaca, dan kejadian sekali seumur hidup.

Cuma pasang satu periode musiman. Penjualan ritel Indonesia punya pola mingguan sekaligus pola tahunan Ramadan. Satu dekomposisi cuma nangkep satu periode, jadi jalanin dua kali atau pakai MSTL kalau butuh dua-duanya.

Bandingin bulan Ramadan sama bulan biasa. Kesalahan paling mahal dan paling sering. Bandingin Ramadan tahun ini sama Ramadan tahun lalu, atau pakai komponen tren yang udah bersih dari efek musiman.

FAQ

Kapan pakai model aditif dan kapan multiplikatif?

Lihat bentuk grafiknya. Kalau selisih puncak dan lembah musiman kelihatan sama lebarnya dari awal sampai akhir, pakai aditif. Kalau ayunannya makin lebar seiring penjualan naik, pakai multiplikatif. Data penjualan yang tumbuh biasanya multiplikatif. Cara cepat lainnya: coba dua-duanya, lalu pilih yang sisanya paling gak berpola.

Berapa nilai period yang harus aku isi?

Period itu jumlah titik data dalam satu putaran musiman. Data harian dengan pola mingguan pakai 7. Data bulanan dengan pola tahunan pakai 12. Data harian dengan pola tahunan pakai 365, tapi itu butuh minimal dua tahun data. Kalau kamu isi angka yang salah, komponen musimannya bakal kelihatan acak dan gak berulang rapi.

Kenapa awal dan akhir garis tren hasil dekomposisi kosong?

Karena tren dihitung pakai rata-rata bergerak terpusat sepanjang satu periode. Buat period 7, dia butuh 3 titik sebelum dan 3 titik sesudah, jadi 3 titik pertama dan terakhir gak punya nilai. Ini normal dan bukan error. Kalau kamu butuh tren sampai ujung, pakai STL yang ngisi bagian tepinya.

Apa bedanya seasonal_decompose dan STL?

seasonal_decompose pakai rata-rata bergerak sederhana dan nganggap pola musimannya tetap sama sepanjang waktu. STL pakai penghalusan bertahap, jadi pola musimannya boleh berubah pelan-pelan dan dia lebih tahan terhadap satu dua nilai ekstrem. Buat data penjualan Indonesia yang polanya bergeser tiap Ramadan, STL biasanya kasih hasil yang lebih masuk akal.

Dekomposisi bisa dipakai buat forecasting langsung?

Gak langsung, soalnya dia cuma misahin data yang udah ada dan gak bikin ramalan ke depan. Tapi hasilnya jadi bahan bagus buat forecasting. Kamu bisa ramal komponen trennya pakai regresi sederhana, lalu tempelin lagi pola musiman yang udah ketahuan. Model kayak Holt-Winters ngerjain dua langkah itu sekaligus.

Penutup

Tiga hal yang perlu kamu bawa.

Rapatkan deret waktunya dulu sebelum apa pun. Tanggal bolong itu penyebab paling sering hasil dekomposisi kelihatan acak.

Pilih model dari bentuk ayunan musimannya. Data penjualan yang tumbuh hampir selalu multiplikatif.

Tiap komponen punya pemakainya sendiri. Tren buat target, musiman buat jadwal, sisa buat peringatan.

Coba jalanin dekomposisi di data penjualan 6 bulan terakhirmu, lalu lihat faktor musiman per hari dalam seminggu. Selisih hari paling ramai dan paling sepi biasanya lebih besar dari dugaan.

Kalau kamu mau segmentasi pelanggan setelah pola waktunya ketahuan, lanjut ke cara menentukan jumlah cluster. Istilah outlier dan metric yang dipakai di sini juga ada penjelasan singkatnya di glossary.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel terkait

Pandas groupby: Agregasi Data ala Pivot di Python (2026)
Tips & Trik
20 Juli 2026•9 menit baca

Pandas groupby: Agregasi Data ala Pivot di Python (2026)

groupby ngelompokin baris berdasarkan kolom, lalu ngitung ringkasan per grup kayak total atau rata-rata. Ini pivot-nya pandas.

BimaBima
Pandas to_excel: Ekspor DataFrame ke Excel (2026)
Tips & Trik
18 Juli 2026•8 menit baca

Pandas to_excel: Ekspor DataFrame ke Excel (2026)

to_excel nyimpen DataFrame pandas jadi file Excel .xlsx. Ini cara pakainya, dari satu sheet sampai banyak sheet, plus setelan yang bikin hasilnya rapi.

BimaBima
Pandas read_excel: Baca File Excel di Python
Tips & Trik
16 Juli 2026•8 menit baca

Pandas read_excel: Baca File Excel di Python

pandas read_excel baca file Excel jadi DataFrame, bisa pilih sheet tertentu dan lompatin baris judul yang berantakan. Ini cara pakai plus parameter penting dengan contoh data toko.

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

© 2026 Ngulik Data. Semua hak dilindungi.

TAUTAN
BantuanHargaDatasetBlogAfiliasi
LEGAL
Syarat & KetentuanKebijakan Privasi
Ngulik Data
DatasetLeaderboardBlogStore