Diketahui terdapat data penjualan produk-produk sebuah Toko selama tahun 2021. Total terdapat lebih dari seribu produk yang dijual. Penjualan dicatat secara harian, namun untuk kepentingan peramalan (karena terdapat beberapa catatan harian yang tidak terdapat penjualan) data diagregasi dalam bentuk pekanan. Akan dilakukan peramalan terhadap salah satu dari produk yang dijual. Produk yang akan dijadikan sampel objek peramalan bernama RECTIFIED W 63801R KW 1. Pemilihan produk ini didasarkan pada volume penjualan terbanyak selama tahun 2021.
A. Library, Data, dan Langkah Kerja
pacman::p_load(tseries, forecast, TSA, xts, dygraphs, tidyverse, lubridate, ggplot2, dplyr, formattable, DiagrammeR, psd, readr, knitr, kableExtra, purrr, webshot, FitAR, TSstudio, glue, plotly, ggplot2, ggbreak) # Package loudout for Timeseries
## package 'glue' successfully unpacked and MD5 sums checked
## package 'DiagrammeR' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Client\AppData\Local\Temp\RtmpkXzamm\downloaded_packages
library(hrbrthemes)
library(viridis)
library(gapminder)
# data yang digunakan
data <- read_csv("rawdata.csv", col_types = cols(date = col_date(format = "%m/%d/%Y")))
data %>% kbl(booktabs = T) %>%
kable_styling(latex_options = c("striped", "HOLD_position"))
| date | qty | month |
|---|---|---|
| 2021-01-04 | 200 | 1 |
| 2021-01-11 | 265 | 1 |
| 2021-01-18 | 55 | 1 |
| 2021-01-25 | 447 | 1 |
| 2021-02-01 | 106 | 2 |
| 2021-02-08 | 72 | 2 |
| 2021-02-15 | 171 | 2 |
| 2021-02-22 | 360 | 2 |
| 2021-03-01 | 111 | 3 |
| 2021-03-08 | 393 | 3 |
| 2021-03-15 | 217 | 3 |
| 2021-03-22 | 333 | 3 |
| 2021-03-29 | 165 | 3 |
| 2021-04-05 | 134 | 4 |
| 2021-04-12 | 173 | 4 |
| 2021-04-19 | 482 | 4 |
| 2021-04-26 | 57 | 4 |
| 2021-05-03 | 138 | 5 |
| 2021-05-10 | 0 | 5 |
| 2021-05-17 | 204 | 5 |
| 2021-05-24 | 125 | 5 |
| 2021-05-31 | 108 | 5 |
| 2021-06-07 | 77 | 6 |
| 2021-06-14 | 152 | 6 |
| 2021-06-21 | 59 | 6 |
| 2021-06-28 | 92 | 6 |
| 2021-07-05 | 126 | 7 |
| 2021-07-12 | 354 | 7 |
| 2021-07-19 | 92 | 7 |
| 2021-07-26 | 235 | 7 |
| 2021-08-02 | 154 | 8 |
| 2021-08-09 | 305 | 8 |
| 2021-08-16 | 423 | 8 |
| 2021-08-23 | 199 | 8 |
| 2021-08-30 | 178 | 8 |
| 2021-09-06 | 283 | 9 |
| 2021-09-13 | 165 | 9 |
| 2021-09-20 | 163 | 9 |
| 2021-09-27 | 346 | 9 |
| 2021-10-04 | 286 | 10 |
| 2021-10-11 | 568 | 10 |
| 2021-10-18 | 542 | 10 |
| 2021-10-25 | 536 | 10 |
| 2021-11-01 | 135 | 11 |
| 2021-11-08 | 548 | 11 |
| 2021-11-15 | 405 | 11 |
| 2021-11-22 | 354 | 11 |
| 2021-11-29 | 537 | 11 |
| 2021-12-06 | 201 | 12 |
| 2021-12-13 | 441 | 12 |
| 2021-12-20 | 314 | 12 |
| 2021-12-27 | 350 | 12 |
Untuk melakukan proses peramalan library yang dibutuhkan dan data yang dijadikan sebagai objek peramalan sebagai berikut. Kolom month menunjukkan bulan.
B. Eksplorasi dan Pengujian Asumsi
B.1. Visualisasi Data
Langkah selanjutnya kita perlu menampilkan secara visual bagaimana kondisi data. Hal ini penting agar kita memperoleh gambaran pola maupun tren yang terjadi.
# mengubah jenis data pada kolom `month` menjadi factor
data$month <- as.factor(data$month)
# visualisasi data secara interaktif
sales_data <- xts(x = data$qty, order.by = data$date)
plot(sales_data, main = "Penjualan Sampel Produk Tahun 2021")
B.2. Heatmap Visualisasi Data
Plot peta untuk objek deret waktu berdasarkan periodisitasnya (saat ini hanya mendukung frekuensi harian, mingguan, bulanan, dan triwulanan). Berdasarkan gambar yang bisa kita lihat penjualan mingguan yang paling ramai pembeli di kisaran 40 sampai 50 yang bisa di artikan di akhir tahun penjualan itu menunjukan sangat pesat dan padat
ts_heatmap(sales_data,color = "Greens", title = "Penjualan berdasarkan permingguan")
B.3. Uji Asumsi: Homogenitas Ragam
Untuk menguji homogenitas ragam, bulan pengamatan akan dijadikan kelompok. Akan dilihat apakah kuantitas penjualan bulanan heterogen antara satu dengan lainnya ataukah tidak.
# uji yang dilakukan adalah Uji Fligner Test
fligner.test(data$qty, data$month, data = data)
##
## Fligner-Killeen test of homogeneity of variances
##
## data: data$qty and data$month
## Fligner-Killeen:med chi-squared = 5.9591, df = 11, p-value = 0.8761
Dari hasil pengujian Fligner-Killeen tersebut dapat dilihat bahwa nilai p-value < 0.05 yang menunjukkan data cenderung homogen antar bulan pengamatan.
C. Pembagian Data
C.1. Training dan Testing Data
Setelah mengetahui pola data dan homogenitas varians, langkah selanjutnya adalah membagi data menjadi Training dan Testing. Data Training digunakan untuk membentuk model, sedangkan data Testing digunakan untuk menguji model. Data pengamatan ke-1 s.d. ke-42 digunakan sebagai data Training sedangkan sisa digunakan sebagai data Testing. Pembagian data ini penting sehingga kita bisa mengevaluasi keakuratan dari model peramalan yang dibangun.
training <- data.frame(data[1:42,])
testing <- data.frame(data[43:52,])
C.2. Time Series Object
Selanjutnya atas data training tersebut, dibentuk timeseries object ts. Pembentukan objek ini menggunakan time cycle (frekuensi) pekanan ~(+-365 hari/7).
ts_training <- ts(training$qty, freq = 365.25/7, start = c(2021,1))
D. Stasioneritas
D.1. Pengujian Stasioneritas
Salah satu asumsi lain dalam menganalisis data deret waktu adalah stasioneritas. Artinya data deret waktu memiliki kecenderungan untuk bergerak di sepanjang rata-ratanya. Untuk menguji ini, metode yang umum digunakan adalah Augmented Dickey–Fuller (ADF) test.
# adf test
adf.test(ts_training)
##
## Augmented Dickey-Fuller Test
##
## data: ts_training
## Dickey-Fuller = -0.93136, Lag order = 3, p-value = 0.9368
## alternative hypothesis: stationary
dari pengujian ADF tersebut dapat diketahui bahwa data belum stasioner (p-value > 0.05). Oleh karena itu data perlu dilakukan diferensiasi sampai menemukan stasioneritas.
D.2. Diferensiasi
Proses diferensiasi dapat dilakukan sebagai berikut:
##
## Augmented Dickey-Fuller Test
##
## data: .
## Dickey-Fuller = -3.8007, Lag order = 3, p-value = 0.02963
## alternative hypothesis: stationary
Setelah dilakukan diferensiasi sebanyak satu kali (p,1,q), data telah stasioner (p-value < 0.05). Data hasil diferensiasi ini yang akan digunakan untuk pembentukan model peramalan.
E. Pembentukan Model
Secara keseluruhan akan coba dibentuk empat model peramalan. Keempat model yang dibangun tersebut adalah: (1) Arima, (2) Error, trend, seasonal model-ETS, (3) TBATS, dan (4) Exponential Smoothing. Dari hasi eksploratori data sebelumnya memang diketahui bahwa selain datanya tidak terlalu banyak, juga cenderung tidak memiliki efek seasonal, namun model (2) dan (3) tetap digunakan sebagai opsi. Keempat model tersebut kemudian akan dievaluasi dan dibandingkan keakurasiannya dalam meramal. Model dengan tingkat akurasi paling baik akan dipilih sebagai model terbaik dan digunakan untuk meramalkan nilai ke depan.
Untuk mengevaluasi beberapa model, dibentuk terlebih dahulu fungsi analisis sisaan yang bertujuan untuk melihat apakah sisaan yang dihasilkan model signifikan atau tidak.
analisis_sisaan <- function(model, std = TRUE){
if (std == TRUE){
res.model = rstandard(model)
}
else
{
res.model = residuals(model)
}
par(mfrow=c(2,2))
plot(res.model,type='o',ylab='Standardised residuals',
main="Time series plot of standardised residuals")
abline(h=0)
qqnorm(res.model,main="QQ plot of standardised residuals")
qqline(res.model, col = 2)
acf(res.model,main="ACF of standardised residuals")
k=0
LBQPlot(res.model, lag.max = length(model$residuals)-1 ,
StartLag = k + 1, k = 0, SquaredQ = FALSE)
par(mfrow=c(1,1))
}
# sources from
# https://www.titanwolf.org/Network/q/9119c26d-885e-4722-9037-3322eac273da/y
E.1. Model Arima
Untuk membentuk model Arima digunakan dua pendekatan yaitu dengan fungsi auto.arima dan pengamatan ACF dan PACF serta membentuk model overfitting sebagai perbandingan model dari auto.arima. Model dengan nilai AIC terkecil dan signifikan akan dipilih sebagai model terbaik Arima.
# model arima
ts_training %>% auto.arima(d = 1, stationary = F)
## Series: .
## ARIMA(1,1,2)
##
## Coefficients:
## ar1 ma1 ma2
## -0.9787 0.2116 -0.6226
## s.e. 0.0383 0.1467 0.1492
##
## sigma^2 estimated as 17884: log likelihood=-257.98
## AIC=523.97 AICc=525.08 BIC=530.82
dengan pendekatan auto.arima diperoleh model ARIMA (1,1,2) dengan AIC sebesar 523.97. Selanjutnya dilihat signfikansi koefisien model dan analisis sisaan sebagai berikut.
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.978724 0.038295 -25.5577 < 2.2e-16 ***
## ma1 0.211581 0.146703 1.4422 0.1492
## ma2 -0.622621 0.149207 -4.1729 3.008e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,1,2)
## Q* = 5.5067, df = 5, p-value = 0.3572
##
## Model df: 3. Total lags used: 8
Dari hasil tersebut dapat dilihat bahwa koefisien model signifikan dan residual model non-signifikan yang ditandai dengan Ljung-Box test non-signifikan (p-value > 0.05). Ini berarti model Arima (1,1,2) sudah baik.
Walaupun demikian, sebagai pembanding, kita perlu membandingkan dengan model overfitting hasil pengamatan ACF dan PACF.
Dari plot ACF dan PACF tersebut memang dapat dilihat model yang dihasilkan adalah ARIMA (1,1,2). Model overfitting yang dapat dicoba dan dibandingkan adalah ARIMA (2,1,2) atau ARIMA (1,1,3).
options(warn = -2)
ts_training %>% Arima(order=c(2,1,2))
## Series: .
## ARIMA(2,1,2)
##
## Coefficients:
## ar1 ar2 ma1 ma2
## -0.8793 0.0965 0.1517 -0.6578
## s.e. 0.2499 0.2399 0.1984 0.1610
##
## sigma^2 estimated as 18272: log likelihood=-257.9
## AIC=525.81 AICc=527.52 BIC=534.37
ts_training %>% Arima(order=c(1,1,3))
## Series: .
## ARIMA(1,1,3)
##
## Coefficients:
## ar1 ma1 ma2 ma3
## -0.9775 0.2974 -0.6518 -0.1307
## s.e. 0.0360 0.2086 0.1480 0.2324
##
## sigma^2 estimated as 18155: log likelihood=-257.82
## AIC=525.63 AICc=527.35 BIC=534.2
ts_training %>% Arima(order=c(2,1,2)) %>% lmtest::coeftest()
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.87930 0.24990 -3.5187 0.0004337 ***
## ar2 0.09651 0.23992 0.4023 0.6874912
## ma1 0.15167 0.19843 0.7643 0.4446663
## ma2 -0.65781 0.16096 -4.0869 4.372e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
ts_training %>% Arima(order=c(1,1,3)) %>% lmtest::coeftest()
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.977479 0.036038 -27.1235 < 2.2e-16 ***
## ma1 0.297424 0.208585 1.4259 0.1539
## ma2 -0.651813 0.148023 -4.4035 1.065e-05 ***
## ma3 -0.130719 0.232395 -0.5625 0.5738
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
ts_training %>% Arima(order=c(2,1,2)) %>% analisis_sisaan()
ts_training %>% Arima(order=c(1,1,3)) %>% analisis_sisaan()
ts_training %>% Arima(order=c(2,1,2)) %>% checkresiduals()
##
## Ljung-Box test
##
## data: Residuals from ARIMA(2,1,2)
## Q* = 6.0517, df = 4, p-value = 0.1953
##
## Model df: 4. Total lags used: 8
ts_training %>% Arima(order=c(1,1,3)) %>% checkresiduals()
##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,1,3)
## Q* = 6.7122, df = 4, p-value = 0.1519
##
## Model df: 4. Total lags used: 8
Berdasarkan model overfitting dapat dikonfirmasi bahwa ARIMA (1,1,2) memberikan model yang lebih baik. AIC lebih kecil dibandingakan dengan ARIMA overfitting, koefisien model signifikan, dan analisis sisaan juga non-signifikan. Dengan demikian model ARIMA (1,1,2) dipilih sebagai model terbaik.
model_arima <- ts_training %>% auto.arima(d = 1, stationary = F)
model_arima$aic
## [1] 523.9669
E.2. Model ETS
Model ETS dibangun sebagai berikut:
# ets
model_ets <- ts_training %>% ets()
model_ets$aic
## [1] 575.2265
AIC model ETS ini lebih besar dibandingkan dengan model ARIMA (575 vs 523)
E.3. Model TBATS
Model TBATS dibangun sebagai berikut:
# tbats
model_tbats <- ts_training %>% tbats(use.trend = F, use.damped.trend = F, use.box.cox = F, use.arma.errors = T)
model_tbats$AIC
## [1] 546.071
AIC model TBATS ini lebih besar dibandingkan dengan model ARIMA (546 vs 523)
E.4. Model Exonential Smoothing
Model Exponential Smoothing di bangun dengan metode Holt Winters sebagai berikut:
# Holt-Winters
model_exsmot <- ts_training %>% HoltWinters(gamma = F, beta = 0.1, alpha = 0.3)
model_exsmot
## Holt-Winters exponential smoothing with trend and without seasonal component.
##
## Call:
## HoltWinters(x = ., alpha = 0.3, beta = 0.1, gamma = F)
##
## Smoothing parameters:
## alpha: 0.3
## beta : 0.1
## gamma: FALSE
##
## Coefficients:
## [,1]
## a 427.88254
## b 19.98501
F. Peramal (Plot) dan Evaluasi Model
F.1. Peramalan dan Plot
Pada tahapan ini kita meramalkan 10 pengamatan atas data training dan membandingkan dengan data aktual testing sehingga dapat di ukur akurasinya.
F.1.1 Model Arima
# model arima
f_arima <- forecast(model_arima, h = 10) # h = testing data
plot_forecast(f_arima, title = "Model Arima")
# saveRDS(f_arima, file = "SFK.rds")
F.1.2 Model ETS
# model ets
f_ets <- forecast(model_ets, h = 10)
plot_forecast(f_ets, title = "Model ETS")
F.1.3 Model TBATS
# model tbats
f_tbats <- forecast(model_tbats, h = 10)
plot_forecast(f_tbats, title = "Model TBATS")
F.1.4 Model Exponential Smoothing
# model exponential smoothing
f_exsmot <- forecast(model_exsmot, h = 10)
plot_forecast(f_exsmot, title = "Model Exponential Smoothing")
F.2. Kompilasi Hasil Forecast vs Testing
Dari keempat model tersebut, hasil peramalan 10 pengamatan dan disandingkan dengan data testing menghasilkan sebagai berikut:
df_arima <- f_arima$mean %>% as.data.frame() %>%
mutate(across(where(is.numeric), ~ round(., 0)))
colnames(df_arima) <- "arima"
df_ets <- f_ets$mean %>% as.data.frame() %>%
mutate(across(where(is.numeric), ~ round(., 0)))
colnames(df_ets) <- "ets"
df_tbats <- f_tbats$mean %>% as.data.frame() %>%
mutate(across(where(is.numeric), ~ round(., 0)))
colnames(df_tbats) <- "tbats"
df_exsmot <- f_exsmot$mean %>% as.data.frame() %>%
mutate(across(where(is.numeric), ~ round(., 0)))
colnames(df_exsmot) <- "holtwinters"
kompilasi <- cbind(testing, df_arima, df_ets, df_exsmot, df_tbats)
kompilasi %>% select(-3) %>% kbl(booktabs = T) %>%
kable_styling(latex_options = c("striped", "HOLD_position"))
| date | qty | arima | ets | holtwinters | tbats |
|---|---|---|---|---|---|
| 2021-10-25 | 536 | 408 | 366 | 448 | 625 |
| 2021-11-01 | 135 | 416 | 366 | 468 | 751 |
| 2021-11-08 | 548 | 408 | 366 | 488 | 809 |
| 2021-11-15 | 405 | 416 | 366 | 508 | 832 |
| 2021-11-22 | 354 | 408 | 366 | 528 | 815 |
| 2021-11-29 | 537 | 416 | 366 | 548 | 762 |
| 2021-12-06 | 201 | 408 | 366 | 568 | 678 |
| 2021-12-13 | 441 | 416 | 366 | 588 | 576 |
| 2021-12-20 | 314 | 408 | 366 | 608 | 467 |
| 2021-12-27 | 350 | 416 | 366 | 628 | 364 |
F.3. Evaluasi Model
Selanjutnya, atas perbandingan dengan data aktual testing tersebut, kita mengevaluasi model dengan beberapa kriteria seperti RMSE, MAE, MAPE, etc. Model yang memberikan kriteria optimal dipilih sebagai model terbaik.
ak_arima <- accuracy(kompilasi$qty, kompilasi$arima, d = 1, D = 0)
ak_ets <- accuracy(kompilasi$qty, kompilasi$ets, d = 1, D = 0)
ak_holtwinters <- accuracy(kompilasi$qty, kompilasi$holtwinters, d = 1, D = 0)
ak_tbats <- accuracy(kompilasi$qty, kompilasi$tbats, d = 1, D = 0)
ak_compile <- rbind(ak_arima, ak_ets, ak_holtwinters, ak_tbats)
rownames(ak_compile) <- c("arima","ets", "holtwinters", "tbats")
ak_compile %>% as.data.frame() %>% mutate(across(where(is.numeric), ~ round(., 2))) %>%
kbl(booktabs = T) %>% kable_styling(latex_options = c("striped", "HOLD_position"))
| ME | RMSE | MAE | MPE | MAPE | ACF1 | Theil’s U | |
|---|---|---|---|---|---|---|---|
| arima | 29.9 | 137.58 | 112.7 | 7.23 | 27.38 | -0.67 | 17.33 |
| ets | -16.1 | 134.94 | 111.3 | -4.40 | 30.41 | -0.67 | Inf |
| holtwinters | 155.9 | 219.83 | 185.5 | 27.67 | 34.06 | -0.38 | 11.33 |
| tbats | 285.8 | 342.10 | 285.8 | 39.63 | 39.63 | -0.13 | 3.63 |
Dari tabel tersebut dapat dilihat bahwa, dalam konteks Inventory dan Supply Chain, model Arima lebih dapat diterima dibandingkan dengan model yang lain dengan argumen sebagai berikut.
- Memiliki nilai kriteria parameter yang tergolong rendah dibandingkan dengan yang lain. Model ini memberikan persentase tingkat kekeliruan sebesar 7% lebih tinggi dibandingkan dengan data aktual.
- Walaupun rendah juga, namun ETS memiliki estimasi nilai yang negatif (pada ME dan MPE) yang bermakna bahwa estimasinya lebih rendah dibandingkan dengan nilai rata-rata pada data testing. Dalam konteks inventory tentu hal ini harus dihindari.
Dengan demikian model Arima dipilih sebagai model untuk memprediksi.
G. Peramalan
Misalnya kita ingin melakukan peramalan selama periode 3 bulan ke depan (tahun 2022) atau 12 pekan. Hal tersebut dapat dilakukan sebagai berikut:
tanggal <- c("21-10-25", "21-11-01", "21-11-08", "21-11-15", "21-11-22", "21-11-29", "21-12-06", "21-12-13", "21-12-20", "21-12-27", "22-01-03", "22-01-10", "22-01-17", "22-01-24", "22-01-31", "22-02-07", "22-02-14", "22-02-21", "22-02-28", "22-03-07", "22-03-14", "22-03-21")
ymd(tanggal)
## [1] "2021-10-25" "2021-11-01" "2021-11-08" "2021-11-15" "2021-11-22"
## [6] "2021-11-29" "2021-12-06" "2021-12-13" "2021-12-20" "2021-12-27"
## [11] "2022-01-03" "2022-01-10" "2022-01-17" "2022-01-24" "2022-01-31"
## [16] "2022-02-07" "2022-02-14" "2022-02-21" "2022-02-28" "2022-03-07"
## [21] "2022-03-14" "2022-03-21"
df_tanggal <- tanggal %>% as.data.frame.Date()
df_tanggal <- df_tanggal[-c(1:10),] %>% as.data.frame.Date()
colnames(df_tanggal) <- "date_yymmdd"
data_forecast <- f_arima_2022$mean %>% as.data.frame()
data_forecast <- data_forecast[-c(1:10),] %>% as.data.frame()
colnames(data_forecast) <- "forecast"
Maka peramalan untuk periode 12 pekan ke depan adalah:
data_forecast_2022 <- cbind(df_tanggal, data_forecast)
data_forecast_2022 %>% mutate(across(where(is.numeric), ~ round(., 1))) %>%
kbl(booktabs = T) %>% kable_styling(latex_options = c("striped", "HOLD_position"))
| date_yymmdd | forecast |
|---|---|
| 22-01-03 | 408.6 |
| 22-01-10 | 415.5 |
| 22-01-17 | 408.8 |
| 22-01-24 | 415.3 |
| 22-01-31 | 408.9 |
| 22-02-07 | 415.2 |
| 22-02-14 | 409.0 |
| 22-02-21 | 415.1 |
| 22-02-28 | 409.2 |
| 22-03-07 | 415.0 |
| 22-03-14 | 409.3 |
| 22-03-21 | 414.8 |
library(readxl)
ul <- read_excel("detail_jualan.xls", skip = 7)
head(ul)
## # A tibble: 6 x 25
## NO FAKTUR TANGGAL KODE_CUS CUSTOMER DIVISI SALES GUDANG
## <dbl> <chr> <dttm> <chr> <chr> <chr> <chr> <chr>
## 1 1 0001/F/01/21 2021-01-04 00:00:00 "\"10006~ SINAR TI~ D-RMF SAL-M GUD R~
## 2 2 0001/F/02/21 2021-02-01 00:00:00 "\"10000~ HARYANTO~ D-RMF SAL-Y GUD R~
## 3 3 0001/F/03/21 2021-03-02 00:00:00 "\"10024~ AGUNG SE~ D-RMF SAL-Y GUD R~
## 4 4 0001/F/04/21 2021-04-01 00:00:00 "\"10003~ CITRA MA~ D-RMF SAL-Y GUD R~
## 5 5 0001/F/05/21 2021-05-03 00:00:00 "\"17007~ PHANG EN~ D-RMF SAL-6 GUD R~
## 6 6 0001/F/06/21 2021-06-01 00:00:00 "\"18000~ WHITE HO~ D-RMF SAL-6 GUD R~
## # ... with 17 more variables: JTH_TEMPO <dttm>, KODE_BRG <chr>, NAMA_BRG <chr>,
## # BANYAK <dbl>, HARGA <dbl>, KURS <dbl>, DISC <dbl>, DISCOUNT <dbl>,
## # TOTAL <dbl>, TOTAL FAKTUR <dbl>, DPP <dbl>, PPN <dbl>, FAKGDG <lgl>,
## # KETERANGAN <chr>, KET ITEM <lgl>, PO <lgl>, TGLPO <dttm>
ul_clean_discard <-
ul %>% select(
-c(
NO,
FAKTUR,
KODE_CUS,
DIVISI,
GUDANG,
KODE_BRG,
DISCOUNT,
FAKGDG,
KURS,
PO,
KETERANGAN,
KODE_BRG,
TGLPO,
JTH_TEMPO,
DISC,
`KET ITEM`
)
)
ul_clean <-
ul_clean_discard %>% mutate_at(c("SALES","NAMA_BRG", "CUSTOMER"), as.factor) %>%
filter_if(is.numeric, all_vars((.) != 0))
head(ul_clean)
## # A tibble: 6 x 10
## TANGGAL CUSTOMER SALES NAMA_BRG BANYAK HARGA TOTAL
## <dttm> <fct> <fct> <fct> <dbl> <dbl> <dbl>
## 1 2021-01-04 00:00:00 SINAR TIMUR - ~ SAL-M GRACE F 55050~ 1 168300 1.14e5
## 2 2021-02-01 00:00:00 HARYANTO - JAK~ SAL-Y R.GRANIT GT91~ 1 490050 3.03e5
## 3 2021-03-02 00:00:00 AGUNG SENTRA K~ SAL-Y R.GRANIT GT61~ 1 314050 1.97e5
## 4 2021-04-01 00:00:00 CITRA MANDIRI SAL-Y INTERLOK GL63~ 22 188100 2.82e6
## 5 2021-06-01 00:00:00 WHITE HOUSE PD~ SAL-6 R.GRESS F 227~ 2 133650 1.85e5
## 6 2021-07-02 00:00:00 MAKMUR KERAMIK~ SAL-B6 R.GRANIT GT63~ 1 348150 2.14e5
## # ... with 3 more variables: TOTAL FAKTUR <dbl>, DPP <dbl>, PPN <dbl>
str(ul_clean)
## tibble [44,642 x 10] (S3: tbl_df/tbl/data.frame)
## $ TANGGAL : POSIXct[1:44642], format: "2021-01-04" "2021-02-01" ...
## $ CUSTOMER : Factor w/ 684 levels "ACC - CIBUBUR*",..: 591 187 6 98 676 288 126 207 24 437 ...
## $ SALES : Factor w/ 19 levels "SAL-2","SAL-20",..: 18 19 19 19 6 10 11 11 4 11 ...
## $ NAMA_BRG : Factor w/ 1332 levels "ASIA CLIFFORD GREY 25x50 KW 1",..: 25 656 509 209 894 585 403 192 327 23 ...
## $ BANYAK : num [1:44642] 1 1 1 22 2 1 1 14 5 12 ...
## $ HARGA : num [1:44642] 168300 490050 314050 188100 133650 ...
## $ TOTAL : num [1:44642] 113603 302606 196972 2824322 185426 ...
## $ TOTAL FAKTUR: num [1:44642] 113603 302606 196972 2824322 185426 ...
## $ DPP : num [1:44642] 103275 275096 179066 2567565 168569 ...
## $ PPN : num [1:44642] 10328 27510 17907 256757 16857 ...
dim(ul_clean)
## [1] 44642 10
ul_clean <-
ul_clean[order(ul_clean$TANGGAL),]
ul_clean
## # A tibble: 44,642 x 10
## TANGGAL CUSTOMER SALES NAMA_BRG BANYAK HARGA TOTAL
## <dttm> <fct> <fct> <fct> <dbl> <dbl> <dbl>
## 1 2021-01-04 00:00:00 SINAR TIMUR - ~ SAL-M GRACE F 5505~ 1 168300 1.14e5
## 2 2021-01-04 00:00:00 ANEKA BANGUNAN~ SAL-M INTERLOK GL6~ 1 187000 1.28e5
## 3 2021-01-04 00:00:00 PHANG ENG LIE SAL-6 ROMAN F 2631~ 4 147400 4.48e5
## 4 2021-01-04 00:00:00 TERATAI KERAMIK SAL-B6 R.GRES F 229~ 4 153450 4.26e5
## 5 2021-01-04 00:00:00 TERATAI KERAMIK SAL-B6 PRECUT WA 33~ 25 239250 4.26e6
## 6 2021-01-04 00:00:00 PT.SINAR BARU ~ SAL-B6 R.GRANIT GTA~ 13 275000 2.24e6
## 7 2021-01-04 00:00:00 MMS - CINERE SAL-B6 INTERLOK GL6~ 12 229900 1.88e6
## 8 2021-01-04 00:00:00 SINAR MAJU - K~ SAL-B6 RECTIFIED W ~ 15 201300 2.15e6
## 9 2021-01-04 00:00:00 SINAR MAJU - K~ SAL-B6 GRACE F 3320~ 10 177650 1.27e6
## 10 2021-01-04 00:00:00 PELITA HARAPAN~ SAL-8 STEPTILE BGT~ 7 193600 1.36e6
## # ... with 44,632 more rows, and 3 more variables: TOTAL FAKTUR <dbl>,
## # DPP <dbl>, PPN <dbl>
plot_penjualan_persale <- ul_clean %>%
group_by(SALES) %>%
summarise(total = mean (`TOTAL FAKTUR`)) %>%
arrange(desc(total)) %>%
mutate(label = glue("Rata-rata penjualan = {total}")) %>%
ggplot(plot, mapping = aes(
x = reorder(SALES, desc(total)),
y = total,
fill = SALES,
text = label
)) + geom_bar(stat = "identity") + xlab("Sales Group") + ylab("Total Rata-rata Penjualan Perbulan") + theme_minimal() + theme(legend.position = "none") + guides(x = guide_axis(n.dodge = 2), y.sec = guide_axis())
ggplotly(plot_penjualan_persale, tooltip = "label")
weekly_quantity <-
ul_clean %>% mutate(date = week(TANGGAL)) %>% # converted become weekly
group_by(date, SALES) %>% # group by berdasarkan category tiap team sales dan perminggu
summarise(quantity = sum(BANYAK),
# transaksi yang sukses
total = sum(`TOTAL FAKTUR`)) # total perminggu tiap team sales
penjualan_tahunan <-
weekly_quantity %>%
mutate(
label = glue(
"Jumlah Transaksi = {quantity}
Total Rupiah = {comma(total)}
Weekly = {date}
Team Sales = {SALES}"
)
) %>%
filter() %>%
ggplot(mapping = aes(
x = date,
y = quantity,
group = SALES,
color = SALES,
text = label
)) + geom_line(lwd = 1) + geom_point()
ggtitle("Team sales penjualan 2020-2021") +
theme_minimal()
## NULL
ggplotly(penjualan_tahunan, tooltip = "label")
pembeli_terbanyak_12ribu <-
ul_clean %>% mutate(bulan = month(TANGGAL)) %>%
group_by(CUSTOMER) %>% # mengroupkan bulan nya
summarise(quantity = sum(BANYAK),
PPN = sum(PPN),
DPP = sum(DPP)) %>%
filter(quantity > 12000) %>%
mutate(label = glue("Pembeli = {CUSTOMER}
Total Transaksi = {quantity}")) %>%
ggplot(
mapping = aes(
x = reorder(CUSTOMER, desc(quantity)),
y = quantity,
fill = quantity,
text = label
)
) + geom_bar(stat = "identity") + theme(legend.position = "none") + labs(x = "Nama Perusahaan", y = "Jumlah transaksi") + guides(x = guide_axis(n.dodge = 2), y.sec = guide_axis()) + scale_fill_continuous()
ggplotly(pembeli_terbanyak_12ribu, tooltip = "label")
weekly_buyers <-
ul_clean %>% transmute(TANGGAL,BANYAK) %>%
mutate(week = week(TANGGAL)) %>%
group_by(week) %>%
summarise(stock = sum(BANYAK))
weekly_buyers
## # A tibble: 52 x 2
## week stock
## <dbl> <dbl>
## 1 1 8762
## 2 2 16530
## 3 3 12663
## 4 4 16440
## 5 5 15091
## 6 6 15691
## 7 7 9937
## 8 8 14848
## 9 9 16140
## 10 10 11907
## # ... with 42 more rows
training1 <- weekly_buyers[1:42,]
testing1<- weekly_buyers[43:52,]
ts_1 <- ts(training1$stock, frequency = 365/7, start = c(2021,1)) # perminggu dalam 1 tahun
adf.test(ts_1)
##
## Augmented Dickey-Fuller Test
##
## data: ts_1
## Dickey-Fuller = -1.9808, Lag order = 3, p-value = 0.5812
## alternative hypothesis: stationary
tail(ul_clean)
## # A tibble: 6 x 10
## TANGGAL CUSTOMER SALES NAMA_BRG BANYAK HARGA TOTAL
## <dttm> <fct> <fct> <fct> <dbl> <dbl> <dbl>
## 1 2021-12-31 00:00:00 AGUS SUDJONO SAL-~ R.GRANIT GT8~ 1 827376 5.11e5
## 2 2021-12-31 00:00:00 SEDERHANA SAL-~ RECTIFIED W ~ 28 187550 3.66e6
## 3 2021-12-31 00:00:00 SEDERHANA SAL-~ RECTIFIED F ~ 4 198550 5.66e5
## 4 2021-12-31 00:00:00 CV. ANDALAN CAH~ SAL-~ STEPNOSING R~ 3500 9482 3.32e7
## 5 2021-12-31 00:00:00 CAHAYA TERANG -~ SAL-~ RECTIFIED W ~ 1 187550 1.34e5
## 6 2021-12-31 00:00:00 NUSANTARA BANGU~ SAL-M R.GRANIT GT6~ 5 353650 1.11e6
## # ... with 3 more variables: TOTAL FAKTUR <dbl>, DPP <dbl>, PPN <dbl>
ts_1 %>% diff() %>% tsdisplay()
ts_1 %>% diff() %>% adf.test()
##
## Augmented Dickey-Fuller Test
##
## data: .
## Dickey-Fuller = -4.5006, Lag order = 3, p-value = 0.01
## alternative hypothesis: stationary
analisis_sisaan <- function(model, std = TRUE){
if (std == TRUE){
res.model = rstandard(model)
}
else
{
res.model = residuals(model)
}
par(mfrow=c(2,2))
plot(res.model,type='o',ylab='Standardised residuals',
main="Time series plot of standardised residuals")
abline(h=0)
qqnorm(res.model,main="QQ plot of standardised residuals")
qqline(res.model, col = 2)
acf(res.model,main="ACF of standardised residuals")
k=0
LBQPlot(res.model, lag.max = length(model$residuals)-1 ,
StartLag = k + 1, k = 0, SquaredQ = FALSE)
par(mfrow=c(1,1))
}
ts_1 %>% auto.arima(d = 1, stationary = F)
## Series: .
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.1666 -0.7922
## s.e. 0.2195 0.1415
##
## sigma^2 estimated as 15175555: log likelihood=-396.49
## AIC=798.98 AICc=799.63 BIC=804.12
options(warn = -2)
ts_1 %>% auto.arima(d = 1, stationary = F) %>% lmtest::coeftest()
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 0.16656 0.21945 0.7590 0.4479
## ma1 -0.79225 0.14150 -5.5988 2.158e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
ts_1 %>% auto.arima(d = 1, stationary = F) %>% checkresiduals()
##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,1,1)
## Q* = 5.6409, df = 6, p-value = 0.4646
##
## Model df: 2. Total lags used: 8
ts_1 %>% auto.arima(d = 1, stationary = F) %>% analisis_sisaan()
# model bandingan overfitting
ACF1 <- ts_1 %>% diff() %>% Acf(plot = F)
PACF1 <- ts_1 %>% diff() %>% Pacf(plot = F)
par(mar=c(3,2,3,0))
plot(ACF1, main = "Stock penjualan perbulan XYZ Time Series ACF")
plot(PACF1, main = "Stock penjualan perbulan XYZ Time Series PACF")
options(warn = -2)
ts_1 %>% Arima(order=c(1,1,1))
## Series: .
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.1666 -0.7922
## s.e. 0.2195 0.1415
##
## sigma^2 estimated as 15175555: log likelihood=-396.49
## AIC=798.98 AICc=799.63 BIC=804.12
ts_1 %>% Arima(order=c(3,1,2))
## Series: .
## ARIMA(3,1,2)
##
## Coefficients:
## ar1 ar2 ar3 ma1 ma2
## -0.2592 0.0294 -0.2897 -0.3469 -0.2098
## s.e. 0.3331 0.2699 0.1928 0.3337 0.2644
##
## sigma^2 estimated as 15220344: log likelihood=-395.02
## AIC=802.03 AICc=804.5 BIC=812.31
ts_1 %>% Arima(order=c(1,1,1)) %>% lmtest::coeftest()
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 0.16656 0.21945 0.7590 0.4479
## ma1 -0.79225 0.14150 -5.5988 2.158e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
ts_1 %>% Arima(order=c(3,1,2)) %>% lmtest::coeftest()
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.25923 0.33306 -0.7783 0.4364
## ar2 0.02942 0.26992 0.1090 0.9132
## ar3 -0.28975 0.19281 -1.5028 0.1329
## ma1 -0.34688 0.33370 -1.0395 0.2986
## ma2 -0.20978 0.26443 -0.7933 0.4276
ts_1 %>% Arima(order=c(1,1,1)) %>% analisis_sisaan()
ts_1 %>% Arima(order=c(3,1,2)) %>% analisis_sisaan()
ts_1 %>% Arima(order=c(1,1,1)) %>% checkresiduals()
##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,1,1)
## Q* = 5.6409, df = 6, p-value = 0.4646
##
## Model df: 2. Total lags used: 8
ts_1 %>% Arima(order=c(3,1,2)) %>% checkresiduals()
##
## Ljung-Box test
##
## data: Residuals from ARIMA(3,1,2)
## Q* = 3.5757, df = 3, p-value = 0.3111
##
## Model df: 5. Total lags used: 8
model_arima3 <- ts_1 %>% arima(order = c(1,1,1),seasonal = list(order = c(1,0,0), period = 12), method = "ML")
model_arima2 <- ts_1 %>% auto.arima(d = 1, stationary = F)
model_ets1 <- ts_1 %>% ets()
model_tbats1 <- ts_1 %>% tbats(use.trend = F, use.damped.trend = F,
use.box.cox = F, use.arma.errors = T)
model_exsmot1 <- ts_1 %>% HoltWinters(gamma = F, beta = 0.1, alpha = 0.3)
auto.arima(ts_1, trace=TRUE)
##
## Fitting models using approximations to speed things up...
##
## ARIMA(2,1,2) with drift : Inf
## ARIMA(0,1,0) with drift : 793.2523
## ARIMA(1,1,0) with drift : 785.7222
## ARIMA(0,1,1) with drift : 784.178
## ARIMA(0,1,0) : 791.1848
## ARIMA(1,1,1) with drift : 783.6381
## ARIMA(2,1,1) with drift : Inf
## ARIMA(1,1,2) with drift : 784.4443
## ARIMA(0,1,2) with drift : 785.9104
## ARIMA(2,1,0) with drift : 788.6544
## ARIMA(1,1,1) : 781.3218
## ARIMA(0,1,1) : 782.5907
## ARIMA(1,1,0) : 783.4559
## ARIMA(2,1,1) : 783.6508
## ARIMA(1,1,2) : 782.3807
## ARIMA(0,1,2) : 784.4344
## ARIMA(2,1,0) : 786.3107
## ARIMA(2,1,2) : 784.3377
##
## Now re-fitting the best model(s) without approximations...
##
## ARIMA(1,1,1) : 799.6273
##
## Best model: ARIMA(1,1,1)
## Series: ts_1
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.1666 -0.7922
## s.e. 0.2195 0.1415
##
## sigma^2 estimated as 15175555: log likelihood=-396.49
## AIC=798.98 AICc=799.63 BIC=804.12
forecast_arima <-
forecast(model_arima2, h = 10)
plot_forecast(forecast_arima,title = "Auto Arima Model",color = "Purple", Xtitle = "Weekly",
Ytitle = "Stock paid")
forecast_ets <- forecast(model_ets1, h = 10)
plot_forecast(forecast_ets, title = "ETS Model",color = "RED", Xtitle = "Weekly",
Ytitle = "Stock paid")
ul_clean %>% group_by(CUSTOMER) %>%
summarise(Jumlah_Transaksi = n(),
total_pengeluaran = sum(`TOTAL FAKTUR`),
total_pengeluaran_in_M = round(total_pengeluaran/1000000000, digits = 2)) %>%
arrange(desc(total_pengeluaran))
## # A tibble: 674 x 4
## CUSTOMER Jumlah_Transaksi total_pengeluar~ total_pengeluar~
## <fct> <int> <dbl> <dbl>
## 1 CV.KEMENANGAN JAYA TRADING 1414 27463956595. 27.5
## 2 PT. SUMBER JAYA LANGGENG 1325 9457786110. 9.46
## 3 PT. SEHATI BANGUNAN ABADI 604 7140263517. 7.14
## 4 CV. HAKA ANUGRAH JAYA 756 4560503585. 4.56
## 5 DEPOK KERAMIK - DEPOK* 714 4189033101. 4.19
## 6 INTI GADING KERAMIK 470 3856634187. 3.86
## 7 BERGUNA JAYA - P.POLIM* 709 3796426639. 3.8
## 8 CAHAYA INDAH K. - P.AREN* 715 3744965404. 3.74
## 9 BINTANG KERAMIK - JAKBAR* 1119 3599621570. 3.6
## 10 WILLY HANSEN 687 3410855618. 3.41
## # ... with 664 more rows
ul_clean %>% group_by(NAMA_BRG) %>%
summarise(Jumlah = sum(BANYAK),
per_transaksi = n()) %>%
arrange(desc(Jumlah))
## # A tibble: 1,316 x 3
## NAMA_BRG Jumlah per_transaksi
## <fct> <dbl> <int>
## 1 RECTIFIED W 63801R KW 1 12936 668
## 2 STEPNOSING SN 13606 KW 1 11187 13
## 3 R.GRANIT GT609860FR KW 1 9947 182
## 4 ROMAN W 40106 KW 1 9730 335
## 5 R.GRANIT GT609866FR KW 1 9343 222
## 6 RECTIFIED W 63364R KW 1 8963 297
## 7 R.GRES F 447106 KW1 8452 132
## 8 R.GRES F 447442 KW1 8114 112
## 9 RECTIFIED W 63765R KW 1 7919 129
## 10 GRACE F 557379 KW 1 7256 44
## # ... with 1,306 more rows
df1 <-
ul %>% mutate(week = week(TANGGAL)) %>%
group_by(NAMA_BRG, week) %>%
summarise(quantity_barang = sum(BANYAK), # banyaknya quantity terjual
per_transaksi = n(),
total_in_rp = sum(`TOTAL FAKTUR`)) %>% filter(NAMA_BRG == "RECTIFIED W 63801R KW 1") %>% mutate(NAMA_BRG = as.factor(NAMA_BRG))
head(df1)
## # A tibble: 6 x 5
## # Groups: NAMA_BRG [1]
## NAMA_BRG week quantity_barang per_transaksi total_in_rp
## <fct> <dbl> <dbl> <int> <dbl>
## 1 RECTIFIED W 63801R KW 1 1 93 6 67632896.
## 2 RECTIFIED W 63801R KW 1 2 349 15 73045701.
## 3 RECTIFIED W 63801R KW 1 3 52 9 16088016.
## 4 RECTIFIED W 63801R KW 1 4 294 16 51035688.
## 5 RECTIFIED W 63801R KW 1 5 225 11 60508205.
## 6 RECTIFIED W 63801R KW 1 6 132 12 37976807.
dataset_barang <-
ul_clean %>% mutate(week = week(TANGGAL)) %>%
group_by(NAMA_BRG, week) %>% summarise(quantity_barang = sum(BANYAK), # banyaknya quantity terjual
per_transaksi = n(),
total_in_rp = sum(`TOTAL FAKTUR`)) %>% mutate(NAMA_BRG = as.factor(NAMA_BRG)) %>%
arrange(desc(week))
head(dataset_barang)
## # A tibble: 6 x 5
## # Groups: NAMA_BRG [6]
## NAMA_BRG week quantity_barang per_transaksi total_in_rp
## <fct> <dbl> <dbl> <int> <dbl>
## 1 GRACE F 332132P KW 1 53 3 1 390308.
## 2 GRACE F 33554P KW 1 53 3 1 3469874.
## 3 GRACE F 550005 KW 1 53 32 1 3706560
## 4 GRACE F 550012 KW 1 53 3 1 334008.
## 5 GRACE F 550500 KW 1 53 45 1 5212350
## 6 GRACE F 550501 KW 1 53 4 1 463320
ul_clean %>% group_by(SALES, CUSTOMER) %>%
summarise(pembelian_tiap_sale_customer = n(),
stock_terbeli = sum(BANYAK),
total = sum(`TOTAL FAKTUR`),
total_M = round(total/1000000000, digits = 2)) %>%
arrange(desc(total_M))
## # A tibble: 849 x 6
## # Groups: SALES [18]
## SALES CUSTOMER pembelian_tiap_sale_~ stock_terbeli total total_M
## <fct> <fct> <int> <dbl> <dbl> <dbl>
## 1 SAL-Y CV.KEMENANGAN J~ 888 29368 1.63e10 16.3
## 2 SAL-41 CV.KEMENANGAN J~ 388 20823 7.44e 9 7.44
## 3 SAL-Y PT. SUMBER JAYA~ 743 20925 6.39e 9 6.39
## 4 SAL-L CV. HAKA ANUGRA~ 755 10875 4.55e 9 4.55
## 5 SAL-B8 DEPOK KERAMIK -~ 714 14085 4.19e 9 4.19
## 6 SAL-B8 BERGUNA JAYA - ~ 709 12740 3.80e 9 3.8
## 7 SAL-8 CV.KEMENANGAN J~ 130 5344 3.72e 9 3.72
## 8 SAL-B6 BINTANG KERAMIK~ 1115 12691 3.59e 9 3.59
## 9 SAL-8 WILLY HANSEN 687 11146 3.41e 9 3.41
## 10 SAL-B8 CV. TIMUR BARU 666 11501 3.30e 9 3.3
## # ... with 839 more rows
dataset_viz <-
dataset_barang %>% mutate(label = glue(
"Weekly = {week}
Total Rupiah = {comma(total_in_rp)}
Product = {NAMA_BRG}"
)) %>%
filter(
NAMA_BRG == "STEPNOSING SN 13606 KW 1" |
NAMA_BRG == "RECTIFIED W 63801R KW 1" |
NAMA_BRG == "R.GRANIT GT609860FR KW 1" |
NAMA_BRG == "ROMAN W 40106 KW 1" |
NAMA_BRG == "R.GRANIT GT609866FR KW 1"
) %>%
ggplot(
mapping = aes(
x = week,
y = quantity_barang,
group = NAMA_BRG,
fill = NAMA_BRG,
color = NAMA_BRG,
text = label
)
) + geom_point() + geom_smooth(method = lm, se = F) + labs(title = "Regression Linear Product")
ggplotly(dataset_viz, tooltip = "label")
dataset <-
ul_clean %>% filter(NAMA_BRG == "RECTIFIED W 63801R KW 1") %>%
mutate(TANGGAL = TANGGAL %>% floor_date(unit = "week")) %>%
group_by(TANGGAL) %>%
summarise(var = sum(BANYAK)) %>%
mutate(month = month(TANGGAL)) # mengubah jenis data pada kolom `month` menjadi factor
head(dataset, 10)
## # A tibble: 10 x 3
## TANGGAL var month
## <dttm> <dbl> <dbl>
## 1 2021-01-03 00:00:00 200 1
## 2 2021-01-10 00:00:00 265 1
## 3 2021-01-17 00:00:00 55 1
## 4 2021-01-24 00:00:00 447 1
## 5 2021-01-31 00:00:00 106 1
## 6 2021-02-07 00:00:00 72 2
## 7 2021-02-14 00:00:00 171 2
## 8 2021-02-21 00:00:00 360 2
## 9 2021-02-28 00:00:00 111 2
## 10 2021-03-07 00:00:00 393 3
dataset_sales <-
xts(x = dataset$var, order.by = dataset$TANGGAL)
plot(dataset_sales, main = "Penjualan Sampel Produk Tahun 2021") # visualisasi data secara interaktif
plotly1 <-
ul_clean %>%
group_by(TANGGAL, SALES, CUSTOMER) %>% # group by berdasarkan category tiap team sales dan perminggu
summarise(quantity = sum(BANYAK),
total_faktur = sum(`TOTAL FAKTUR`),
product = (NAMA_BRG)) %>% mutate(label = glue (
"Total barang terjual = {quantity}
Total Rupiah = {comma(total_faktur)}
Date = {TANGGAL}
Team Sales = {SALES}
Customer = {CUSTOMER}"
)) %>% filter(SALES == "SAL-L" | SALES == "SAL-K" | SALES == "SAL-2") %>%
ggplot(mapping = aes(x = TANGGAL,
y = quantity,
color = SALES,
size = quantity,
text = label)) + geom_point(alpha=0.7) +
scale_size(range = c(1.4, 10)) +scale_color_viridis(discrete=TRUE, guide=FALSE)
ggtitle("Team sales penjualan 2020-2021") +
theme_minimal()
## NULL
ggplotly(plotly1, tooltip = "label")
ul_clean %>% group_by(SALES) %>% summarise(var = n()) %>%
arrange(desc(var))
## # A tibble: 18 x 2
## SALES var
## <fct> <int>
## 1 SAL-B8 9723
## 2 SAL-B6 7761
## 3 SAL-8 7176
## 4 SAL-Y 6731
## 5 SAL-M 5687
## 6 SAL-41 3257
## 7 SAL-6 1616
## 8 SAL-L 1251
## 9 SAL-2 607
## 10 SAL-C4 450
## 11 SAL-K 204
## 12 SAL-74 57
## 13 SAL-20 31
## 14 SAL-49 23
## 15 SAL-67 22
## 16 SAL-G 21
## 17 SAL-H 18
## 18 SAL-26 7