Data

Data yang dipakai adalah volume produksi air minum PDAM Kabupaten Serang dari Januari 2022 sampai Desember 2024, satuannya ribu m³ per bulan.

prod_air <- c(
  410, 415, 405, 420, 430, 445, 455, 440, 425, 420, 418, 435,
  440, 445, 438, 452, 462, 478, 488, 472, 458, 452, 450, 468,
  470, 476, 468, 483, 494, 510, 521, 504, 489, 483, 480, 499
)

ts_air <- ts(prod_air, start = c(2022, 1), frequency = 12)
ts_air
##      Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 2022 410 415 405 420 430 445 455 440 425 420 418 435
## 2023 440 445 438 452 462 478 488 472 458 452 450 468
## 2024 470 476 468 483 494 510 521 504 489 483 480 499
# bantuan untuk sumbu grafik dan tabel
nama_bln <- month.abb
waktu    <- seq(as.Date("2022-01-01"), by = "month", length.out = length(ts_air))

Dekomposisi Additive

Model additive:

\[Z_t = T_t + S_t + e_t\]

Artinya, nilai data = tren + musiman + residu (sisa).

Soal 1

Buat objek ts dari data di atas, lalu lakukan dekomposisi additive menggunakan decompose().

library(ggplot2)
hasil_aditif <- decompose(ts_air, type = "additive")
plot(hasil_aditif)

Melihat masing-masing komponen:

hasil_aditif$trend
##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 2022       NA       NA       NA       NA       NA       NA 427.7500 430.2500
## 2023 443.7083 446.4167 449.1250 451.8333 454.5000 457.2083 459.8333 462.3750
## 2024 475.4583 478.1667 480.7917 483.3750 485.9167 488.4583       NA       NA
##           Sep      Oct      Nov      Dec
## 2022 432.8750 435.5833 438.2500 440.9583
## 2023 464.9167 467.4583 470.0833 472.7500
## 2024       NA       NA       NA       NA
hasil_aditif$seasonal
##               Jan          Feb          Mar          Apr          May
## 2022  -4.53993056  -1.74826389 -11.91493056  -0.06076389   7.83506944
## 2023  -4.53993056  -1.74826389 -11.91493056  -0.06076389   7.83506944
## 2024  -4.53993056  -1.74826389 -11.91493056  -0.06076389   7.83506944
##               Jun          Jul          Aug          Sep          Oct
## 2022  21.21006944  27.75173611   9.73090278  -7.35243056 -15.47743056
## 2023  21.21006944  27.75173611   9.73090278  -7.35243056 -15.47743056
## 2024  21.21006944  27.75173611   9.73090278  -7.35243056 -15.47743056
##               Nov          Dec
## 2022 -20.12326389  -5.31076389
## 2023 -20.12326389  -5.31076389
## 2024 -20.12326389  -5.31076389
hasil_aditif$random
##              Jan         Feb         Mar         Apr         May         Jun
## 2022          NA          NA          NA          NA          NA          NA
## 2023  0.83159722  0.33159722  0.78993056  0.22743056 -0.33506944 -0.41840278
## 2024 -0.91840278 -0.41840278 -0.87673611 -0.31423611  0.24826389  0.33159722
##              Jul         Aug         Sep         Oct         Nov         Dec
## 2022 -0.50173611  0.01909722 -0.52256944 -0.10590278 -0.12673611 -0.64756944
## 2023  0.41493056 -0.10590278  0.43576389  0.01909722  0.03993056  0.56076389
## 2024          NA          NA          NA          NA          NA          NA

Dekomposisi menghasilkan empat bagian: data asli (observed), tren, musiman, dan residu (random). Pada komponen tren ada nilai NA di 6 bulan pertama dan 6 bulan terakhir (total 12). Ini normal, karena tren dihitung dengan rata-rata bergerak terpusat (2×12-MA) yang butuh data di kiri dan kanan tiap bulan.

Datanya punya tren yang naik, pola musiman yang berulang tiap tahun, dan sisa (residu) yang kecil.

Soal 2

Tampilkan dan gambarkan komponen tren. Apakah produksi air minum menunjukkan tren naik?

df_tren_aditif <- data.frame(
  waktu = waktu,
  nilai_tren = as.numeric(hasil_aditif$trend)
)

ggplot(df_tren_aditif, aes(x = waktu, y = nilai_tren)) +
  geom_line(color = "purple", linewidth = 1) +
  geom_point(color = "purple", size = 2) +
  labs(title = "Tren Produksi Air Minum (Model Additive)",
       x = "Periode", y = "Tren (ribu m³)") +
  scale_x_date(date_breaks = "3 months", date_labels = "%b\n%Y") +
  theme_bw()
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_point()`).

Tren pertama yang bisa dihitung (Juli 2022) sekitar 427,75 ribu m³, dan tren terakhir (Juni 2024) sekitar 488,46 ribu m³.

Garis tren terus naik dari waktu ke waktu, jadi produksi air minum PDAM Kabupaten Serang memang punya tren naik selama periode ini. Naiknya sekitar 60,7 ribu m³ dalam 23 bulan, atau rata-rata sekitar 2,6 ribu m³ per bulan.

Soal 3

Tampilkan 12 indeks musiman. Bulan apa yang cenderung tertinggi dan terendah? Berikan dugaan penjelasannya.

tabel_musim_aditif <- data.frame(
  Nama_Bulan   = nama_bln,
  Nilai_Musiman = as.numeric(hasil_aditif$seasonal[1:12])
)
tabel_musim_aditif
sum(tabel_musim_aditif$Nilai_Musiman)   # harus 0 (syarat model additive)
## [1] 0
ggplot(tabel_musim_aditif,
       aes(x = factor(Nama_Bulan, levels = nama_bln), y = Nilai_Musiman)) +
  geom_col(fill = "purple") +
  geom_hline(yintercept = 0) +
  labs(title = "Pola Musiman Produksi Air Minum (Model Additive)",
       x = "Bulan", y = "Nilai Musiman (ribu m³)") +
  theme_bw()

Bulan Indeks Musiman
Januari -4,54
Februari -1,75
Maret -11,91
April -0,06
Mei 7,84
Juni 21,21
Juli 27,75
Agustus 9,73
September -7,35
Oktober -15,48
November -20,12
Desember -5,31

Jumlah ke-12 indeks sama dengan 0, sesuai syarat model additive.

Indeks positif disini artinya produksi bulan itu di atas tren, indeks negatif artinya di bawah tren.

  • Tertinggi: Juli (+27,75). Pada bulan Juli, produksi biasanya sekitar 27,75 ribu m³ lebih banyak dari tren.
  • Terendah: November (-20,12). Pada bulan November, produksi biasanya sekitar 20,12 ribu m³ lebih sedikit dari tren.

Dugaan: Juni sampai Agustus biasanya musim kemarau, jadi pemakaian air naik dan produksi ikut naik. Sebaliknya, Oktober sampai November mulai masuk musim hujan, jadi kebutuhan air dari PDAM turun.

Soal 4

Periksa komponen residu (ringkasan statistik dan simpangan bakunya). Apakah residu tampak berfluktuasi acak di sekitar nol?

summary(hasil_aditif$random)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
## -0.9184 -0.4184 -0.0434 -0.0434  0.3316  0.8316      12
sd_sisa_aditif <- sd(hasil_aditif$random, na.rm = TRUE)
sd_sisa_aditif
## [1] 0.4862621
df_sisa_aditif <- data.frame(
  waktu = waktu,
  nilai_sisa = as.numeric(hasil_aditif$random)
)

ggplot(df_sisa_aditif, aes(x = waktu, y = nilai_sisa)) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  geom_line(color = "purple", linewidth = 1) +
  geom_point(color = "purple", size = 2) +
  labs(title = "Residu Model Additive",
       x = "Periode", y = "Residu (ribu m³)") +
  theme_bw()
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_point()`).

Rata-rata residu sekitar -0,043 (hampir nol), nilainya berkisar dari -0,92 sampai +0,83, dan simpangan bakunya sekitar 0,4863 ribu m³.

Residunya kecil sekali dibanding level datanya yang sekitar 450 ribu m³, dan naik-turunnya di sekitar nol tanpa pola yang jelas. Jadi tren dan musiman sudah menjelaskan hampir semua pola di data.

Dekomposisi Multiplicative

Model multiplicative:

\[Z_t = T_t \times S_t \times e_t\]

Artinya, nilai data = tren × musiman × residu. Faktor musiman 1 berarti pas di tren, lebih dari 1 berarti di atas tren, dan kurang dari 1 berarti di bawah tren. Residu yang bagus berfluktuasi di sekitar 1 (bukan 0).

Soal 1

Lakukan dekomposisi multiplicative pada data produksi air minum PDAM.

hasil_multi <- decompose(ts_air, type = "multiplicative")
plot(hasil_multi)

Melihat masing-masing komponen:

hasil_multi$trend
##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 2022       NA       NA       NA       NA       NA       NA 427.7500 430.2500
## 2023 443.7083 446.4167 449.1250 451.8333 454.5000 457.2083 459.8333 462.3750
## 2024 475.4583 478.1667 480.7917 483.3750 485.9167 488.4583       NA       NA
##           Sep      Oct      Nov      Dec
## 2022 432.8750 435.5833 438.2500 440.9583
## 2023 464.9167 467.4583 470.0833 472.7500
## 2024       NA       NA       NA       NA
hasil_multi$seasonal
##            Jan       Feb       Mar       Apr       May       Jun       Jul
## 2022 0.9901875 0.9962547 0.9744168 0.9999039 1.0166776 1.0449005 1.0625939
## 2023 0.9901875 0.9962547 0.9744168 0.9999039 1.0166776 1.0449005 1.0625939
## 2024 0.9901875 0.9962547 0.9744168 0.9999039 1.0166776 1.0449005 1.0625939
##            Aug       Sep       Oct       Nov       Dec
## 2022 1.0218486 0.9835709 0.9656814 0.9556379 0.9883262
## 2023 1.0218486 0.9835709 0.9656814 0.9556379 0.9883262
## 2024 1.0218486 0.9835709 0.9656814 0.9556379 0.9883262
hasil_multi$random
##            Jan       Feb       Mar       Apr       May       Jun       Jul
## 2022        NA        NA        NA        NA        NA        NA 1.0010461
## 2023 1.0014693 1.0005740 1.0008342 1.0004650 0.9998269 1.0005500 0.9987391
## 2024 0.9983158 0.9992111 0.9989510 0.9993202 0.9999583 0.9992351        NA
##            Aug       Sep       Oct       Nov       Dec
## 2022 1.0007953 0.9982074 0.9984910 0.9980699 0.9981398
## 2023 0.9989899 1.0015778 1.0012941 1.0017152 1.0016454
## 2024        NA        NA        NA        NA        NA

Dekomposisi multiplicative juga menghasilkan data asli, tren, musiman, dan residu. Bedanya, komponen musiman berbentuk faktor (angka di sekitar 1), bukan selisih.

Pengaruh musiman di model ini berbentuk persentase terhadap tren, bukan jumlah tetap.

Soal 2

Tampilkan dan gambarkan komponen tren dari dekomposisi multiplicative.

df_tren_multi <- data.frame(
  waktu = waktu,
  nilai_tren = as.numeric(hasil_multi$trend)
)

ggplot(df_tren_multi, aes(x = waktu, y = nilai_tren)) +
  geom_line(color = "darkorange", linewidth = 1) +
  geom_point(color = "darkorange", size = 2) +
  labs(title = "Tren Produksi Air Minum (Model Multiplicative)",
       x = "Periode", y = "Tren (ribu m³)") +
  scale_x_date(date_breaks = "3 months", date_labels = "%b\n%Y") +
  theme_bw()
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_point()`).

Tren pertama yang bisa dihitung sekitar 427,75 ribu m³ dan tren terakhir sekitar 488,46 ribu m³. Angkanya sama persis dengan model additive, karena keduanya memakai CMA 2×12 yang sama untuk menghitung tren.

Tren di model multiplicative juga naik, jadi kesimpulannya sama: produksi air minum cenderung meningkat dari waktu ke waktu.

Soal 3

Tampilkan 12 faktor musiman dan identifikasi bulan dengan faktor musiman tertinggi dan terendah.

tabel_musim_multi <- data.frame(
  Nama_Bulan     = nama_bln,
  Faktor_Bulanan = as.numeric(hasil_multi$seasonal[1:12])
)
tabel_musim_multi$Persen_thd_Tren <- round((tabel_musim_multi$Faktor_Bulanan - 1) * 100, 1)
tabel_musim_multi
mean(tabel_musim_multi$Faktor_Bulanan)   # harus 1 (syarat model multiplicative)
## [1] 1
ggplot(tabel_musim_multi,
       aes(x = factor(Nama_Bulan, levels = nama_bln), y = Faktor_Bulanan)) +
  geom_col(fill = "darkorange") +
  geom_hline(yintercept = 1, linetype = "dashed") +
  labs(title = "Faktor Musiman Produksi Air Minum (Model Multiplicative)",
       x = "Bulan", y = "Faktor Musiman") +
  theme_bw()

Bulan Faktor Musiman Terhadap Tren
Januari 0,990 -1,0%
Februari 0,996 -0,4%
Maret 0,974 -2,6%
April 1,000 0,0%
Mei 1,017 +1,7%
Juni 1,045 +4,5%
Juli 1,063 +6,3%
Agustus 1,022 +2,2%
September 0,984 -1,6%
Oktober 0,966 -3,4%
November 0,956 -4,4%
Desember 0,988 -1,2%
  • Tertinggi: Juli (1,063). Produksi Juli sekitar 6,3% di atas tren.
  • Terendah: November (0,956). Produksi November sekitar 4,4% di bawah tren.

Bulan tertinggi dan terendahnya sama dengan model additive, hanya saja di sini dinyatakan dalam persen.

Soal 4

Periksa komponen residu multiplicative dan bandingkan dengan model additive.

Di model additive, residu ada di sekitar 0. Di model multiplicative, residu ada di sekitar 1.

summary(hasil_multi$random)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##  0.9981  0.9989  0.9999  0.9999  1.0009  1.0017      12
sd_sisa_multi <- sd(hasil_multi$random, na.rm = TRUE)
sd_sisa_multi
## [1] 0.001249183
df_sisa_multi <- data.frame(
  waktu = waktu,
  nilai_sisa = as.numeric(hasil_multi$random)
)

ggplot(df_sisa_multi, aes(x = waktu, y = nilai_sisa)) +
  geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
  geom_line(color = "darkorange", linewidth = 1) +
  geom_point(color = "darkorange", size = 2) +
  labs(title = "Residu Model Multiplicative",
       x = "Periode", y = "Residu (rasio)") +
  theme_bw()
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_point()`).

Perbandingan langsung simpangan baku kedua model:

data.frame(
  Model = c("Additive", "Multiplicative"),
  SD_Residu = c(sd_sisa_aditif, sd_sisa_multi)
)

Rata-rata residu sekitar 0,9999 (hampir 1), nilainya berkisar dari 0,9981 sampai 1,0017, dan simpangan bakunya sekitar 0,00125. Sebagai perbandingan, simpangan baku residu additive sekitar 0,4863.

Residu multiplicative naik-turun di sekitar 1 dengan jarak yang sangat kecil, tanpa pola yang jelas. Jadi model multiplicative juga sudah menjelaskan data dengan baik.

Tapi angka 0,4863 dan 0,00125 belum bisa dibandingkan langsung, karena yang satu dalam ribu m³ dan yang satu dalam rasio. Karena itu perlu di samakan dulu skalanya.

Perbandingan Model

Bagian ini untuk memutuskan model mana yang lebih cocok. Ada tiga hal yang dicek: pola grafik, besar residu di skala yang sama, dan pola residunya.

1. Pola visual: ayunan musiman konstan atau membesar?

df_asli <- data.frame(waktu = waktu, volume = as.numeric(ts_air))

ggplot(df_asli, aes(x = waktu, y = volume)) +
  geom_line(color = "purple", linewidth = 1) +
  geom_point(size = 2) +
  labs(title = "Data Asli Produksi Air Minum PDAM Kabupaten Serang",
       x = "Periode", y = "Volume (ribu m³)") +
  scale_x_date(date_breaks = "3 months", date_labels = "%b\n%Y") +
  theme_bw()

Supaya tidak sekadar menebak dari grafik, kita bandingkan bulan puncak (Juli) dan bulan lembah (Maret) di tiap tahun.

tahun_cek <- 2022:2024
nilai_jul <- sapply(0:2, function(i) prod_air[i * 12 + 7])
nilai_mar <- sapply(0:2, function(i) prod_air[i * 12 + 3])

data.frame(Tahun = tahun_cek,
           Juli = nilai_jul,
           Maret = nilai_mar,
           Selisih = nilai_jul - nilai_mar,
           Rasio = round(nilai_jul / nilai_mar, 4))
Tahun Juli Maret Selisih Rasio
2022 455 405 50 1,1235
2023 488 438 50 1,1142
2024 521 468 53 1,1132

Levelnya naik tiap tahun, tapi jarak antara Juli dan Maret hampir sama, yaitu sekitar 50 sampai 53 ribu m³. Rasionya malah sedikit turun. Jadi naik-turun musimannya tidak ikut membesar saat level naik. Ini ciri model additive.

2. Besar residu di skala yang sama

# Cara 1: ubah SD additive jadi skala rasio (dibagi rata-rata tren)
sd_aditif_rasio <- sd_sisa_aditif / mean(hasil_aditif$trend, na.rm = TRUE)

# Cara 2: ubah residu multiplicative ke skala asli (ribu m3)
sisa_multi_asli <- ts_air - hasil_multi$trend * hasil_multi$seasonal
sd_multi_asli   <- sd(sisa_multi_asli, na.rm = TRUE)

data.frame(
  Skala = c("Rasio (relatif terhadap level)", "Asli (ribu m3)"),
  Additive = c(sd_aditif_rasio, sd_sisa_aditif),
  Multiplicative = c(sd_sisa_multi, sd_multi_asli)
)
df_banding <- data.frame(
  waktu = rep(waktu, 2),
  nilai_sisa = c(as.numeric(hasil_aditif$random), as.numeric(sisa_multi_asli)),
  Model = rep(c("Additive", "Multiplicative"), each = length(waktu))
)

ggplot(df_banding, aes(x = waktu, y = nilai_sisa, colour = Model)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_line(linewidth = 0.9) +
  labs(title = "Residu Kedua Model pada Skala Asli (ribu m³)",
       x = "Periode", y = "Residu") +
  theme_bw()
## Warning: Removed 24 rows containing missing values or values outside the scale range
## (`geom_line()`).

Skala Additive Multiplicative
Rasio 0,00106 0,00125
Asli (ribu m³) 0,486 0,561

Setelah skalanya disamakan, residu additive sedikit lebih kecil di kedua skala. Bedanya tipis, tapi konsisten mengarah ke additive.

3. Pola residu

Kedua model punya residu yang naik-turun acak di sekitar nilai idealnya (0 untuk additive, 1 untuk multiplicative). Tidak ada tanda residu yang berubah arah seiring naiknya level, jadi tidak ada bukti bahwa additive “dipaksakan” pada data ini.

Kesimpulan

Produksi air minum PDAM Kabupaten Serang dari Januari 2022 sampai Desember 2024 punya tren naik (tren yang bisa dihitung naik dari sekitar 427,75 ke 488,46 ribu m³) dan pola musiman yang jelas.

  • Additive: indeks musiman tertinggi di Juli (+27,75) dan terendah di November (-20,12). Residu berfluktuasi di sekitar 0 dengan simpangan baku sekitar 0,4863.
  • Multiplicative: faktor musiman tertinggi di Juli (1,063) dan terendah di November (0,956). Residu berfluktuasi di sekitar 1 dengan simpangan baku sekitar 0,00125.

Dari pola grafik (ayunan musiman konstan) dan perbandingan residu di skala yang sama, model additive lebih sesuai untuk data ini. Perlu dicatat bahwa kedua model hasilnya mirip, karena naik turun musimannya kecil dibanding level datanya, jadi selisih kualitasnya tipis. Jadi alasan utama memilih additive adalah pola musimannya yang konstan.