Data berikut merupakan harga gabah kering panen (GKP) di tingkat petani Kabupaten Serang periode Januari 2023 hingga Desember 2024 (dalam satuan Rp/kg):
# Input data bulanan harga GKP (Rp/kg)
gkp_2023 <- c(5200, 5150, 5300, 5400, 5250, 5350, 5450, 5500, 5400, 5550, 5600, 5700)
gkp_2024 <- c(5650, 5700, 5800, 5900, 5750, 5850, 5950, 6000, 5900, 6050, 6150, 6300)
bulan <- c("Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des")
# Tabel data harga GKP
tabel_gkp <- rbind("2023" = format(gkp_2023, big.mark = ".", scientific = FALSE),
"2024" = format(gkp_2024, big.mark = ".", scientific = FALSE))
colnames(tabel_gkp) <- bulan
kable(tabel_gkp, caption = "Tabel 1: Data Harga GKP di Tingkat Petani Kabupaten Serang (Rp/kg)")
| Jan | Feb | Mar | Apr | Mei | Jun | Jul | Agu | Sep | Okt | Nov | Des | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2023 | 5.200 | 5.150 | 5.300 | 5.400 | 5.250 | 5.350 | 5.450 | 5.500 | 5.400 | 5.550 | 5.600 | 5.700 |
| 2024 | 5.650 | 5.700 | 5.800 | 5.900 | 5.750 | 5.850 | 5.950 | 6.000 | 5.900 | 6.050 | 6.150 | 6.300 |
ts dan Plot Runtun WaktuObjek deret waktu (time series) dibuat dengan menggabungkan data tahun 2023 dan 2024, dimulai dari Januari 2023 dengan frekuensi \(12\) (karena data berupa observasi bulanan).
# 1. Membuat objek time series
gkp_ts <- ts(c(gkp_2023, gkp_2024), start = c(2023, 1), frequency = 12)
# Menampilkan ringkasan objek ts
print(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
# 2. Visualisasi Plot Runtun Waktu
plot(gkp_ts,
type = "o",
pch = 19,
col = "#1e40af",
lwd = 2,
ylim = c(5000, 6500),
main = "Runtun Waktu Harga Gabah Kering Panen (GKP) Kabupaten Serang\nPeriode 2023–2024",
xlab = "Bulan dan Tahun",
ylab = "Harga GKP (Rp/kg)",
xaxt = "n")
# Konfigurasi sumbu X per bulan
waktu_label <- c("Jan 23", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des",
"Jan 24", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des")
axis(1, at = seq(2023, 2024 + 11/12, by = 1/12), labels = waktu_label, las = 2, cex.axis = 0.8)
grid(col = "#cbd5e1", lty = "dotted")
# Menambahkan garis tren linear
fit_trend <- lm(gkp_ts ~ time(gkp_ts))
abline(fit_trend, col = "#dc2626", lty = 2, lwd = 2)
# Menambahkan legenda
legend("topleft",
legend = c("Harga Aktual (Rp/kg)", "Garis Tren Linear"),
col = c("#1e40af", "#dc2626"),
pch = c(19, NA),
lty = c(1, 2),
lwd = 2,
bty = "n")
Berdasarkan plot runtun waktu harga GKP di atas, dapat diidentifikasi beberapa karakteristik penting:
Transformasi logaritma natural (\(\ln(Y_t)\)) diaplikasikan pada data deret waktu untuk menstabilkan variansi serta meminimalkan heteroskedastisitas data.
# Melakukan transformasi logaritma natural
log_gkp <- log(gkp_ts)
# Perbandingan statistik deskriptif sebelum dan sesudah transformasi
ringkasan_perbandingan <- data.frame(
Indikator = c("Nilai Minimum", "Kuartil 1 (Q1)", "Median", "Rata-Rata (Mean)", "Kuartil 3 (Q3)", "Nilai Maksimum", "Ragam (Variansi)"),
Data_Asli_Rp = c(min(gkp_ts), quantile(gkp_ts, 0.25), median(gkp_ts), mean(gkp_ts), quantile(gkp_ts, 0.75), max(gkp_ts), var(gkp_ts)),
Data_Logaritma = c(min(log_gkp), quantile(log_gkp, 0.25), median(log_gkp), mean(log_gkp), quantile(log_gkp, 0.75), max(log_gkp), var(log_gkp))
)
ringkasan_perbandingan$Data_Asli_Rp <- format(round(ringkasan_perbandingan$Data_Asli_Rp, 2), big.mark = ".")
ringkasan_perbandingan$Data_Logaritma <- round(ringkasan_perbandingan$Data_Logaritma, 5)
kable(ringkasan_perbandingan, caption = "Tabel 2: Perbandingan Statistik Deskriptif Data Asli vs Data Hasil Transformasi Logaritma")
| Indikator | Data_Asli_Rp | Data_Logaritma |
|---|---|---|
| Nilai Minimum | 5.150.00 | 8.54675 |
| Kuartil 1 (Q1) | 5.400.00 | 8.59415 |
| Median | 5.675.00 | 8.64382 |
| Rata-Rata (Mean) | 5.660.42 | 8.63978 |
| Kuartil 3 (Q3) | 5.900.00 | 8.68271 |
| Nilai Maksimum | 6.300.00 | 8.74830 |
| Ragam (Variansi) | 98.691.12 | 0.00307 |
# Membuat plot perbandingan (2 Panel Atas - Bawah)
par(mfrow = c(2, 1), mar = c(4, 4.5, 2.5, 1.5))
# Plot 1: Data Asli
plot(gkp_ts,
type = "o",
pch = 19,
col = "#1e40af",
lwd = 2,
main = "1. Data Asli Harga GKP Kabupaten Serang (Rp/kg)",
xlab = "",
ylab = "Harga (Rp/kg)",
xaxt = "n")
axis(1, at = seq(2023, 2024 + 11/12, by = 1/12), labels = waktu_label, las = 2, cex.axis = 0.75)
grid(col = "#cbd5e1", lty = "dotted")
abline(lm(gkp_ts ~ time(gkp_ts)), col = "#dc2626", lty = 2, lwd = 1.5)
# Plot 2: Data Transformasi Logaritma
plot(log_gkp,
type = "o",
pch = 17,
col = "#047857",
lwd = 2,
main = "2. Data Hasil Transformasi Logaritma: ln(Harga GKP)",
xlab = "Bulan dan Tahun",
ylab = "ln(Harga GKP)",
xaxt = "n")
axis(1, at = seq(2023, 2024 + 11/12, by = 1/12), labels = waktu_label, las = 2, cex.axis = 0.75)
grid(col = "#cbd5e1", lty = "dotted")
abline(lm(log_gkp ~ time(log_gkp)), col = "#dc2626", lty = 2, lwd = 1.5)
# Reset parameter grafik
par(mfrow = c(1, 1))
Differencing tingkat pertama (\(d = 1\)) didefinisikan secara matematis sebagai selisih antara nilai pada waktu \(t\) dengan nilai satu periode sebelumnya (\(t-1\)):
\[\nabla \ln(Y_t) = \ln(Y_t) - \ln(Y_{t-1})\]
Pada data deret waktu yang telah ditransformasi logaritma, nilai \(\nabla \ln(Y_t)\) ini merepresentasikan perkiraan laju pertumbuhan bulanan (monthly proportional change / growth rate).
# Melakukan differencing tingkat pertama (d = 1)
diff_log_gkp <- diff(log_gkp, lag = 1, differences = 1)
# Menampilkan ringkasan deret differencing
print(diff_log_gkp)
## Jan Feb Mar Apr May
## 2023 -0.009661911 0.028710106 0.018692133 -0.028170877
## 2024 -0.008810630 0.008810630 0.017391743 0.017094433 -0.025752496
## Jun Jul Aug Sep Oct
## 2023 0.018868484 0.018519048 0.009132484 -0.018349139 0.027398974
## 2024 0.017241806 0.016949558 0.008368250 -0.016807118 0.025105921
## Nov Dec
## 2023 0.008968670 0.017699577
## 2024 0.016393810 0.024097552
# Visualisasi Plot Deret Hasil Diferensiasi
plot(diff_log_gkp,
type = "o",
pch = 19,
col = "#b45309",
lwd = 2,
main = "Differencing Tingkat Pertama Data Logaritma Harga GKP\n[ ln(Y_t) - ln(Y_{t-1}) ]",
xlab = "Bulan dan Tahun",
ylab = "Diferensiasi ln(Harga)",
xaxt = "n")
# Label sumbu X untuk 23 observasi hasil differencing
waktu_diff_label <- waktu_label[-1]
axis(1, at = seq(2023 + 1/12, 2024 + 11/12, by = 1/12), labels = waktu_diff_label, las = 2, cex.axis = 0.75)
grid(col = "#cbd5e1", lty = "dotted")
# Menambahkan garis horizontal nol (acuan keseimbangan)
abline(h = 0, col = "#475569", lty = 2, lwd = 1.5)
# Menambahkan garis rata-rata deret diferensiasi
rata_diff <- mean(diff_log_gkp)
abline(h = rata_diff, col = "#2563eb", lty = 3, lwd = 2)
# Garis regresi tren pada data hasil diferensiasi
fit_diff_trend <- lm(diff_log_gkp ~ time(diff_log_gkp))
abline(fit_diff_trend, col = "#dc2626", lty = 1, lwd = 1.8)
# Legenda
legend("topleft",
legend = c("Deret Diferensiasi", "Garis Nol (y = 0)",
paste0("Rata-Rata Diferensiasi (", round(rata_diff, 4), ")"),
"Tren Linier Hasil Diferensiasi"),
col = c("#b45309", "#475569", "#2563eb", "#dc2626"),
pch = c(19, NA, NA, NA),
lty = c(1, 2, 3, 1),
lwd = c(2, 1.5, 2, 1.8),
bty = "n", cex = 0.85)
JAWABAN: YA, TREN NAIK JANGKA PANJANG SUDAH BERHASIL HILANG.
Data dipisahkan menjadi: - Data Latih (Training Set): 21 observasi pertama, yaitu Januari 2023 s.d. September 2024. - Data Uji (Testing Set): 3 observasi terakhir, yaitu Oktober 2024, November 2024, dan Desember 2024.
# Pembagian data latih (21 observasi) dan data uji (3 observasi)
data_latih <- window(gkp_ts, end = c(2024, 9))
data_uji <- window(gkp_ts, start = c(2024, 10))
cat("Jumlah observasi data latih :", length(data_latih), "bulan (Jan 2023 - Sep 2024)\n")
## Jumlah observasi data latih : 21 bulan (Jan 2023 - Sep 2024)
cat("Jumlah observasi data uji :", length(data_uji), "bulan (Okt 2024 - Des 2024)\n")
## Jumlah observasi data uji : 3 bulan (Okt 2024 - Des 2024)
Metode peramalan naif sederhana (Random Walk Model) menetapkan nilai ramalan untuk seluruh horizon ke depan (\(h\)) sama persis dengan nilai observasi aktual terakhir dari data latih (\(Y_T\)):
\[\hat{Y}_{T+h} = Y_T, \quad \text{untuk } h = 1, 2, 3\]
Karena observasi ke-21 (September 2024) bernilai Rp5.900/kg, maka nilai ramalan naif untuk 3 bulan berikutnya adalah: - Oktober 2024: Rp5.900/kg - November 2024: Rp5.900/kg - Desember 2024: Rp5.900/kg
# Menghitung ramalan naif untuk horizon 3 bulan ke depan
ramalan_naif <- naive(data_latih, h = 3)
print(ramalan_naif)
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Oct 2024 5900 5770.253 6029.747 5701.569 6098.431
## Nov 2024 5900 5716.510 6083.490 5619.376 6180.624
## Dec 2024 5900 5675.271 6124.729 5556.307 6243.693
Rumus evaluasi kesalahan peramalan dengan \(n = 3\) periode pengujian:
Berikut adalah rincian perhitungan per periode uji:
# Vektor nilai aktual dan hasil ramalan
y_aktual <- as.numeric(data_uji)
y_ramalan <- as.numeric(ramalan_naif$mean)
periode_uji <- c("Oktober 2024", "November 2024", "Desember 2024")
# Perhitungan komponen error
error_e <- y_aktual - y_ramalan
abs_error <- abs(error_e)
sq_error <- error_e^2
pct_abs_error <- (abs_error / y_aktual) * 100
# Tabel rincian perhitungan per bulan
tabel_rincian <- data.frame(
Bulan = periode_uji,
Aktual_Yt = format(y_aktual, big.mark = "."),
Ramalan_Yhat = format(y_ramalan, big.mark = "."),
Error_et = ifelse(error_e >= 0, paste0("+", error_e), as.character(error_e)),
Abs_Error = abs_error,
Sq_Error = format(sq_error, big.mark = "."),
APE_Persen = paste0(round(pct_abs_error, 3), " %")
)
kable(tabel_rincian, align = "c",
caption = "Tabel 3: Rincian Perhitungan Galat Ramalan Naif per Bulan Pengujian")
| Bulan | Aktual_Yt | Ramalan_Yhat | Error_et | Abs_Error | Sq_Error | APE_Persen |
|---|---|---|---|---|---|---|
| Oktober 2024 | 6.050 | 5.900 | +150 | 150 | 22.500 | 2.479 % |
| November 2024 | 6.150 | 5.900 | +250 | 250 | 62.500 | 4.065 % |
| Desember 2024 | 6.300 | 5.900 | +400 | 400 | 160.000 | 6.349 % |
# Menghitung metrik ringkasan
n_uji <- length(y_aktual)
me_val <- sum(error_e) / n_uji
mae_val <- sum(abs_error) / n_uji
mse_val <- sum(sq_error) / n_uji
rmse_val <- sqrt(mse_val)
mape_val <- sum(pct_abs_error) / n_uji
# Tabel hasil evaluasi akurasi
tabel_metrik <- data.frame(
Metrik_Evaluasi = c("Mean Error (ME)",
"Mean Absolute Error (MAE)",
"Mean Squared Error (MSE)",
"Root Mean Squared Error (RMSE)",
"Mean Absolute Percentage Error (MAPE)"),
Formula = c("mean(e_t)",
"mean(|e_t|)",
"mean(e_t^2)",
"sqrt(mean(e_t^2))",
"mean(|e_t / Y_t|) * 100%"),
Nilai_Hitung = c(round(me_val, 4),
round(mae_val, 4),
round(mse_val, 4),
round(rmse_val, 4),
paste0(round(mape_val, 4), " %")),
Satuan = c("Rp/kg", "Rp/kg", "(Rp/kg)^2", "Rp/kg", "%")
)
kable(tabel_metrik, align = c("l", "l", "r", "l"),
caption = "Tabel 4: Ringkasan Nilai Metrik Evaluasi Akurasi Ramalan Naif")
| Metrik_Evaluasi | Formula | Nilai_Hitung | Satuan |
|---|---|---|---|
| Mean Error (ME) | mean(e_t) | 266.6667 | Rp/kg |
| Mean Absolute Error (MAE) | mean(|e_t|) | 266.6667 | Rp/kg |
| Mean Squared Error (MSE) | mean(e_t^2) | 81666.6667 | (Rp/kg)^2 |
| Root Mean Squared Error (RMSE) | sqrt(mean(e_t^2)) | 285.7738 | Rp/kg |
| Mean Absolute Percentage Error (MAPE) | mean(|e_t / Y_t|) * 100% | 4.2979 % | % |
Sebagai validasi, berikut verifikasi otomatis menggunakan fungsi
accuracy() dari package forecast:
# Validasi menggunakan fungsi accuracy()
eval_accuracy <- accuracy(ramalan_naif, data_uji)
kable(round(eval_accuracy, 4), caption = "Tabel 5: Verifikasi Output accuracy() Package forecast")
| ME | RMSE | MAE | MPE | MAPE | MASE | ACF1 | Theil’s U | |
|---|---|---|---|---|---|---|---|---|
| Training set | 35.0000 | 101.2423 | 95.0000 | 0.6148 | 1.7017 | 0.1900 | -0.3240 | NA |
| Test set | 266.6667 | 285.7738 | 266.6667 | 4.2979 | 4.2979 | 0.5333 | -0.0088 | 2.6154 |
# Visualisasi hasil peramalan naif vs data aktual
plot(ramalan_naif,
main = "Peramalan Naif Harga Gabah Kering Panen (GKP) Kabupaten Serang\n(Horizon 3 Bulan: Oktober–Desember 2024)",
xlab = "Bulan dan Tahun",
ylab = "Harga GKP (Rp/kg)",
ylim = c(5000, 6600),
col = "#1e40af",
lwd = 2,
xaxt = "n")
# Menambahkan titik aktual data latih
points(time(data_latih), data_latih, pch = 19, col = "#1e40af", cex = 0.8)
# Menambahkan data aktual uji (garis dan titik merah)
lines(data_uji, col = "#dc2626", lwd = 2.5, type = "o", pch = 17)
# Konfigurasi sumbu X
axis(1, at = seq(2023, 2024 + 11/12, by = 1/12), labels = waktu_label, las = 2, cex.axis = 0.75)
grid(col = "#cbd5e1", lty = "dotted")
# Menambahkan garis pemisah data latih dan data uji
abline(v = 2024 + 8.5/12, col = "#64748b", lty = 2, lwd = 1.5)
text(2024 + 8.5/12, 5100, "Batas Data Latih / Uji", pos = 2, cex = 0.75, col = "#64748b")
# Legenda
legend("topleft",
legend = c("Data Latih (Aktual)", "Data Uji (Aktual)", "Ramalan Naif",
"Interval Prediksi 80%", "Interval Prediksi 95%"),
col = c("#1e40af", "#dc2626", "#0284c7", "#bfdbfe", "#e2e8f0"),
pch = c(19, 17, NA, 15, 15),
lty = c(1, 1, 1, NA, NA),
lwd = c(2, 2.5, 2, NA, NA),
pt.cex = c(0.8, 1, NA, 1.5, 1.5),
bty = "n", cex = 0.8)