library(tidyverse)
library(ggplot2)
library(forcats)
library(caret)
library(forecast)
library(TTR)
library(fpp)
library(xts)
library(lubridate)
library(padr)
library(MLmetrics)
options(scipen=999)
knitr::opts_chunk$set(fig.align = "center")R.version## _
## platform x86_64-w64-mingw32
## arch x86_64
## os mingw32
## crt ucrt
## system x86_64, mingw32
## status
## major 4
## minor 2.1
## year 2022
## month 06
## day 23
## svn rev 82513
## language R
## version.string R version 4.2.1 (2022-06-23 ucrt)
## nickname Funny-Looking Kid
LBB ini mendemonstrasikan pemodelan machine learning untuk data time series.
.Rmd atau styles.css bisa melihat
github proyek ini di taruma/mls-lbb-5.
|> yang tersedia di R 4.1+
untuk versi selain itu gunakan %>%.
Dataset yang digunakan adalah data Daily Exchange Rates per Euro 1999-2022 yang diperoleh dari Kaggle (Data diunduh pada hari Senin, 28 November 2022). Dataset ini berisikan Exchange Rate (Nilai tukar) Euro/EUR (€) terhadap mata uang negara lain setiap harinya sejak tahun 1999. Berikut 6 baris pertama dataset.
exchange <- read.csv("data/euro-daily-hist_1999_2022.csv")
exchange |> head()Sebagai catatan, dataset diurutkan dari yang terbaru ke yang terlama.
Sehingga, baris pertama merupakan data paling terbaru (2022) meski di
halaman dataset dimulai dari 1999. Berikut 6 baris terakhir dataset
exchange.
exchange |> tail()Berikut struktur dataset menggunakan str().
str(exchange)## 'data.frame': 6177 obs. of 41 variables:
## $ Period.Unit. : chr "2022-11-15" "2022-11-14" "2022-11-11" "2022-11-10" ...
## $ X.Australian.dollar.. : chr "1.5415" "1.5427" "1.5459" "1.5525" ...
## $ X.Bulgarian.lev.. : chr "1.9558" "1.9558" "1.9558" "1.9558" ...
## $ X.Brazilian.real.. : chr "5.5480" "5.4605" "5.5147" "5.2860" ...
## $ X.Canadian.dollar.. : chr "1.3816" "1.3706" "1.3698" "1.3467" ...
## $ X.Swiss.franc.. : chr "0.9790" "0.9751" "0.9844" "0.9834" ...
## $ X.Chinese.yuan.renminbi..: chr "7.3299" "7.2906" "7.3267" "7.2184" ...
## $ X.Cypriot.pound.. : chr "" "" "" "" ...
## $ X.Czech.koruna.. : chr "24.326" "24.289" "24.278" "24.361" ...
## $ X.Danish.krone.. : chr "7.4388" "7.4382" "7.4384" "7.4381" ...
## $ X.Estonian.kroon.. : chr "" "" "" "" ...
## $ X.UK.pound.sterling.. : chr "0.87455" "0.87513" "0.87538" "0.87298" ...
## $ X.Greek.drachma.. : chr "" "" "" "" ...
## $ X.Hong.Kong.dollar.. : chr "8.1430" "8.0852" "8.0758" "7.8128" ...
## $ X.Croatian.kuna.. : chr "7.5459" "7.5465" "7.5445" "7.5427" ...
## $ X.Hungarian.forint.. : chr "405.45" "407.28" "402.08" "400.95" ...
## $ X.Indonesian.rupiah.. : chr "16164.78" "16052.12" "15979.45" "15615.60" ...
## $ X.Israeli.shekel.. : chr "3.5694" "3.5410" "3.5255" "3.5453" ...
## $ X.Indian.rupee.. : chr "84.1304" "83.7779" "83.2253" "81.3058" ...
## $ X.Iceland.krona.. : num 150 150 149 148 147 ...
## $ X.Japanese.yen.. : chr "144.84" "144.86" "143.89" "145.47" ...
## $ X.Korean.won.. : chr "1365.61" "1369.32" "1359.20" "1373.96" ...
## $ X.Lithuanian.litas.. : chr "" "" "" "" ...
## $ X.Latvian.lats.. : chr "" "" "" "" ...
## $ X.Maltese.lira.. : chr "" "" "" "" ...
## $ X.Mexican.peso.. : chr "20.0795" "20.0985" "20.0239" "19.4562" ...
## $ X.Malaysian.ringgit.. : chr "4.7208" "4.7429" "4.7700" "4.6789" ...
## $ X.Norwegian.krone.. : chr "10.3570" "10.3143" "10.2635" "10.3615" ...
## $ X.New.Zealand.dollar.. : chr "1.6897" "1.6957" "1.7020" "1.6984" ...
## $ X.Philippine.peso.. : chr "59.532" "59.040" "59.106" "57.793" ...
## $ X.Polish.zloty.. : chr "4.7073" "4.6898" "4.6765" "4.7060" ...
## $ X.Romanian.leu.. : num 4.91 4.9 4.89 4.89 4.9 ...
## $ X.Russian.rouble.. : chr "" "" "" "" ...
## $ X.Swedish.krona.. : chr "10.8081" "10.7713" "10.7241" "10.8743" ...
## $ X.Singapore.dollar.. : chr "1.4238" "1.4177" "1.4199" "1.3963" ...
## $ X.Slovenian.tolar.. : chr "" "" "" "" ...
## $ X.Slovak.koruna.. : chr "" "" "" "" ...
## $ X.Thai.baht.. : chr "36.9390" "36.9780" "37.0880" "36.7000" ...
## $ X.Turkish.lira.. : num 19.4 19.2 19.1 18.5 18.7 ...
## $ X.US.dollar.. : chr "1.0404" "1.0319" "1.0308" "0.9954" ...
## $ X.South.African.rand.. : chr "17.8822" "17.8393" "17.7944" "17.6882" ...
Dari struktur diatas diketahui terdapat kolom/negara yang berupa
character, yang seharusnya berupa angka/numeric. Oleh
karena itu, dataset exchange harus diolah kembali sebelum
dilakukan pemodelan. Sebagai catatan, dataset exchange
memiliki \(6,177\) baris/observasi dan
\(41\) kolom/variabel. Proses tersebut
dilanjutkan ke R1 - Pemrosesan Data.
Informasi struktur diatas menandakan banyak sekali yang harus diolah
sebelum siap digunakan. Perubahan nama kolom dan tipe kolom merupakan
hal yang cukup terlihat jelas dari kilasan dataset
exchange. Sebelum memulai pra-pemrosesan data semua dataset
yang digunakan pada tahap ini disimpan dalam objek
exchange_r1.
exchange_r1 <- exchange
exchange_r1 |> head()Nama kolom di exchange bisa berbeda ketika pembacaan
dataset menggunakan read_csv(), tapi untuk dataset ini
digunakan read.csv(). Nama kolom disimpan dalam variabel
name_columns.
name_columns <- colnames(exchange_r1)
name_columns## [1] "Period.Unit." "X.Australian.dollar.."
## [3] "X.Bulgarian.lev.." "X.Brazilian.real.."
## [5] "X.Canadian.dollar.." "X.Swiss.franc.."
## [7] "X.Chinese.yuan.renminbi.." "X.Cypriot.pound.."
## [9] "X.Czech.koruna.." "X.Danish.krone.."
## [11] "X.Estonian.kroon.." "X.UK.pound.sterling.."
## [13] "X.Greek.drachma.." "X.Hong.Kong.dollar.."
## [15] "X.Croatian.kuna.." "X.Hungarian.forint.."
## [17] "X.Indonesian.rupiah.." "X.Israeli.shekel.."
## [19] "X.Indian.rupee.." "X.Iceland.krona.."
## [21] "X.Japanese.yen.." "X.Korean.won.."
## [23] "X.Lithuanian.litas.." "X.Latvian.lats.."
## [25] "X.Maltese.lira.." "X.Mexican.peso.."
## [27] "X.Malaysian.ringgit.." "X.Norwegian.krone.."
## [29] "X.New.Zealand.dollar.." "X.Philippine.peso.."
## [31] "X.Polish.zloty.." "X.Romanian.leu.."
## [33] "X.Russian.rouble.." "X.Swedish.krona.."
## [35] "X.Singapore.dollar.." "X.Slovenian.tolar.."
## [37] "X.Slovak.koruna.." "X.Thai.baht.."
## [39] "X.Turkish.lira.." "X.US.dollar.."
## [41] "X.South.African.rand.."
Strategi dalam membuat nama baru adalah seluruh nama kolom berhuruf
kecil semua dengan pemisahnya menggunakan titik. Jadi karakter seperti
X. dihilangkan, dan .. dihapus juga. Proses
tersebut dilakukan menggunakan str_replace() dan
str_to_lower(). Nama baru kolom disimpan dalam variabel
newname_columns. Berikut nama baru kolom.
newname_columns <- name_columns |>
str_replace("^X\\.", "") |>
str_replace("\\.+$", "") |>
str_to_lower()
newname_columns## [1] "period.unit" "australian.dollar" "bulgarian.lev"
## [4] "brazilian.real" "canadian.dollar" "swiss.franc"
## [7] "chinese.yuan.renminbi" "cypriot.pound" "czech.koruna"
## [10] "danish.krone" "estonian.kroon" "uk.pound.sterling"
## [13] "greek.drachma" "hong.kong.dollar" "croatian.kuna"
## [16] "hungarian.forint" "indonesian.rupiah" "israeli.shekel"
## [19] "indian.rupee" "iceland.krona" "japanese.yen"
## [22] "korean.won" "lithuanian.litas" "latvian.lats"
## [25] "maltese.lira" "mexican.peso" "malaysian.ringgit"
## [28] "norwegian.krone" "new.zealand.dollar" "philippine.peso"
## [31] "polish.zloty" "romanian.leu" "russian.rouble"
## [34] "swedish.krona" "singapore.dollar" "slovenian.tolar"
## [37] "slovak.koruna" "thai.baht" "turkish.lira"
## [40] "us.dollar" "south.african.rand"
Nama baru tersebut diterapkan ke dataset exchange_r1 dan
disimpan dalam objek baru bernama exchange_r1_newname.
exchange_r1_newname <- exchange_r1 |>
setNames(newname_columns)
exchange_r1_newname |> head()Dan berikut secara sekilas data exchange_r1_newname.
exchange_r1_newname |>
glimpse()## Rows: 6,177
## Columns: 41
## $ period.unit <chr> "2022-11-15", "2022-11-14", "2022-11-11", "2022-…
## $ australian.dollar <chr> "1.5415", "1.5427", "1.5459", "1.5525", "1.5538"…
## $ bulgarian.lev <chr> "1.9558", "1.9558", "1.9558", "1.9558", "1.9558"…
## $ brazilian.real <chr> "5.5480", "5.4605", "5.5147", "5.2860", "5.1947"…
## $ canadian.dollar <chr> "1.3816", "1.3706", "1.3698", "1.3467", "1.3501"…
## $ swiss.franc <chr> "0.9790", "0.9751", "0.9844", "0.9834", "0.9880"…
## $ chinese.yuan.renminbi <chr> "7.3299", "7.2906", "7.3267", "7.2184", "7.2813"…
## $ cypriot.pound <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ czech.koruna <chr> "24.326", "24.289", "24.278", "24.361", "24.337"…
## $ danish.krone <chr> "7.4388", "7.4382", "7.4384", "7.4381", "7.4382"…
## $ estonian.kroon <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ uk.pound.sterling <chr> "0.87455", "0.87513", "0.87538", "0.87298", "0.8…
## $ greek.drachma <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ hong.kong.dollar <chr> "8.1430", "8.0852", "8.0758", "7.8128", "7.8801"…
## $ croatian.kuna <chr> "7.5459", "7.5465", "7.5445", "7.5427", "7.5425"…
## $ hungarian.forint <chr> "405.45", "407.28", "402.08", "400.95", "403.53"…
## $ indonesian.rupiah <chr> "16164.78", "16052.12", "15979.45", "15615.60", …
## $ israeli.shekel <chr> "3.5694", "3.5410", "3.5255", "3.5453", "3.5621"…
## $ indian.rupee <chr> "84.1304", "83.7779", "83.2253", "81.3058", "81.…
## $ iceland.krona <dbl> 149.9, 150.3, 148.7, 147.5, 146.7, 146.3, 145.9,…
## $ japanese.yen <chr> "144.84", "144.86", "143.89", "145.47", "146.82"…
## $ korean.won <chr> "1365.61", "1369.32", "1359.20", "1373.96", "136…
## $ lithuanian.litas <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ latvian.lats <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ maltese.lira <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ mexican.peso <chr> "20.0795", "20.0985", "20.0239", "19.4562", "19.…
## $ malaysian.ringgit <chr> "4.7208", "4.7429", "4.7700", "4.6789", "4.7098"…
## $ norwegian.krone <chr> "10.3570", "10.3143", "10.2635", "10.3615", "10.…
## $ new.zealand.dollar <chr> "1.6897", "1.6957", "1.7020", "1.6984", "1.7033"…
## $ philippine.peso <chr> "59.532", "59.040", "59.106", "57.793", "58.236"…
## $ polish.zloty <chr> "4.7073", "4.6898", "4.6765", "4.7060", "4.7010"…
## $ romanian.leu <dbl> 4.9116, 4.9043, 4.8940, 4.8913, 4.9045, 4.8978, …
## $ russian.rouble <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ swedish.krona <chr> "10.8081", "10.7713", "10.7241", "10.8743", "10.…
## $ singapore.dollar <chr> "1.4238", "1.4177", "1.4199", "1.3963", "1.4061"…
## $ slovenian.tolar <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ slovak.koruna <chr> "", "", "", "", "", "", "", "", "", "", "", "", …
## $ thai.baht <chr> "36.9390", "36.9780", "37.0880", "36.7000", "36.…
## $ turkish.lira <dbl> 19.3608, 19.1923, 19.0987, 18.5100, 18.6728, 18.…
## $ us.dollar <chr> "1.0404", "1.0319", "1.0308", "0.9954", "1.0039"…
## $ south.african.rand <chr> "17.8822", "17.8393", "17.7944", "17.6882", "17.…
Setelah nama kolom sudah dibersihkan, bisa dilanjutkan untuk mengubah tipe data setiap kolomnya.
Melihat informasi sekilas mengenai dataset
exchange_r1_newname. Terdapat dua jenis data yang berbeda
di dataset. Kolom pertama yaitu period.unit berupa tanggal
dengan format YYYY-MM-DD. Sedangkan kolom lainnya,
merupakan kolom numerik.
Kolom yang merupakan waktu yaitu period.unit. Berikut
sekilas data pada kolom periode.unit.
set.seed(41608481)
exchange_r1_newname$period.unit |> sample(size=10)## [1] "2021-12-30" "1999-10-13" "2013-07-15" "2001-12-14" "2019-07-25"
## [6] "2015-02-16" "2009-04-30" "2007-05-10" "2012-03-09" "2004-10-05"
Setelah mengetahui format YYYY-MM-DD, kolom tersebut
bisa dikonversi menggunakan library lubridate
dengan fungsi ymd(). Hasil perubahan tersebut disimpan
dalam bentuk objek baru bernama exchange_r1_date. Berikut
beberapa baris pertamanya.
exchange_r1_date <- exchange_r1_newname |>
mutate(period.unit = ymd(period.unit))
exchange_r1_date |> head()Untuk memudahkan membaca, dataset diurutkan berdasarkan tanggal.
exchange_r1_date <- exchange_r1_date |>
arrange(period.unit)
exchange_r1_date |> head()Kita lihat range waktu yang digunakan di
exchange_r1_date dengan summary() pada kolom
period.unit.
summary(exchange_r1_date$period.unit)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## "1999-01-04" "2004-12-03" "2010-11-04" "2010-11-20" "2016-11-04" "2022-11-15"
Setelah mengetahui tanggal dimulainya dan berakhirnya dataset. Akan
dicek apakah ada tanggal yang tidak terekam di dataset. Digunakan
seq.Date() untuk membuat range dari 4 Januari 1999
hingga 15 November 2022.
date_start <- exchange_r1_date$period.unit |> min()
date_end <- exchange_r1_date$period.unit |> max()
date_range <- seq.Date(date_start, date_end, by = "day")
date_log_exist <- date_range %in% exchange_r1_date$period.unit
any(!date_log_exist)## [1] TRUE
Ternyata dari koding diatas diketahui bahwa terdapat tanggal yang hilang. Berikut tanggal dimana observasi tidak tersedia.
date_missing <- date_range[!date_log_exist]
date_range_wday <- date_range |> wday(label=TRUE, abbr = FALSE) |> summary()
date_missing_wday <- date_missing |> wday(label=TRUE, abbr = FALSE) |> summary()
data.frame(date_range_wday, date_missing_wday) |>
mutate(missing_date_percent = date_missing_wday / date_range_wday * 100)Diketahui bahwa data pada hari Sabtu dan Minggu tidak direkam sama sekali. Sedangkan terdapat juga di hari lain yang hilang dalam dataset. Perlu diingat, hilangnya data ini fokus pada tanggal yang tidak tersedia pada dataset original dan bukan kehilangan data pada kolom lainnya.
Tanggal yang hilang pada exchange_r1_date dilengkapi
menggunakan fungsi pad(). Berikut prosesnya dan
pemeriksaannya setelah menggunakan fungsi pad() dan
disimpan dalam objek baru bernama
exchange_r1_date_complete.
exchange_r1_date_complete <- exchange_r1_date |>
pad(interval = "day")
all(date_range %in% exchange_r1_date_complete$period.unit)## [1] TRUE
Dari nilai TRUE diatas, menandakan bahwa setiap tanggal
pada range 4 Januari 1999 hingga 15 November 2022 sudah
terdapat baris/observasinya di objek
exchange_r1_date_complete. Dengan kata lain, tidak ada
tanggal yang hilang dalam objek tersebut. Berikut 8 baris pertama
dataset.
exchange_r1_date_complete |> head(8)Untuk sementara padding yang dilakukan diisi dengan nilai
NA, yang nanti akan diproses lebih lanjut sebelum masuk
eksplorasi data. Dan berikut informasi mengenai perubahan/penambahan
baris setelah padding.
data.frame(
info = c("baris/observasi", "kolom/variabel"),
nrow.date.original = exchange_r1 |> dim(),
nrow.date.complete = exchange_r1_date_complete |> dim()
) |> column_to_rownames("info") |>
mutate(
diff = nrow.date.complete - nrow.date.original,
diff_percent = diff / nrow.date.complete * 100
)Dari informasi diatas diketahui bahwa banyaknya baris yang
ditambahkan menggunakan padding sebanyak \(2,540\) baris atau sekitar \(29\%\) dari total baris lengkapnya data.
Untuk catatan banyaknya baris tersebut disimpan dalam variabel
total_padding.
total_padding <- nrow(exchange_r1_date_complete) - nrow(exchange_r1)Selain kolom period.unit, kolom lainnya merupakan kolom
numerik. Akan tetapi pada saat pembacaan read.csv() terjadi
coercing sehingga kolom tersebut berubah menjadi tipe data
character. Sebelum memaksakan kolom tersebut menjadi
numerik, diinginkan untuk mengidentifikasi apa yang terjadi dengan
dataset tersebut sehingga membuat kolom tersebut menjadi
character.
Berikut jumlah jenis kolom masing-masing dari dataset
exchange_r1_date_complete.
exchange_r1_date_complete |>
sapply(class) |> table()##
## character Date numeric
## 37 1 3
Diketahui ada \(37\) kolom yang
bertipe character dan hanya \(3\) yang numeric. Berikut informasi
mengenai tipe setiap kolomnya.
column_type_exchange <- exchange_r1_date_complete |>
sapply(class) |> as.data.frame() |> set_names("column.type") |>
arrange(column.type)
column_type_exchangeBerikut kolom yang berupa numerik dan tanggal.
column_type_exchange |>
filter(column.type %in% c("Date", "numeric"))Jadi untuk iceland.krona, romanian.leu, dan
turkish.lira sudah berupa numerik.
Pada bagian ini, diinginkan untuk memperoleh informasi kenapa
terjadinya coercion sehingga mengubah kolom tersebut menjadi
tipe character. Untuk evaluasi tersebut akan menggunakan
objek exchange_r1_coercion yang merupakan
exchange_r1_date_complete dengan nama baris
period.unit.
exchange_r1_coercion <- exchange_r1_date_complete |>
column_to_rownames("period.unit")
exchange_r1_coercion |> head()Berikut daftar karakter yang bukan merupakan angka di dataset
exchange_r1_coercion.
list_of_character <- exchange_r1_coercion |>
select_if(is_character) |>
lapply(
function (.) {
is_digits <- str_detect(., "[:digit:]")
is_na <- is.na(.)
not_digits <- !(is_digits | is_na)
row_not_digits <- .[not_digits]
row_unique <- row_not_digits |> unique()
}
)
list_of_character |> unlist() |> unique()## [1] "-" ""
Dari informasi diatas, karakter "-" merupakan penyebab
kenapa kolom tersebut diubah menjadi character. karakter
"" (karakter kosong) muncul dikarenakan terdapat karakter
dikolom tersebut dan terjadi coercion sehingga memaksakan nilai
yang kosong menjadi "" (character)). Berikut
dikolom mana saja karakter tersebut muncul.
list_of_character |>
lapply(\(.) {paste("[", ., "]", sep = "", collapse = ",")}) |>
as.data.frame() |> t() |> as.data.frame() |> setNames("not.digit")Dari informasi diatas, bisa diketahui juga bahwa kolom yang tidak
memiliki [] ($not.digit hanya memiliki nilai
[-]) diartikan tidak memiliki data yang kosong saat
pembacaan. Untuk menghitung tepat jumlah baris yang diisi dengan
"-", elemen yang "" akan dibuat
NA.
exchange_r1_coercion[exchange_r1_coercion == ""] <- NA
exchange_r1_coercion |> head()Dengan kode diatas maka nilai yang "" akan diubah
menjadi NA, sehingga karakter yang diidentifikasi penyebab
coercion itu adalah "-". Selanjutnya ingin
mengidentifikasi tanggal mana saja yang terjadi tidak ada data
(menggunakan indikator "-").
func_logi_dash <- function(.) {
is_dash <- (. == "-")
logi_dash <- is_dash |>
apply(1, any, na.rm = TRUE)
}
logi_dash <- exchange_r1_coercion |> func_logi_dash()
exchange_r1_coercion |> filter(logi_dash)Dari informasi diatas, terdapat \(63\) baris yang memiliki nilai
"-" (tidak ada). Berikut hari dimana data tersebut tidak
tersedia.
exchange_r1_coercion |> filter(logi_dash) |>
rownames() |> wday(label = TRUE, abbr = FALSE) |> table()##
## Sunday Monday Tuesday Wednesday Thursday Friday Saturday
## 0 22 9 5 7 20 0
Perlu diingat bahwa hari Sabtu dan Minggu, memang tidak direkam dan
tersedia di dataset original sama sekali, sehingga tidak muncul sama
sekali di dataset. Langkah berikutnya adalah mengubah nilai
"-" menjadi NA. Berikut hasil perubahannya di
objek exchange_r1_coercion.
exchange_r1_coercion[exchange_r1_coercion == "-"] <- NA
exchange_r1_coercion |> subset(logi_dash)Untuk memastikan tidak ada karakter yang bukan angka, diperiksa
kembali objek exchange_r1_coercion. Berikut hasil
pemeriksaannya.
exchange_r1_coercion |>
lapply(str_detect, pattern = "[:digit:]") |>
lapply(all, na.rm = TRUE) |>
unlist() |> all()## [1] TRUE
Dari hasil diatas, sudah dipastikan bahwa pada
exchange_r1_coercion seluruh isiannya merupakan angka. Oleh
karena itu, semua kolom karakter tersebut bisa diubah menjadi numeric
dengan fungsi as.numeric(). Hasil perubahan tersebut
disimpan dalam objek baru bernama exchange_r1_numeric.
exchange_r1_numeric <- exchange_r1_coercion |>
mutate_if(is_character, as.numeric)
exchange_r1_numeric |> str()## 'data.frame': 8717 obs. of 40 variables:
## $ australian.dollar : num 1.91 1.89 1.88 1.85 1.84 ...
## $ bulgarian.lev : num NA NA NA NA NA NA NA NA NA NA ...
## $ brazilian.real : num NA NA NA NA NA NA NA NA NA NA ...
## $ canadian.dollar : num 1.8 1.8 1.77 1.76 1.76 ...
## $ swiss.franc : num 1.62 1.61 1.61 1.62 1.61 ...
## $ chinese.yuan.renminbi: num NA NA NA NA NA NA NA NA NA NA ...
## $ cypriot.pound : num 0.582 0.582 0.582 0.582 0.582 ...
## $ czech.koruna : num 35.1 34.9 34.9 34.9 34.9 ...
## $ danish.krone : num 7.45 7.45 7.45 7.44 7.44 ...
## $ estonian.kroon : num 15.6 15.6 15.6 15.6 15.6 ...
## $ uk.pound.sterling : num 0.711 0.712 0.708 0.706 0.709 ...
## $ greek.drachma : num 327 325 325 324 324 ...
## $ hong.kong.dollar : num 9.13 9.13 9.1 9.01 9.03 ...
## $ croatian.kuna : num NA NA NA NA NA NA NA NA NA NA ...
## $ hungarian.forint : num 251 251 251 250 250 ...
## $ indonesian.rupiah : num 9434 9315 9338 9219 9322 ...
## $ israeli.shekel : num NA NA NA NA NA NA NA NA NA NA ...
## $ indian.rupee : num NA NA NA NA NA NA NA NA NA NA ...
## $ iceland.krona : num 81.5 81.5 81.5 81.1 81 ...
## $ japanese.yen : num 134 131 131 129 130 ...
## $ korean.won : num 1399 1373 1360 1337 1367 ...
## $ lithuanian.litas : num 4.72 4.72 4.7 4.65 4.66 ...
## $ latvian.lats : num 0.667 0.666 0.665 0.663 0.665 ...
## $ maltese.lira : num 0.443 0.443 0.442 0.441 0.442 ...
## $ mexican.peso : num 11.6 11.6 11.5 11.6 11.4 ...
## $ malaysian.ringgit : num 4.48 4.48 4.46 4.42 4.43 ...
## $ norwegian.krone : num 8.86 8.77 8.73 8.63 8.59 ...
## $ new.zealand.dollar : num 2.22 2.2 2.19 2.15 2.16 ...
## $ philippine.peso : num 45.5 44.7 44.9 44.4 44.3 ...
## $ polish.zloty : num 4.07 4.02 4.01 4.02 4.04 ...
## $ romanian.leu : num 1.31 1.32 1.32 1.31 1.31 ...
## $ russian.rouble : num 25.3 26.6 27.4 27 27.2 ...
## $ swedish.krona : num 9.47 9.4 9.3 9.18 9.16 ...
## $ singapore.dollar : num 1.96 1.97 1.97 1.94 1.95 ...
## $ slovenian.tolar : num 189 189 189 189 189 ...
## $ slovak.koruna : num 43 42.8 42.8 42.8 42.6 ...
## $ thai.baht : num 42.7 42.5 42.7 42.2 42.6 ...
## $ turkish.lira : num 0.372 0.373 0.372 0.37 0.372 ...
## $ us.dollar : num 1.18 1.18 1.17 1.16 1.17 ...
## $ south.african.rand : num 6.94 6.8 6.73 6.83 6.79 ...
Proses berikutnya adalah mengevaluasi data yang hilang
(NA).
Sebelum mengisi data yang hilang, sebaiknya di eksplorasi terlebih
dahulu mengenai informasi hilangnya data. Dataset yang digunakan adalah
objek exchange_r1_numeric yang telah mengubah seluruh tipe
kolom menjadi numerik.
missing_val <- exchange_r1_numeric |> is.na() |> colSums()
missing_val |> as.data.frame() |>
mutate(missing_percentage = missing_val / nrow(exchange_r1_numeric) * 100) |>
arrange(missing_percentage |> desc())Dari informasi diatas nilai NA yang dibangkitkan dari
padding terhitung juga. Karena jumlah padding yang
dilakukan sudah diketahui pada tahap sebelumnya yaitu sebanyak \(2,540\) baris (disimpan dalam variabel
total_padding). Maka baris yang hilang dikurangi jumalh
tersebut untuk memastikan banyaknya data yang hilang ketika tidak
dilakukan padding atau hilangnya data aktualnya.
missing_val_actual <- missing_val |> as.data.frame() |>
mutate(
missing_val_actual = missing_val - total_padding,
percentage_missing_actual = missing_val_actual / (nrow(exchange_r1_numeric) - total_padding) * 100
) |>
arrange(percentage_missing_actual |> desc())
missing_val_actualBerikut visualisasinya agar memudahkan melihat perbandingannya.
missing_val_actual |>
rownames_to_column("currency") |>
ggplot(aes(x = fct_reorder(currency, missing_val_actual), y = missing_val_actual)) +
geom_col(aes(fill = percentage_missing_actual)) +
scale_fill_gradient(low = "green", high = "black") +
theme_bw() +
labs(
title = "Hilangnya Data (Aktual)",
x = "Mata Uang",
y = "Jumlah Baris yang Hilang",
fill = "Persen Hilang"
) +
coord_flip()Banyaknya Baris yang Hilang (Aktual)
Dari informasi diatas diambil kesimpulan untuk mengambil beberapa
kolom saja yang memiliki kelengkapan data yang lebih baik. Dari
eksplorasi diatas, diambil keputusan untuk mengambil kolom yang memiliki
data yang hilang aktual kurang dari \(100\). Kolom terpilih disimpan dalam
variabel selected_country.
selected_country <- missing_val_actual |>
filter(missing_val_actual <= 100) |>
rownames()
selected_country## [1] "australian.dollar" "canadian.dollar" "swiss.franc"
## [4] "czech.koruna" "danish.krone" "uk.pound.sterling"
## [7] "hong.kong.dollar" "hungarian.forint" "indonesian.rupiah"
## [10] "japanese.yen" "korean.won" "mexican.peso"
## [13] "malaysian.ringgit" "norwegian.krone" "new.zealand.dollar"
## [16] "philippine.peso" "polish.zloty" "romanian.leu"
## [19] "swedish.krona" "singapore.dollar" "thai.baht"
## [22] "turkish.lira" "us.dollar" "south.african.rand"
Kolom-kolom yang terpilih disimpan dalam bentuk objek baru bernama
exchange_r1_selected. Berikut kilasan dataset.
exchange_r1_selected <- exchange_r1_numeric |>
select(all_of(selected_country))
exchange_r1_selected |> glimpse()## Rows: 8,717
## Columns: 24
## $ australian.dollar <dbl> 1.9100, 1.8944, 1.8820, 1.8474, 1.8406, NA, NA, 1.8…
## $ canadian.dollar <dbl> 1.8004, 1.7965, 1.7711, 1.7602, 1.7643, NA, NA, 1.7…
## $ swiss.franc <dbl> 1.6168, 1.6123, 1.6116, 1.6165, 1.6138, NA, NA, 1.6…
## $ czech.koruna <dbl> 35.107, 34.917, 34.850, 34.886, 34.938, NA, NA, 35.…
## $ danish.krone <dbl> 7.4501, 7.4495, 7.4452, 7.4431, 7.4433, NA, NA, 7.4…
## $ uk.pound.sterling <dbl> 0.71110, 0.71220, 0.70760, 0.70585, 0.70940, NA, NA…
## $ hong.kong.dollar <dbl> 9.1332, 9.1341, 9.1010, 9.0131, 9.0302, NA, NA, 8.9…
## $ hungarian.forint <dbl> 251.48, 250.80, 250.67, 250.09, 250.15, NA, NA, 249…
## $ indonesian.rupiah <dbl> 9433.61, 9314.51, 9337.68, 9218.77, 9321.63, NA, NA…
## $ japanese.yen <dbl> 133.73, 130.96, 131.42, 129.43, 130.09, NA, NA, 126…
## $ korean.won <dbl> 1398.59, 1373.01, 1359.54, 1337.16, 1366.73, NA, NA…
## $ mexican.peso <dbl> 11.6446, 11.5960, 11.4705, 11.5511, 11.4414, NA, NA…
## $ malaysian.ringgit <dbl> 4.4798, 4.4805, 4.4637, 4.4203, 4.4295, NA, NA, 4.3…
## $ norwegian.krone <dbl> 8.8550, 8.7745, 8.7335, 8.6295, 8.5900, NA, NA, 8.5…
## $ new.zealand.dollar <dbl> 2.2229, 2.2011, 2.1890, 2.1531, 2.1557, NA, NA, 2.1…
## $ philippine.peso <dbl> 45.510, 44.745, 44.872, 44.436, 44.295, NA, NA, 43.…
## $ polish.zloty <dbl> 4.0712, 4.0245, 4.0065, 4.0165, 4.0363, NA, NA, 4.0…
## $ romanian.leu <dbl> 1.3111, 1.3168, 1.3168, 1.3092, 1.3143, NA, NA, 1.2…
## $ swedish.krona <dbl> 9.4696, 9.4025, 9.3050, 9.1800, 9.1650, NA, NA, 9.0…
## $ singapore.dollar <dbl> 1.9554, 1.9655, 1.9699, 1.9436, 1.9537, NA, NA, 1.9…
## $ thai.baht <dbl> 42.6799, 42.5048, 42.6949, 42.1678, 42.5590, NA, NA…
## $ turkish.lira <dbl> 0.3723, 0.3728, 0.3722, 0.3701, 0.3718, NA, NA, 0.3…
## $ us.dollar <dbl> 1.1789, 1.1790, 1.1743, 1.1632, 1.1659, NA, NA, 1.1…
## $ south.african.rand <dbl> 6.9358, 6.7975, 6.7307, 6.8283, 6.7855, NA, NA, 6.7…
Dari dataset tersebut bisa dilanjutkan ke pengisian data yang hilang.
Dataset exchange_r1_selected diperiksa nilai data yang
hilangnya. Dari narasi diatas diketahui, hari Sabtu dan Minggu, memang
tidak tersedia datanya. Sehingga, observasi tersebut harus diisi jika
menginginkan dataset yang kontinyu dengan interval waktu dalam bentuk
harian. Berikut baris yang hilang dan disimpan dalam bentuk
data.frame. Dan berikut jumlah hari yang hilang setiap
weekday.
exchange_r1_missing <- exchange_r1_selected |>
filter(exchange_r1_selected |> is.na() |> apply(1, all)) |>
rownames_to_column("period.unit") |>
mutate(
period.unit = ymd(period.unit)
)
date_missing <- exchange_r1_missing$period.unit
date_missing |> wday(label = TRUE, abbr = FALSE) |> table()##
## Sunday Monday Tuesday Wednesday Thursday Friday Saturday
## 1245 36 15 13 12 36 1245
Data yang hilang akan diisi dengan metode na.fill()
dengan menggunakan fill = "extend". Data yang telah diisi
disimpan pada objek exchange_r1_fill. Hal ini dipilih
dikarenakan nilai mata uang bersifat kontinyu dari sebelum dan
sesudahnya. Sehingga pengisian nilai harus diisi berdasarkan nilai
terdekatnya.
exchange_r1_fill <- exchange_r1_selected |>
mutate_all(na.fill, fill = "extend")
exchange_r1_fill |> glimpse()## Rows: 8,717
## Columns: 24
## $ australian.dollar <dbl> 1.910000, 1.894400, 1.882000, 1.847400, 1.840600, 1…
## $ canadian.dollar <dbl> 1.800400, 1.796500, 1.771100, 1.760200, 1.764300, 1…
## $ swiss.franc <dbl> 1.616800, 1.612300, 1.611600, 1.616500, 1.613800, 1…
## $ czech.koruna <dbl> 35.10700, 34.91700, 34.85000, 34.88600, 34.93800, 3…
## $ danish.krone <dbl> 7.450100, 7.449500, 7.445200, 7.443100, 7.443300, 7…
## $ uk.pound.sterling <dbl> 0.7111000, 0.7122000, 0.7076000, 0.7058500, 0.70940…
## $ hong.kong.dollar <dbl> 9.133200, 9.134100, 9.101000, 9.013100, 9.030200, 9…
## $ hungarian.forint <dbl> 251.4800, 250.8000, 250.6700, 250.0900, 250.1500, 2…
## $ indonesian.rupiah <dbl> 9433.610, 9314.510, 9337.680, 9218.770, 9321.630, 9…
## $ japanese.yen <dbl> 133.7300, 130.9600, 131.4200, 129.4300, 130.0900, 1…
## $ korean.won <dbl> 1398.590, 1373.010, 1359.540, 1337.160, 1366.730, 1…
## $ mexican.peso <dbl> 11.64460, 11.59600, 11.47050, 11.55110, 11.44140, 1…
## $ malaysian.ringgit <dbl> 4.479800, 4.480500, 4.463700, 4.420300, 4.429500, 4…
## $ norwegian.krone <dbl> 8.855000, 8.774500, 8.733500, 8.629500, 8.590000, 8…
## $ new.zealand.dollar <dbl> 2.222900, 2.201100, 2.189000, 2.153100, 2.155700, 2…
## $ philippine.peso <dbl> 45.51000, 44.74500, 44.87200, 44.43600, 44.29500, 4…
## $ polish.zloty <dbl> 4.071200, 4.024500, 4.006500, 4.016500, 4.036300, 4…
## $ romanian.leu <dbl> 1.311100, 1.316800, 1.316800, 1.309200, 1.314300, 1…
## $ swedish.krona <dbl> 9.469600, 9.402500, 9.305000, 9.180000, 9.165000, 9…
## $ singapore.dollar <dbl> 1.955400, 1.965500, 1.969900, 1.943600, 1.953700, 1…
## $ thai.baht <dbl> 42.67990, 42.50480, 42.69490, 42.16780, 42.55900, 4…
## $ turkish.lira <dbl> 0.3723000, 0.3728000, 0.3722000, 0.3701000, 0.37180…
## $ us.dollar <dbl> 1.178900, 1.179000, 1.174300, 1.163200, 1.165900, 1…
## $ south.african.rand <dbl> 6.935800, 6.797500, 6.730700, 6.828300, 6.785500, 6…
Dilakukan pengecekan ulang dengan anyNA().
anyNA(exchange_r1_fill)## [1] FALSE
Menghasilkan FALSE yang artinya data sudah lengkap
(tidak terdapat data yang kosong/hilang). Setelah ini dataset
exchange_r1_fill, bisa dilanjutkan ke tahap R2 -
Eksplorasi Data.
Setelah memastikan dataset sudah lengkap dan memenuhi kriteria
kelengkapan data, dilanjutkan dengan mengeksplorasi dataset ini.
Eksplorasi ini bisa berupa statistik deskriptif ataupun analisis terkait
jenis data deret waktu (time series). Pada tahap ini dataset
disimpan sebagai objek baru bernama exchange_r2 yang
merupakan objek exchange_r1_fill. Kolom
period.unit dimunculkan kembali dari nama baris dan diubah
sebagai jenis data waktu.
exchange_r2 <- exchange_r1_fill |>
rownames_to_column("period.unit") |>
mutate(period.unit = ymd(period.unit))
exchange_r2 |> head()Langkah yang akan dilakukan dalam mengeksplorasi dataset dimulai dari deskripsi umum mengenai dataset, statistik dataset, kemudian diakhiri dengan eksplorasi sebagai data deret waktu.
Dataset yang digunakan adalah exchange_r2. Deskrpsi yang
dimaksud adalah eksplorasi dini terkait jumlah observasi/baris, jumlah
variabel/kolom, dan periode datasetnya. Berikut kilasan
exchange_r2.
exchange_r2 |> glimpse()## Rows: 8,717
## Columns: 25
## $ period.unit <date> 1999-01-04, 1999-01-05, 1999-01-06, 1999-01-07, 19…
## $ australian.dollar <dbl> 1.910000, 1.894400, 1.882000, 1.847400, 1.840600, 1…
## $ canadian.dollar <dbl> 1.800400, 1.796500, 1.771100, 1.760200, 1.764300, 1…
## $ swiss.franc <dbl> 1.616800, 1.612300, 1.611600, 1.616500, 1.613800, 1…
## $ czech.koruna <dbl> 35.10700, 34.91700, 34.85000, 34.88600, 34.93800, 3…
## $ danish.krone <dbl> 7.450100, 7.449500, 7.445200, 7.443100, 7.443300, 7…
## $ uk.pound.sterling <dbl> 0.7111000, 0.7122000, 0.7076000, 0.7058500, 0.70940…
## $ hong.kong.dollar <dbl> 9.133200, 9.134100, 9.101000, 9.013100, 9.030200, 9…
## $ hungarian.forint <dbl> 251.4800, 250.8000, 250.6700, 250.0900, 250.1500, 2…
## $ indonesian.rupiah <dbl> 9433.610, 9314.510, 9337.680, 9218.770, 9321.630, 9…
## $ japanese.yen <dbl> 133.7300, 130.9600, 131.4200, 129.4300, 130.0900, 1…
## $ korean.won <dbl> 1398.590, 1373.010, 1359.540, 1337.160, 1366.730, 1…
## $ mexican.peso <dbl> 11.64460, 11.59600, 11.47050, 11.55110, 11.44140, 1…
## $ malaysian.ringgit <dbl> 4.479800, 4.480500, 4.463700, 4.420300, 4.429500, 4…
## $ norwegian.krone <dbl> 8.855000, 8.774500, 8.733500, 8.629500, 8.590000, 8…
## $ new.zealand.dollar <dbl> 2.222900, 2.201100, 2.189000, 2.153100, 2.155700, 2…
## $ philippine.peso <dbl> 45.51000, 44.74500, 44.87200, 44.43600, 44.29500, 4…
## $ polish.zloty <dbl> 4.071200, 4.024500, 4.006500, 4.016500, 4.036300, 4…
## $ romanian.leu <dbl> 1.311100, 1.316800, 1.316800, 1.309200, 1.314300, 1…
## $ swedish.krona <dbl> 9.469600, 9.402500, 9.305000, 9.180000, 9.165000, 9…
## $ singapore.dollar <dbl> 1.955400, 1.965500, 1.969900, 1.943600, 1.953700, 1…
## $ thai.baht <dbl> 42.67990, 42.50480, 42.69490, 42.16780, 42.55900, 4…
## $ turkish.lira <dbl> 0.3723000, 0.3728000, 0.3722000, 0.3701000, 0.37180…
## $ us.dollar <dbl> 1.178900, 1.179000, 1.174300, 1.163200, 1.165900, 1…
## $ south.african.rand <dbl> 6.935800, 6.797500, 6.730700, 6.828300, 6.785500, 6…
exchange_r2$period.unit |> summary() |> strftime("%d %B %Y")## Min. 1st Qu. Median Mean
## "04 January 1999" "22 December 2004" "10 December 2010" "10 December 2010"
## 3rd Qu. Max.
## "27 November 2016" "15 November 2022"
exchange_r2 |> dim()## [1] 8717 25
Dari informasi diatas diketahui bahwa exchange_r2
memiliki \(8,717\) baris dan \(25\) kolom (\(24\) mata uang dengan \(1\) kolom waktu) yang dimulai dari \(\text{4 Januari 1999}\) sampai \(\text{15 November 2022}\). Pada tahap ini
diambil keputusan untuk mengambil tiga mata uang saja untuk eksplorasi
berikutnya sampai akhir. Mata uang yang digunakan antara lain
indonesian.rupiah, us.dollar,
japanese.yen. Kolom yang terpilih disimpan dalam objek
exchange_r2_selected.
exchange_r2_selected <- exchange_r2 |>
select(period.unit, indonesian.rupiah, us.dollar, japanese.yen)
exchange_r2_selected |> glimpse()## Rows: 8,717
## Columns: 4
## $ period.unit <date> 1999-01-04, 1999-01-05, 1999-01-06, 1999-01-07, 199…
## $ indonesian.rupiah <dbl> 9433.610, 9314.510, 9337.680, 9218.770, 9321.630, 92…
## $ us.dollar <dbl> 1.178900, 1.179000, 1.174300, 1.163200, 1.165900, 1.…
## $ japanese.yen <dbl> 133.7300, 130.9600, 131.4200, 129.4300, 130.0900, 12…
Mata uang yang terpilih disimpan dalam variabel
r2_selected.
r2_selected <- exchange_r2_selected |>
select(-period.unit) |>
colnames()Untuk tahap ini dan seterusnya akan menggunakan dataset
exchange_r2_selected. Berikut summary() dari
dataset.
exchange_r2_selected |>
select(-period.unit) |>
summary()## indonesian.rupiah us.dollar japanese.yen
## Min. : 6708 Min. :0.8252 Min. : 89.3
## 1st Qu.:11279 1st Qu.:1.0951 1st Qu.:117.1
## Median :12864 Median :1.1891 Median :128.7
## Mean :12986 Mean :1.1936 Mean :127.6
## 3rd Qu.:15412 3rd Qu.:1.3123 3rd Qu.:135.8
## Max. :18240 Max. :1.5990 Max. :169.8
Dari informasi diatas diketahui nilai minimum, kuartil
pertama/ketiga, median, rata-rata, dan maksimum. Nilai tiap kolom
terlihat memiliki rentang (range) yang berbeda-beda. Sehingga
jika dicoba untuk di plot distribusinya menggunakan boxplot
akan berbeda.
exchange_r2_selected |>
select(-period.unit) |>
boxplot()Boxplot Nilai Tukar
Salah satu cara untuk melihat perbandingan antar kolom dengan dilakukan normalisasi. Normalisasi yang digunakan adalah menggunakan minimum dan maksimumnya (minmax scale). Berikut boxplot yang serupa setelah normalisasi.
exchange_r2_minmax <- exchange_r2_selected |>
mutate_if(
is.numeric,
function(.) {
minvec <- min(.)
maxvec <- max(.)
normalize <- (. - minvec) / (maxvec - minvec)
}
)
exchange_r2_minmax |>
select(-period.unit) |>
boxplot()Boxplot Nilai Tukar (normalisasi)
Dari boxplot diatas, semua mata uang bisa dilihat
distribusinya secara sekaligus. Mata uang japanese.yen
memiliki beberapa potensi outlier. Sedangkan untuk
indonesia.rupiah dan us.dollar tidak
memilikinya. Hal tersebut bisa diinterpretasikan, bahwa pada
indonesian.rupiah maupun us.dollar tidak ada
lonjakan tajam yang diluar dari rata-rata maupun kuartilnya. Sedangkan
untuk japanese.yen diduga terdapat posisi dimana mata
uangnya yang berbeda dari seluruh observasi data lainnya.
exchange_r2_minmax |>
pivot_longer(cols = -period.unit, names_to = "currency", values_to = "rate") |>
arrange(currency) |>
ggplot(aes(x = period.unit, y = rate, color = currency)) +
geom_line()Perubahan Nilai Tukar Harian (Normalisasi)
Untuk eksplorasi data deret waktu, yang digunakan hanyalah mata uang
indonesian.rupiah.
exchange_r2_rupiah <- exchange_r2_selected |>
select(period.unit, indonesian.rupiah)
exchange_r2_rupiah |> glimpse()## Rows: 8,717
## Columns: 2
## $ period.unit <date> 1999-01-04, 1999-01-05, 1999-01-06, 1999-01-07, 199…
## $ indonesian.rupiah <dbl> 9433.610, 9314.510, 9337.680, 9218.770, 9321.630, 92…
Untuk eksplorasi berdasarkan jenis datanya, dibuat objek
ts_rupiah yang mengubah objek
exchange_r2_rupiah menjadi time series menggunakan
ts().
ts_rupiah <- ts(exchange_r2_rupiah$indonesian.rupiah, start = c(1999, 1), frequency = 365)Selanjutnya dilakukan decomposition untuk melihat
karakteristik dataset ts_rupiah.
Dekomposisi dilakukan menggunakan fungsi decompose()
yang membagi dataset menjadi tiga bagian utama yaitu trend,
seasonal, dan error / remainder. Berikut
objek dekomposisi decompose_rupiah beserta struktur
datanya.
decompose_rupiah <- ts_rupiah |> decompose()
decompose_rupiah |> str()## List of 6
## $ x : Time-Series [1:8717] from 1999 to 2023: 9434 9315 9338 9219 9322 ...
## $ seasonal: Time-Series [1:8717] from 1999 to 2023: 173 175 181 141 94 ...
## $ trend : Time-Series [1:8717] from 1999 to 2023: NA NA NA NA NA NA NA NA NA NA ...
## $ random : Time-Series [1:8717] from 1999 to 2023: NA NA NA NA NA NA NA NA NA NA ...
## $ figure : num [1:365] 173 175 181 141 94 ...
## $ type : chr "additive"
## - attr(*, "class")= chr "decomposed.ts"
Didapatkan tiga komponen dekomposisi yaitu seasonal,
trend, dan random. Dan secara default
dataset termasuk additive time series. Berikut grafik
dekomposisi menggunakan autoplot().
decompose_rupiah |> autoplot()Dekomposisi Nilai Tukar Rupiah
Dari grafik dekomposisi diatas, terlihat bahwa hasil
decompose() mengeluarkan tiga komponen utamanya. Akan
tetapi, hasil diatas belum tentu sesuai dengan kenyataannya. Dan harus
dieksplorasi lebih lanjut.
Untuk pemodelan digunakan Holt Winters dan ARIMA. dataset yang
digunakan adalah ts_rupiah. Tapi sebelumnya dataset harus
dibagi menjadi dua bagian yaitu train set dan testing set.
window_selected <- 365
train_ts <- ts_rupiah |> head(-window_selected)
test_ts <- ts_rupiah |> tail(window_selected)Pemodelan Holt Winters dan ARIMA menggunakan holtwinter
dan stlm.
hw_rupiah <- HoltWinters(train_ts)
arima_rupiah <- stlm(train_ts, s.window = 365, method = "arima")Evaluasi
hw_forecast <- forecast(hw_rupiah, window_selected)
arima_forecast <- forecast(arima_rupiah, window_selected)accuracy(hw_forecast, test_ts)## ME RMSE MAE MPE MAPE MASE
## Training set 3.164765 121.6350 80.6686 0.02337438 0.6513953 0.0688837
## Test set -516.177619 910.2031 650.2115 -3.42822365 4.2676716 0.5552219
## ACF1 Theil's U
## Training set 0.5521309 NA
## Test set 0.9906554 14.43078
accuracy(arima_forecast, test_ts)## ME RMSE MAE MPE MAPE MASE
## Training set 0.7814501 75.46314 48.48109 0.004273649 0.4012051 0.04139847
## Test set -594.6595784 762.99467 624.46642 -3.911100785 4.0932986 0.53323790
## ACF1 Theil's U
## Training set -0.0001222072 NA
## Test set 0.9865063092 12.0606
train_ts |>
autoplot() +
autolayer(hw_rupiah$fitted[,'xhat'], series = "training") +
autolayer(hw_forecast, series = "forecast") +
autolayer(test_ts, series = "actual")Training dan Prediksi menggunakan Holt-Winters
train_ts |>
autoplot() +
autolayer(arima_rupiah$fitted, series = "training") +
autolayer(hw_forecast, series = "forecast") +
autolayer(test_ts, series = "actual")Training dan Prediksi menggunakan Holt-Winters
Berikut saran yang bisa diberikan:
TRUE karena memiliki komponen
:digit:, meski jika dilakukan as.numeric()
akan muncul peringatan dan menghasilkan nilai NA. Hal
tersebut dikarenakan penggunaan str_detect() dengan
pattern = "[:digit:]".class objek. Dalam lembar
kerja, objek missing_val merupakan list,
sedangkan missing_val_actual merupakan
data.frame. Untuk konsistensi dan memudahkan
troubleshooting, sebaiknya dilakukan penamaan dan konsistensi
tipe objeknya.