Kelompok 4
library("forecast")
## Warning in register(): Can't find generic `scale_type` in package ggplot2 to
## register S3 method.
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library("graphics")
library("TTR")
library("TSA")
## Registered S3 methods overwritten by 'TSA':
## method from
## fitted.Arima forecast
## plot.Arima forecast
##
## Attaching package: 'TSA'
## The following objects are masked from 'package:stats':
##
## acf, arima
## The following object is masked from 'package:utils':
##
## tar
library("readxl")
Dataset yang digunakan yaitu Data_P2. Data_P2 terdiri dari dua variabel, yaitu period (periode waktu) dan data penjualan (sales). Data dapat dilihat pada tabel di bawah ini.
setwd("C:/Users/Radja Fikri/Documents/Tugas Kuliah/Tugas Kuliah/Semester 6/MPDW")
df2 = read_excel('Data/Data_P2.xlsx')
knitr::kable(head(df2))
| Period | Sales |
|---|---|
| 1 | 10618.1 |
| 2 | 10537.9 |
| 3 | 10209.3 |
| 4 | 10553.0 |
| 5 | 9934.9 |
| 6 | 10534.5 |
str(df2)
## tibble [120 x 2] (S3: tbl_df/tbl/data.frame)
## $ Period: num [1:120] 1 2 3 4 5 6 7 8 9 10 ...
## $ Sales : num [1:120] 10618 10538 10209 10553 9935 ...
dim(df2)
## [1] 120 2
colSums(is.na(df2))
## Period Sales
## 0 0
Statistik deskriptif Data_P2 dapat dilihat pada tabel di bawah ini.
summary(df2)
## Period Sales
## Min. : 1.00 Min. : 9815
## 1st Qu.: 30.75 1st Qu.:10210
## Median : 60.50 Median :10392
## Mean : 60.50 Mean :10379
## 3rd Qu.: 90.25 3rd Qu.:10535
## Max. :120.00 Max. :10827
Pada R, data deret waktu dapat didefinisikan dengan menggunakan syntax ts().
data.ts = ts(df2[,2])
head(data.ts)
## Time Series:
## Start = 1
## End = 6
## Frequency = 1
## Sales
## [1,] 10618.1
## [2,] 10537.9
## [3,] 10209.3
## [4,] 10553.0
## [5,] 9934.9
## [6,] 10534.5
ts.plot(data.ts, xlab="Period",
ylab="Sales", main= "Time Series Plot of Sales")
points(data.ts)
Dari plot tersebut dapat kita lihat bahwa data series ini merupakan data yang stasioner karena tidak terlihat memiliki trend maupun seasonality. Titik-titik data terlihat menyebar secara acak dan terlihat bergerak secara horizontal.
Simple moving average adalah teknik pemulusan data dengan menggunakan beberapa data periode sebelumnya dan mengambil rata-ratanya. Pemulusan data dengan metode ini cocok ketika data yang akan dilakukan pemulusan sudah dalam bentuk stasioner, atau sudah menyebar secara acak tanpa ada seasonality. Pada kasus ini, nilai m, atau rentang data yang digunakan dalam proses ini, akan dicari nilai optimumnya. Nilai m yang optimum dapat diketahui dari beberapa perhitungan seperti MAPE (Mean Absolute Percentage Error), SSE (Sum Square Error), dan MSE (Mean Square Error) terkecil. Semakin kecil ketiga nilai tersebut, maka semakin akurat peramalan yang dihasilkan (Sungkawa dan Megastri 2011).
sma23 = SMA(data.ts,n=23)
forecast23 = c(NA,sma23)
pemulusan23=c(sma23,NA)
error.sma = data.ts-forecast23[1:length(data.ts)]
MAPE23 = mean(abs((error.sma[24:length(data.ts)]/data.ts[24:length(data.ts)])*100))
SSE23 = sum(error.sma[24:length(data.ts)]^2)
MSE23 = mean(error.sma[24:length(data.ts)]^2)
sma24 = SMA(data.ts,n=23)
forecast24 = c(NA,sma24)
pemulusan24=c(sma24,NA)
error.sma = data.ts-forecast24[1:length(data.ts)]
MAPE24 = mean(abs((error.sma[25:length(data.ts)]/data.ts[25:length(data.ts)])*100))
SSE24 = sum(error.sma[25:length(data.ts)]^2)
MSE24 = mean(error.sma[25:length(data.ts)]^2)
sma25 = SMA(data.ts,n=25)
forecast25 = c(NA,sma25)
pemulusan25=c(sma25,NA)
error.sma = data.ts-forecast25[1:length(data.ts)]
MAPE25 = mean(abs((error.sma[26:length(data.ts)]/data.ts[26:length(data.ts)])*100))
SSE25 = sum(error.sma[26:length(data.ts)]^2)
MSE25 = mean(error.sma[26:length(data.ts)]^2)
sma26 = SMA(data.ts,n=26)
forecast26 = c(NA,sma26)
pemulusan26=c(sma26,NA)
error.sma = data.ts-forecast26[1:length(data.ts)]
MAPE26 = mean(abs((error.sma[27:length(data.ts)]/data.ts[27:length(data.ts)])*100))
SSE26 = sum(error.sma[27:length(data.ts)]^2)
MSE26 = mean(error.sma[27:length(data.ts)]^2)
sma27 = SMA(data.ts,n=27)
forecast27 = c(NA,sma27)
pemulusan27=c(sma27,NA)
error.sma = data.ts-forecast27[1:length(data.ts)]
MAPE27 = mean(abs((error.sma[28:length(data.ts)]/data.ts[28:length(data.ts)])*100))
SSE27 = sum(error.sma[28:length(data.ts)]^2)
MSE27 = mean(error.sma[28:length(data.ts)]^2)
baris<- c('m=23','m=24','m=25','m=26','m=27')
akurasi.sma <-cbind("M" = baris, "MAPE"= c(MAPE23, MAPE24, MAPE25, MAPE26, MAPE27), "SSE"=c(SSE23,SSE24,SSE25,SSE26,SSE27), "MSE"=c(MSE23,MSE24,MSE25,MSE26,MSE27))
knitr::kable(akurasi.sma)
| M | MAPE | SSE | MSE |
|---|---|---|---|
| m=23 | 1.67124818777071 | 4424012.11446125 | 45608.3723140334 |
| m=24 | 1.6627142298079 | 4360290.99005671 | 45419.6978130907 |
| m=25 | 1.64995568036271 | 4232360.20289602 | 44551.1600304844 |
| m=26 | 1.65592567938655 | 4202375.65118344 | 44706.12394876 |
| m=27 | 1.66382923999482 | 4184774.64292181 | 44997.5768056109 |
Pada Single Moving Average didapatkan nilai MAPE dan MSE yang memiliki nilai error paling kecil yaitu ketika rentang m = 25.
Plot untuk peramalan dengan rentan m = 25 dapat dilihat pada grafik di bawah ini.
ramalan25 = c(forecast25,rep(forecast25[length(forecast25)],25))
ts.plot(data.ts, xlab="Period",
ylab="Sales", main= "Single Moving Average Dengan Rentang m=25")
points(data.ts)
lines(pemulusan25,col="green",lwd=2)
lines(forecast25,col="red",lwd=2)
legend("topleft",c("data aktual","data pemulusan","data peramalan"), lty=8,
col=c("black","green","red"), cex=0.8)
Hasil peramalan dapat dilihat di bawah ini.
data = cbind(aktual=c(data.ts,rep(NA,25)),pemulusan=c(sma25,rep(NA,25)),ramalan=c(ramalan25))
## Warning in cbind(aktual = c(data.ts, rep(NA, 25)), pemulusan = c(sma25, : number
## of rows of result is not a multiple of vector length (arg 1)
knitr::kable(tail(data,30))
| aktual | pemulusan | ramalan | |
|---|---|---|---|
| [117,] | 10741.6 | 10430.48 | 10405.75 |
| [118,] | 10246.0 | 10421.81 | 10430.48 |
| [119,] | 10354.4 | 10427.76 | 10421.81 |
| [120,] | 10155.4 | 10413.07 | 10427.76 |
| [121,] | NA | NA | 10413.07 |
| [122,] | NA | NA | 10413.07 |
| [123,] | NA | NA | 10413.07 |
| [124,] | NA | NA | 10413.07 |
| [125,] | NA | NA | 10413.07 |
| [126,] | NA | NA | 10413.07 |
| [127,] | NA | NA | 10413.07 |
| [128,] | NA | NA | 10413.07 |
| [129,] | NA | NA | 10413.07 |
| [130,] | NA | NA | 10413.07 |
| [131,] | NA | NA | 10413.07 |
| [132,] | NA | NA | 10413.07 |
| [133,] | NA | NA | 10413.07 |
| [134,] | NA | NA | 10413.07 |
| [135,] | NA | NA | 10413.07 |
| [136,] | NA | NA | 10413.07 |
| [137,] | NA | NA | 10413.07 |
| [138,] | NA | NA | 10413.07 |
| [139,] | NA | NA | 10413.07 |
| [140,] | NA | NA | 10413.07 |
| [141,] | NA | NA | 10413.07 |
| [142,] | NA | NA | 10413.07 |
| [143,] | NA | NA | 10413.07 |
| [144,] | NA | NA | 10413.07 |
| [145,] | NA | NA | 10413.07 |
| [146,] | 10618.1 | NA | 10413.07 |
Prinsip dari double moving average sama dengan pada single moving average, dimana beberapa data pada periode sebelumnya diambil rata-ratanya. Hanya saja, pada double moving average, dilakukan proses single moving average kembali pada data yang sudah dilakukan proses single moving average sebelumnya. Sama seperti sebelumnya, nilai m optimum dicari dengan menggunakan perhitungan MAPE, SSE, dan MSE dengan mencari nilai m yang memberikan nilai terkecil untuk ketiga perhitungan tersebut.
data.sma<-SMA(data.ts, n=24)
dma24 <- SMA(data.sma, n = 24)
At <- 2*data.sma - dma24
Bt <- 2/(24-1)*(data.sma - dma24)
data.dma24<- At+Bt
data.ramal24<- c(NA, data.dma24)
t = 1:5
f = c()
for (i in t) {
f[i] = At[length(At)] + Bt[length(Bt)]*(i)
}
error.dma = data.ts-data.ramal24[1:length(data.ts)]
MAPE24 = mean(abs((error.dma[48:length(data.ts)]/data.ts[48:length(data.ts)])*100))
SSE24 = sum(error.dma[48:length(data.ts)]^2)
MSE24 = mean(error.dma[48:length(data.ts)]^2)
data.sma<-SMA(data.ts, n=25)
dma25 <- SMA(data.sma, n = 25)
At <- 2*data.sma - dma25
Bt <- 2/(25-1)*(data.sma - dma25)
data.dma25<- At+Bt
data.ramal25<- c(NA, data.dma25)
t = 1:5
f = c()
for (i in t) {
f[i] = At[length(At)] + Bt[length(Bt)]*(i)
}
error.dma = data.ts-data.ramal25[1:length(data.ts)]
MAPE25 = mean(abs((error.dma[50:length(data.ts)]/data.ts[50:length(data.ts)])*100))
SSE25 = sum(error.dma[50:length(data.ts)]^2)
MSE25 = mean(error.dma[50:length(data.ts)]^2)
data.sma<-SMA(data.ts, n=26)
dma26 <- SMA(data.sma, n = 26)
At <- 2*data.sma - dma26
Bt <- 2/(26-1)*(data.sma - dma26)
data.dma26<- At+Bt
data.ramal26<- c(NA, data.dma26)
t = 1:5
f = c()
for (i in t) {
f[i] = At[length(At)] + Bt[length(Bt)]*(i)
}
error.dma = data.ts-data.ramal26[1:length(data.ts)]
MAPE26 = mean(abs((error.dma[52:length(data.ts)]/data.ts[52:length(data.ts)])*100))
SSE26 = sum(error.dma[52:length(data.ts)]^2)
MSE26 = mean(error.dma[52:length(data.ts)]^2)
data.sma<-SMA(data.ts, n=27)
dma27 <- SMA(data.sma, n = 27)
At <- 2*data.sma - dma27
Bt <- 2/(27-1)*(data.sma - dma27)
data.dma27<- At+Bt
data.ramal27<- c(NA, data.dma27)
t = 1:5
f = c()
for (i in t) {
f[i] = At[length(At)] + Bt[length(Bt)]*(i)
}
error.dma = data.ts-data.ramal27[1:length(data.ts)]
MAPE27 = mean(abs((error.dma[54:length(data.ts)]/data.ts[54:length(data.ts)])*100))
SSE27 = sum(error.dma[54:length(data.ts)]^2)
MSE27 = mean(error.dma[54:length(data.ts)]^2)
data.sma<-SMA(data.ts, n=28)
dma28 <- SMA(data.sma, n = 28)
At <- 2*data.sma - dma28
Bt <- 2/(28-1)*(data.sma - dma28)
data.dma28<- At+Bt
data.ramal28<- c(NA, data.dma28)
t = 1:5
f = c()
for (i in t) {
f[i] = At[length(At)] + Bt[length(Bt)]*(i)
}
error.dma = data.ts-data.ramal28[1:length(data.ts)]
MAPE28 = mean(abs((error.dma[56:length(data.ts)]/data.ts[56:length(data.ts)])*100))
SSE28 = sum(error.dma[56:length(data.ts)]^2)
MSE28 = mean(error.dma[56:length(data.ts)]^2)
baris<- c('m=24','m=25','m=26','m=27','m=28')
akurasi.dma <-cbind("M" = baris, "MAPE"= c(MAPE24, MAPE25, MAPE26, MAPE27, MAPE28), "SSE"=c(SSE24,SSE25,SSE26,SSE27,SSE28), "MSE"=c(MSE24,MSE25,MSE26,MSE27,MSE28))
knitr::kable(akurasi.dma)
| M | MAPE | SSE | MSE |
|---|---|---|---|
| m=24 | 1.73506500078678 | 3627979.40339164 | 49698.3479916664 |
| m=25 | 1.73437878003934 | 3608649.27616209 | 50826.046143128 |
| m=26 | 1.66590633881641 | 3161325.44135142 | 45816.3107442235 |
| m=27 | 1.70997073175906 | 3176364.07798257 | 47408.4190743668 |
| m=28 | 1.71845450807912 | 3182114.66376946 | 48955.6102118378 |
Pada Double Moving Average didapatkan nilai MAPE dan MSE yang memiliki nilai error paling kecil yaitu ketika rentang m = 26
ramalan26 = c(data.ramal26,rep(data.ramal26[length(data.ramal26)],26))
ts.plot(data.ts, xlab="Period",
ylab="Sales", main= "Double Moving Average Dengan Rentang m=26")
points(data.ts)
lines(dma26,col="green",lwd=2)
lines(data.ramal26,col="red",lwd=2)
legend("topleft",c("data aktual","data pemulusan","data peramalan"), lty=8,
col=c("black","green","red"), cex=0.8)
Hasil ramalan dapat dilihat pada tabel di bawah ini.
data = cbind(aktual=c(data.ts,rep(NA,26)),pemulusan=c(dma26,rep(NA,25)),ramalan=c(ramalan26))
## Warning in cbind(aktual = c(data.ts, rep(NA, 26)), pemulusan = c(dma26, : number
## of rows of result is not a multiple of vector length (arg 1)
knitr::kable(tail(data,30))
| aktual | pemulusan | ramalan | |
|---|---|---|---|
| [118,] | 10246.0 | 10386.35 | 10456.24 |
| [119,] | 10354.4 | 10388.46 | 10463.38 |
| [120,] | 10155.4 | 10390.73 | 10452.43 |
| [121,] | NA | NA | 10445.97 |
| [122,] | NA | NA | 10445.97 |
| [123,] | NA | NA | 10445.97 |
| [124,] | NA | NA | 10445.97 |
| [125,] | NA | NA | 10445.97 |
| [126,] | NA | NA | 10445.97 |
| [127,] | NA | NA | 10445.97 |
| [128,] | NA | NA | 10445.97 |
| [129,] | NA | NA | 10445.97 |
| [130,] | NA | NA | 10445.97 |
| [131,] | NA | NA | 10445.97 |
| [132,] | NA | NA | 10445.97 |
| [133,] | NA | NA | 10445.97 |
| [134,] | NA | NA | 10445.97 |
| [135,] | NA | NA | 10445.97 |
| [136,] | NA | NA | 10445.97 |
| [137,] | NA | NA | 10445.97 |
| [138,] | NA | NA | 10445.97 |
| [139,] | NA | NA | 10445.97 |
| [140,] | NA | NA | 10445.97 |
| [141,] | NA | NA | 10445.97 |
| [142,] | NA | NA | 10445.97 |
| [143,] | NA | NA | 10445.97 |
| [144,] | NA | NA | 10445.97 |
| [145,] | NA | NA | 10445.97 |
| [146,] | NA | NA | 10445.97 |
| [147,] | 10618.1 | NA | 10445.97 |
Dengan metode Single Moving Average, diketahui SSE, MSE, dan MAPE bernilai lebih kecil maka Metode SMA lebih baik digunakan. Selain itu bentuk data series yang tidak memiliki trend sehingga metode SMA lebih cocok digunakan.
Megasari RT, Sungkawa I. 2011. Penerapan ukuran ketepatan nilai ramalan data deret waktu dalam seleksi model peramalan volume penjualan PT. Satriamandiri Citramulia. J ComTech. 2(2) : 636 – 645.