Analisis Deret Waktu: Transformasi, Differencing, dan Metrik Evaluasi Harga Gabah Kering Panen (GKP) Kabupaten Serang

Gambaran Umum Data dan Analisis yang Dipakai

Data yang digunakan adalah harga gabah kering panen (GKP) di tingkat petani Kabupaten Serang periode Januari 2023 sampai Desember 2024 dalam satuan Rp/kg, dengan total 24 observasi bulanan. Analisis dimulai dengan membuat objek ts dan plot runtun waktu untuk melihat pola data, kemudian transformasi logaritma untuk menstabilkan variansi, dan differencing tingkat pertama pada data hasil transformasi untuk menghilangkan tren agar data stasioner dalam mean. Tahap terakhir adalah evaluasi ramalan naif, dengan 21 observasi pertama sebagai data latih dan 3 observasi terakhir sebagai data uji, yang hasilnya diukur menggunakan ME, MAE, MSE, RMSE, dan MAPE.


1. Membuat Objek ts dan Plot Runtun Waktu

Input data dan membuat objek ts

# Data harga GKP tingkat petani Kab. Serang (Rp/kg), Jan 2023 - Des 2024
gkp <- c(5200, 5150, 5300, 5400, 5250, 5350, 5450, 5500, 5400, 5550, 5600, 5700,  # 2023
         5650, 5700, 5800, 5900, 5750, 5850, 5950, 6000, 5900, 6050, 6150, 6300)  # 2024

# Ubah menjadi objek time series bulanan yang dimulai Januari 2023
gkp_ts <- ts(gkp, start = c(2023, 1), frequency = 12)
gkp_ts
##       Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
## 2023 5200 5150 5300 5400 5250 5350 5450 5500 5400 5550 5600 5700
## 2024 5650 5700 5800 5900 5750 5850 5950 6000 5900 6050 6150 6300

Plot runtun waktu

# Label 
nama_bulan <- c("Jan", "Feb", "Mar", "Apr", "Mei", "Jun",
                "Jul", "Agu", "Sep", "Okt", "Nov", "Des")
label_x <- paste(rep(nama_bulan, 2), rep(c("23", "24"), each = 12), sep = "-")

# Plot runtun waktu
plot(gkp_ts, type = "o", pch = 16, col = "#1f3a93", lwd = 2,
     main = "Harga GKP di Tingkat Petani Kab. Serang",
     xlab = "Waktu", ylab = "Harga (Rp/kg)",
     xaxt = "n")                                   
axis(1, at = time(gkp_ts), labels = label_x,
     cex.axis = 0.7, las = 2)                      
grid()

Untuk melihat pola secara lebih jelas, berikut ringkasan per tahun:

gkp_2023 <- window(gkp_ts, end   = c(2023, 12))
gkp_2024 <- window(gkp_ts, start = c(2024, 1))

ringkas <- data.frame(
  Tahun         = c(2023, 2024),
  Rata_rata     = c(mean(gkp_2023), mean(gkp_2024)),
  Simpangan_Baku = c(sd(gkp_2023), sd(gkp_2024))
)
knitr::kable(ringkas, digits = 1, caption = "Rata-rata dan simpangan baku harga GKP per tahun")
Rata-rata dan simpangan baku harga GKP per tahun
Tahun Rata_rata Simpangan_Baku
2023 5404.2 165.8
2024 5916.7 188.7

Interpretasi:

Plot memperlihatkan harga GKP cenderung naik dari waktu ke waktu. Harga dimulai dari sekitar Rp5200/kg pada Januari 2023 dan mencapai Rp 6300/kg pada Desember 2024. Rata-rata harga tahun 2023 adalah sekitar Rp5404.2, lalu naik menjadi sekitar Rp5916.7 pada 2024.

Artinya, rata-rata data berubah dari waktu ke waktu (ada tren naik). Ini melanggar syarat stasioneritas dalam mean, sehingga data asli belum stasioner. Selain tren, ada naik-turun kecil setiap beberapa bulan (misalnya harga turun sedikit pada Februari, Mei, dan September), tetapi arah besarnya tetap naik.


2. Transformasi Logaritma

Transformasi log natural

Rumus yang dipakai: \(W_t = \ln(Z_t)\) (syarat: \(Z_t\) harus positif, dan semua harga GKP memang positif).

log_gkp <- log(gkp_ts)
log_gkp
##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 2023 8.556414 8.546752 8.575462 8.594154 8.565983 8.584852 8.603371 8.612503
## 2024 8.639411 8.648221 8.665613 8.682708 8.656955 8.674197 8.691146 8.699515
##           Sep      Oct      Nov      Dec
## 2023 8.594154 8.621553 8.630522 8.648221
## 2024 8.682708 8.707814 8.724207 8.748305

Perbandingan plot data asli dan hasil transformasi

# Dua plot berdampingan: data asli vs data log
par(mfrow = c(1, 2), mar = c(6, 4, 4, 1))

plot(gkp_ts, type = "o", pch = 16, col = "#1f3a93", lwd = 2,
     main = "Data Asli (Rp/kg)", xlab = "Waktu", ylab = "Harga",
     xaxt = "n")
axis(1, at = time(gkp_ts), labels = label_x, cex.axis = 0.6, las = 2)
grid()

plot(log_gkp, type = "o", pch = 16, col = "#e6a700", lwd = 2,
     main = "Log(Data)", xlab = "Waktu", ylab = "ln(Harga)",
     xaxt = "n")
axis(1, at = time(log_gkp), labels = label_x, cex.axis = 0.6, las = 2)
grid()

par(mfrow = c(1, 1), mar = c(5, 4, 4, 2)) 

Interpretasi:

Dari Plot diatas dapat diinterpretasikan dalam beberapa poin berikut.

  • Bentuk plot data log hampir sama dengan data asli: sama-sama naik dan naik-turunnya juga mirip. Ini wajar, karena log hanya mengubah skala (dari Rupiah ke skala logaritma), bukan menghilangkan tren.
  • Setelah dilog, sebaran tiap tahun juga tetap mirip. Jadi pada data GKP ini, transformasi log tidak memberi perubahan besar karena variansinya memang sudah relatif stabil.
  • Tetap saja, log berguna karena mengubah perubahan persentase menjadi perubahan aditif, sehingga nanti hasil differencing-nya bisa dibaca sebagai laju pertumbuhan (%) per bulan.

3. Differencing Tingkat Pertama pada Data Log

Differencing

Rumus: \(W_t = \ln(Z_t) - \ln(Z_{t-1}) = \ln\left(\frac{Z_t}{Z_{t-1}}\right)\), yang mendekati laju pertumbuhan harga dari satu bulan ke bulan berikutnya.

diff_log_gkp <- diff(log_gkp)
round(diff_log_gkp, 4)
##          Jan     Feb     Mar     Apr     May     Jun     Jul     Aug     Sep
## 2023         -0.0097  0.0287  0.0187 -0.0282  0.0189  0.0185  0.0091 -0.0183
## 2024 -0.0088  0.0088  0.0174  0.0171 -0.0258  0.0172  0.0169  0.0084 -0.0168
##          Oct     Nov     Dec
## 2023  0.0274  0.0090  0.0177
## 2024  0.0251  0.0164  0.0241
ringkasan_diff <- data.frame(
  Statistik = c("Jumlah data", "Rata-rata", "Simpangan baku", "Minimum", "Maksimum"),
  Nilai = c(length(diff_log_gkp), mean(diff_log_gkp), sd(diff_log_gkp),
            min(diff_log_gkp), max(diff_log_gkp))
)
knitr::kable(ringkasan_diff, digits = 4, caption = "Ringkasan data hasil log lalu differencing")
Ringkasan data hasil log lalu differencing
Statistik Nilai
Jumlah data 23.0000
Rata-rata 0.0083
Simpangan baku 0.0173
Minimum -0.0282
Maksimum 0.0287

Plot hasil differencing

label_diff <- label_x[-1]   # data hasil differencing mulai Feb-23 (23 titik)
par(mar = c(6, 4, 4, 2))
plot(diff_log_gkp, type = "o", pch = 16, col = "#7b2d3b", lwd = 2,
     main = "Differencing Log(Harga GKP)",
     xlab = "Waktu", ylab = "Selisih ln(Harga)",
     xaxt = "n")
axis(1, at = time(diff_log_gkp), labels = label_diff, cex.axis = 0.7, las = 2)
abline(h = 0, col = "grey40", lty = 2)                        # garis nol
abline(h = mean(diff_log_gkp), col = "red", lty = 3, lwd = 2) # garis rata-rata
legend("topleft", legend = c("Nol", "Rata-rata"),
       col = c("grey40", "red"), lty = c(2, 3), lwd = c(1, 2), bty = "n")
grid()

par(mar = c(5, 4, 4, 2))

Interpretasi:

Pada data asli maupun data log, harga GKP terlihat naik terus dari awal hingga akhir periode, tanda adanya tren. Setelah dilakukan differencing tingkat pertama, nilainya tidak lagi menanjak, melainkan naik-turun di sekitar garis rata-rata, yaitu 0.0083 atau sekitar 0.83% per bulan, dengan rentang nilai dari -0.0282 sampai 0.0287 dan simpangan baku 0.0173. Nilai positif berarti harga naik dibanding bulan sebelumnya, sedangkan nilai negatif (misalnya pada bulan Mei dan September) berarti harga turun. Karena hasil differencing tidak menunjukkan pola naik atau turun yang berlanjut dan hanya bergerak di sekitar satu nilai rata-rata, maka tren sudah hilang dan data sudah stasioner dalam mean, sehingga cukup differencing satu kali (d = 1).


4. Ramalan Naif dan Metrik Evaluasi

Pembagian data latih dan data uji

Data dibagi menjadi dua bagian yaitu data latih dan data uji dengan 21 observasi pertama (Jan 2023 - Sep 2024) sebagai data latih dan 3 observasi terakhir (Okt - Des 2024) sebagai data uji.

train <- head(gkp, 21)
test  <- tail(gkp, 3)

cat("Data latih (21 observasi):\n"); print(train)
## Data latih (21 observasi):
##  [1] 5200 5150 5300 5400 5250 5350 5450 5500 5400 5550 5600 5700 5650 5700 5800
## [16] 5900 5750 5850 5950 6000 5900
cat("\nData uji (3 observasi, Okt-Des 2024):\n"); print(test)
## 
## Data uji (3 observasi, Okt-Des 2024):
## [1] 6050 6150 6300

Ramalan naif

Ramalan naif memakai nilai observasi terakhir data latih sebagai ramalan untuk semua periode ke depan: \(\hat{Z}_{n+h} = Z_n\).

naive_forecast <- rep(tail(train, 1), 3)

hasil <- data.frame(
  Bulan   = c("Okt 2024", "Nov 2024", "Des 2024"),
  Aktual  = test,
  Ramalan = naive_forecast,
  Galat   = test - naive_forecast
)
knitr::kable(hasil, caption = "Perbandingan nilai aktual dan ramalan naif")
Perbandingan nilai aktual dan ramalan naif
Bulan Aktual Ramalan Galat
Okt 2024 6050 5900 150
Nov 2024 6150 5900 250
Des 2024 6300 5900 400
plot(1:24, gkp, type = "o", pch = 16, col = "#1f3a93", lwd = 2,
     xaxt = "n", xlab = "Waktu", ylab = "Harga (Rp/kg)",
     main = "Ramalan Naif vs Data Aktual")
axis(1, at = c(1, 6, 12, 18, 24),
     labels = c("Jan 2023", "Jun 2023", "Des 2023", "Jun 2024", "Des 2024"))
lines(22:24, naive_forecast, type = "o", pch = 17, col = "red", lwd = 2)
abline(v = 21.5, lty = 2, col = "grey40")
legend("topleft", legend = c("Aktual", "Ramalan naif", "Batas latih | uji"),
       col = c("#1f3a93", "red", "grey40"), lty = c(1, 1, 2), pch = c(16, 17, NA), bty = "n")
grid()

Perhitungan ME, MAE, MSE, RMSE, dan MAPE

Galat: \(e_i = Z_i - \hat{Z}_i\).

error <- test - naive_forecast

ME   <- mean(error)
MAE  <- mean(abs(error))
MSE  <- mean(error^2)
RMSE <- sqrt(MSE)
MAPE <- mean(abs(error / test)) * 100

metrik <- data.frame(
  Metrik = c("ME", "MAE", "MSE", "RMSE", "MAPE (%)"),
  Nilai  = c(ME, MAE, MSE, RMSE, MAPE)
)
knitr::kable(metrik, digits = 2, caption = "Hasil evaluasi ramalan naif (data uji: Okt-Des 2024)")
Hasil evaluasi ramalan naif (data uji: Okt-Des 2024)
Metrik Nilai
ME 266.67
MAE 266.67
MSE 81666.67
RMSE 285.77
MAPE (%) 4.30

Interpretasi:

Ramalan naif menebak harga tiga bulan ke depan sama persis dengan harga bulan terakhir data latih, yaitu Rp 5900 per kg. Padahal harga aktual terus naik menjadi Rp 6050, Rp 6150, dan Rp 6300, sehingga galatnya positif semua dan makin besar pada bulan yang makin jauh (150, 250, 400). Nilai ME sebesar 266.7 bernilai positif, artinya ramalan naif cenderung terlalu rendah (under-forecast), yang wajar karena harga sedang naik sementara ramalan naif hanya “diam” di satu angka. Nilai MAE sebesar 266.7 berarti rata-rata ramalan meleset sekitar Rp267 per kg, dan nilainya sama dengan ME karena semua galat berarah sama sehingga tidak ada yang saling menghapus. Nilai MSE sebesar 81.666,7 tampak besar karena satuannya Rupiah kuadrat, sehingga lebih mudah dibaca lewat RMSE sebesar 285.8, yang berarti rata-rata kesalahan ramalan sekitar Rp286 per kg. RMSE sedikit lebih besar daripada MAE karena ada galat yang lebih besar pada bulan Desember (Rp400) dan RMSE memberi hukuman lebih berat pada galat besar. Terakhir, MAPE sebesar 4.3% berarti ramalan rata-rata meleset sekitar 4.3% dari harga sebenarnya. Untuk ramalan yang sangat sederhana, angka ini tergolong cukup baik karena masih di bawah 10%, dan dapat dijadikan patokan (baseline) untuk model peramalan yang lebih canggih.


Kesimpulan

Data harga GKP di tingkat petani Kabupaten Serang periode Januari 2023 sampai Desember 2024 berhasil dibentuk menjadi objek ts bulanan dan menunjukkan tren naik, sehingga belum stasioner dalam mean. Transformasi logaritma hanya mengubah skala data tanpa mengubah pola secara berarti, karena fluktuasi harga dari tahun ke tahun sudah relatif stabil sehingga variansinya tidak melebar. Differencing tingkat pertama pada data log berhasil menghilangkan tren, ditandai dengan nilai yang berfluktuasi di sekitar rata-rata kenaikan sekitar 0.83% per bulan, sehingga data sudah stasioner dalam mean dan cukup didifferencing satu kali. Pada evaluasi ramalan naif untuk Oktober sampai Desember 2024, diperoleh ME sebesar 266.7, MAE sebesar 266.7, MSE sebesar 8.16667^{4}, RMSE sebesar 285.8, dan MAPE sebesar 4.3%, yang menunjukkan ramalan cenderung terlalu rendah karena harga GKP terus naik, namun tingkat kesalahannya masih tergolong kecil sebagai patokan awal.