library(tidyverse)
library(readxl)
library(ggplot2)
library(lubridate)
library(writexl)
library(magrittr)

1, Tidy Data

Here is the history data about monthly electricity demand satisfied by non-renewable energy technologies from 2013 to 2017, which are downloaded from Malta National Statistics Office.

head(ti)
ti %>%
  mutate(month = month(.$date)) %>%
  mutate(year = as.character(year(.$date))) %>%
  ggplot() +
    geom_line(mapping = aes(x = month, y = demand, color = year))

ti %>%
  ggplot() +
    geom_line(mapping = aes(x = date, y = demand)) +
    labs(
      title = "Monthly Electricity Demand from Non-Renewables",
      subtitle = "in Malta from 2013 to 2017",
      y = "Electricity Demand from Non-Renewables (MWh)",
      x = "Index (Month)"
      )

2, Decomposition

ts <-
  ts(ti$demand, frequency = 12)

li_decomp <-
  ts %>%
  decompose(type = c("multiplicative"), filter = NULL)

The seasonal compoents is the most important part, and it’s shown in the following figure.

ts <-
  ts(ti$demand, frequency = 12)
li_decomp <-
  ts %>%
  decompose(type = c("multiplicative"), filter = NULL)
ti %>%
  mutate(coef_decomp = as.numeric(li_decomp$seasonal)) %>%
  ggplot() +
    geom_line(mapping = aes(x = date, y = coef_decomp)) +
    labs(
      title = "Seasonal Coefficients of Decomposition",
      subtitle = "for Monthly Non-Re E-Demand in Malta from 2013 to 2017",
      y = "Seasonal Coefficients",
      x = "Index (Month)"
      )

The random component is checked using ACF and PACF.

acf(li_decomp$random, na.action = na.pass)

pacf(li_decomp$random, na.action = na.pass)

We can say that the random component can be treated as white noise.

4, Forecast

trend_new <- predict(
  lm_trend, newdata = data.frame(
    x = c((length(df_trend$x) + 1):(length(df_trend$x) + 12 * 20))
    )
  )
seasonal_new <- rep(li_decomp$seasonal[1:12], 20)
ti_new <-
  tibble(
    index = 1:(12 * 20), demand = trend_new * seasonal_new  # multiplicative
    ) %>%
  mutate(date = rep(ti$date[60], length(.$index)))
for (i in 1:length(ti_new$index)) {
  month(ti_new$date[i]) = i + month(ti$date[60])
}
ti_new %<>%
  select(date, demand) %>%
  mutate(observation = rep(FALSE, length(.$date)))
ti_fore <- ti %>%
  bind_rows(ti_new)
ti_fore %>%
  ggplot() +
    geom_line(mapping = aes(x = date, y = demand, color = observation)) +
    labs(title = "Forecast of Monthly Electricity Demand from Non-Renewables",
         subtitle = "in Malta from 2018 to 2037 using Data from 2013 to 2017",
         y = "Electricity Demand from Non-Renewables (MWh)",
         x = "Index (Month)")

LS0tCnRpdGxlOiAiRm9yZWNhc3Qgb2YgRWxlY3RyaWNpdHkgRGVtYW5kIGluIE1hbHRhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQpybShsaXN0ID0gbHMoKSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbGxhcHNlID0gVFJVRSwKICBjb21tZW50ID0gIiM+IiwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcuYXNwID0gOS8xNiwKICBmaWcud2lkdGggPSAxMCwKICB3YXJuaW5nID0gRkFMU0UKKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkod3JpdGV4bCkKbGlicmFyeShtYWdyaXR0cikKYGBgCgojIyAxLCBUaWR5IERhdGEKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQp0aSA8LQogIHJlYWR4bDo6cmVhZF9leGNlbCgifi9HaXRIdWIvRW5lcmd5U3RvcmFnZS9kZW1hbmQtZm9yZWNhc3QvZGVtYW5kLXdpdGhvdXQtcmVuZXdhYmxlcy54bHN4IikgJT4lCiAgbXV0YXRlKG1vbnRoID0gMToxMikgJT4lCiAgZ2F0aGVyKC1tb250aCwga2V5ID0gInllYXIiLCB2YWx1ZSA9ICJkZW1hbmQiKSAlPiUKICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoLiR5ZWFyKSkgJT4lCiAgbXV0YXRlKGRhdGUgPSB5bWQoc3ByaW50ZigiJWQtJTAyZC0wMSIsIC4keWVhciwgLiRtb250aCkpKSAlPiUKICBtdXRhdGUob2JzZXJ2YXRpb24gPSByZXAoVFJVRSwgbGVuZ3RoKGRhdGUpKSkgJT4lCiAgc2VsZWN0KGRhdGUsIGRlbWFuZCwgb2JzZXJ2YXRpb24pCmBgYAoKSGVyZSBpcyB0aGUgaGlzdG9yeSBkYXRhIGFib3V0IG1vbnRobHkgZWxlY3RyaWNpdHkgZGVtYW5kIHNhdGlzZmllZCBieSBub24tcmVuZXdhYmxlIGVuZXJneSB0ZWNobm9sb2dpZXMgZnJvbSAyMDEzIHRvIDIwMTcsIHdoaWNoIGFyZSBkb3dubG9hZGVkIGZyb20gTWFsdGEgTmF0aW9uYWwgU3RhdGlzdGljcyBPZmZpY2UuCgpgYGB7cn0KaGVhZCh0aSkKYGBgCgpgYGB7cn0KdGkgJT4lCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoLiRkYXRlKSkgJT4lCiAgbXV0YXRlKHllYXIgPSBhcy5jaGFyYWN0ZXIoeWVhciguJGRhdGUpKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IG1vbnRoLCB5ID0gZGVtYW5kLCBjb2xvciA9IHllYXIpKQpgYGAKCmBgYHtyfQp0aSAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IGRlbWFuZCkpICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gIk1vbnRobHkgRWxlY3RyaWNpdHkgRGVtYW5kIGZyb20gTm9uLVJlbmV3YWJsZXMiLAogICAgICBzdWJ0aXRsZSA9ICJpbiBNYWx0YSBmcm9tIDIwMTMgdG8gMjAxNyIsCiAgICAgIHkgPSAiRWxlY3RyaWNpdHkgRGVtYW5kIGZyb20gTm9uLVJlbmV3YWJsZXMgKE1XaCkiLAogICAgICB4ID0gIkluZGV4IChNb250aCkiCiAgICAgICkKYGBgCgojIyAyLCBEZWNvbXBvc2l0aW9uCgpgYGB7cn0KdHMgPC0KICB0cyh0aSRkZW1hbmQsIGZyZXF1ZW5jeSA9IDEyKQoKbGlfZGVjb21wIDwtCiAgdHMgJT4lCiAgZGVjb21wb3NlKHR5cGUgPSBjKCJtdWx0aXBsaWNhdGl2ZSIpLCBmaWx0ZXIgPSBOVUxMKQpgYGAKClRoZSBzZWFzb25hbCBjb21wb2VudHMgaXMgdGhlIG1vc3QgaW1wb3J0YW50IHBhcnQsIGFuZCBpdCdzIHNob3duIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLgoKYGBge3J9CnRpICU+JQogIG11dGF0ZShjb2VmX2RlY29tcCA9IGFzLm51bWVyaWMobGlfZGVjb21wJHNlYXNvbmFsKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUsIHkgPSBjb2VmX2RlY29tcCkpICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gIlNlYXNvbmFsIENvZWZmaWNpZW50cyBvZiBEZWNvbXBvc2l0aW9uIiwKICAgICAgc3VidGl0bGUgPSAiZm9yIE1vbnRobHkgTm9uLVJlIEUtRGVtYW5kIGluIE1hbHRhIGZyb20gMjAxMyB0byAyMDE3IiwKICAgICAgeSA9ICJTZWFzb25hbCBDb2VmZmljaWVudHMiLAogICAgICB4ID0gIkluZGV4IChNb250aCkiCiAgICAgICkKYGBgCgpUaGUgcmFuZG9tIGNvbXBvbmVudCBpcyBjaGVja2VkIHVzaW5nIEFDRiBhbmQgUEFDRi4KCmBgYHtyfQphY2YobGlfZGVjb21wJHJhbmRvbSwgbmEuYWN0aW9uID0gbmEucGFzcykKYGBgCgpgYGB7cn0KcGFjZihsaV9kZWNvbXAkcmFuZG9tLCBuYS5hY3Rpb24gPSBuYS5wYXNzKQpgYGAKCldlIGNhbiBzYXkgdGhhdCB0aGUgcmFuZG9tIGNvbXBvbmVudCBjYW4gYmUgdHJlYXRlZCBhcyB3aGl0ZSBub2lzZS4KCiMjIDMsIE1vZGVsIFRyZW5kaW5nIENvbXBvbmVudCB1c2luZyBMaW5lYXIgUmVncmVzc2lvbgoKYGBge3J9CmFjZihsaV9kZWNvbXAkdHJlbmQsIG5hLmFjdGlvbiA9IG5hLnBhc3MpCmBgYAoKYGBge3J9CnBhY2YobGlfZGVjb21wJHRyZW5kLCBuYS5hY3Rpb24gPSBuYS5wYXNzKQpgYGAKCmBgYHtyfQphcmltYShhcy50cyhsaV9kZWNvbXAkdHJlbmQpKQpgYGAKClRob3VnaCB0aGVyZSBpcyBzb21lIGNvcnJlbGF0aW9uIGluIEFDRiBvZiB0aGUgdHJlbmRpbmcgY29tcG9uZW50LCB0aGUgImFyaW1hIiBmdW5jdGlvbiBzaG93cyB0aGF0IG5vIGJlbmVmaXQsIHdoaWNoIGlzIHRoZSBzYW1lIGFzIGV4cGVjdGVkIGJlY3Vhc2UgdGhlIGxlbmd0aCBvZiB0aGUgc2FtcGxpbmcgaXMgb25lIG1vbnRoLiBTbyBsaW5lYXIgcmVncmVzc2lvbiBpcyB1c2VkLgoKYGBge3J9CmRmX3RyZW5kIDwtIGRhdGEuZnJhbWUoeCA9IDE6bGVuZ3RoKGxpX2RlY29tcCR0cmVuZCksIHkgPSBsaV9kZWNvbXAkdHJlbmQpCmxtX3RyZW5kIDwtIGxtKHkgfiB4LCBkZl90cmVuZCkKCnBhcihtZnJvdyA9IGMoMiwgMikpCnBsb3QobG1fdHJlbmQpCmBgYAoKVGhlIGlsbHVzdHJhdGlvbiBvZiBsaW5lYXIgcmVncmVzc2lvbiBhbmFkIGZvcmVjYXN0IG9mIHRyZW5kaW5nIGNvbXBvbmVudCBpcyBzaG93biBpbiB0aGUgZm9sbG93aW5nIGZpZ3VyZS4KCmBgYHtyfQpwYXIobWZyb3cgPSBjKDEsIDEpKQpwbG90KAogIHByZWRpY3QoCiAgICBsbV90cmVuZCwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoeCA9IGMoMToobGVuZ3RoKGRmX3RyZW5kJHgpICsgMTIgKiAxMCkpKQogICAgKQogICkKbGluZXMoZGZfdHJlbmQkeCwgZGZfdHJlbmQkeSkKYGBgCgojIyA0LCBGb3JlY2FzdAoKYGBge3J9CnRyZW5kX25ldyA8LSBwcmVkaWN0KAogIGxtX3RyZW5kLCBuZXdkYXRhID0gZGF0YS5mcmFtZSgKICAgIHggPSBjKChsZW5ndGgoZGZfdHJlbmQkeCkgKyAxKToobGVuZ3RoKGRmX3RyZW5kJHgpICsgMTIgKiAyMCkpCiAgICApCiAgKQpzZWFzb25hbF9uZXcgPC0gcmVwKGxpX2RlY29tcCRzZWFzb25hbFsxOjEyXSwgMjApCgp0aV9uZXcgPC0KICB0aWJibGUoCiAgICBpbmRleCA9IDE6KDEyICogMjApLCBkZW1hbmQgPSB0cmVuZF9uZXcgKiBzZWFzb25hbF9uZXcgICMgbXVsdGlwbGljYXRpdmUKICAgICkgJT4lCiAgbXV0YXRlKGRhdGUgPSByZXAodGkkZGF0ZVs2MF0sIGxlbmd0aCguJGluZGV4KSkpCgpmb3IgKGkgaW4gMTpsZW5ndGgodGlfbmV3JGluZGV4KSkgewogIG1vbnRoKHRpX25ldyRkYXRlW2ldKSA9IGkgKyBtb250aCh0aSRkYXRlWzYwXSkKfQoKdGlfbmV3ICU8PiUKICBzZWxlY3QoZGF0ZSwgZGVtYW5kKSAlPiUKICBtdXRhdGUob2JzZXJ2YXRpb24gPSByZXAoRkFMU0UsIGxlbmd0aCguJGRhdGUpKSkKCnRpX2ZvcmUgPC0gdGkgJT4lCiAgYmluZF9yb3dzKHRpX25ldykKCnRpX2ZvcmUgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUsIHkgPSBkZW1hbmQsIGNvbG9yID0gb2JzZXJ2YXRpb24pKSArCiAgICBsYWJzKHRpdGxlID0gIkZvcmVjYXN0IG9mIE1vbnRobHkgRWxlY3RyaWNpdHkgRGVtYW5kIGZyb20gTm9uLVJlbmV3YWJsZXMiLAogICAgICAgICBzdWJ0aXRsZSA9ICJpbiBNYWx0YSBmcm9tIDIwMTggdG8gMjAzNyB1c2luZyBEYXRhIGZyb20gMjAxMyB0byAyMDE3IiwKICAgICAgICAgeSA9ICJFbGVjdHJpY2l0eSBEZW1hbmQgZnJvbSBOb24tUmVuZXdhYmxlcyAoTVdoKSIsCiAgICAgICAgIHggPSAiSW5kZXggKE1vbnRoKSIpCmBgYAoK