Bu yazıda R Programlama dili ile, zaman serisi analizinde sıkça kullanılan Ayrıştırma Yöntemlerinden olan Toplamsal Ayrıştırma Yöntemini göreceğiz.

Verinin Tanımlanması ve Zaman Serisinin Oluşturulması

Veri

Analiz boyunca kullanılan veri, ABD Enerji Bilgi Yönetim İdaresi (eia) tarafından 1973-2021 yılları arasında tutulan aylık elektrik tüketimi verisidir.

Veriye buradan ulaşabilirsiniz: Veri / eia

Verinin yüklenmesi:

veri <-read.csv("https://raw.githubusercontent.com/gungorrbaris/zaman-serisi-analizi-R/main/data/Table_7.6_Electricity_End_Use.csv")
knitr::kable(head(veri,n=10), align = "c")
Month Electricity.End.Use..Total
1973 January 144505.2
1973 February 139546.1
1973 March 137102.3
1973 April 131365.9
1973 May 131360.9
1973 June 140293.0
1973 July 152562.2
1973 August 157480.8
1973 September 157309.6
1973 October 146042.0

Verinin Düzenlenmesi:

Tarih değişkenini Ay-Yıl formatına getirelim:

tarih = seq(from = as.Date("1973-01-01"), to = as.Date("2021-11-01"), by = 'month')
veri$Month <- tarih
veri$Month <-format(veri$Month, "%m-%Y")
knitr::kable(head(veri), align = "c")
Month Electricity.End.Use..Total
01-1973 144505.2
02-1973 139546.1
03-1973 137102.3
04-1973 131365.9
05-1973 131360.9
06-1973 140293.0

Değişken isimlerini türkçeleştirelim:

colnames(veri) <- c("Tarih","Elektrik_Tuketimi")
knitr::kable(head(veri), align = "c")
Tarih Elektrik_Tuketimi
01-1973 144505.2
02-1973 139546.1
03-1973 137102.3
04-1973 131365.9
05-1973 131360.9
06-1973 140293.0




Serinin Hazırlanması

Zaman Serisinin Oluşturulması

veri_ts <- ts(data = veri$Elektrik_Tuketimi, start = c(1973, 01), end = c(2021, 11), frequency = 12 )

Verimizde gözlemler aylık olduğu için frekans değeri (frequency) 12 olarak belirlenmelidir.

Zaman Serisi Grafiğinin Çizilmesi

ts.plot(veri_ts,gpars=list(xlab="Zaman", ylab="Elektrik Tüketimi"))

Zaman Serisi Grafiğine bakıldığında:

  • Pozitif yönlü artış vardır. Bu yüzden Serinin artan bir trende sahip olduğunu söyleyebiliriz.

  • Seride düzenli dalgalanmaların olduğu görülmektedir. Bu seride mevsimsellik olabileceğini gösterir. Daha kesin sonuç için ACF grafiğini çizelim.

ACF Grafiğinin Çizilmesi

! BİLGİ !

Gecikmeli seri: Serilerdeki verilerin dönem kaydırılması işlemi ile ortaya çıkan serilerdir. Zt bir zaman serisi değişkeni ise; bir dönem gecikmeli zaman serisi Zt-1, iki dönem gecikmeli Zt-2 ve k dönem gecikmeli Zt-k ile gösterilir.

Otokorelasyon katsayısı: Zaman serileri ile bu serilerin gecikmeli serileri arasındaki ilişkileri verir.

ACF: Otokorelasyon fonksiyonu (Autocorrelation function) demektir. Otokorelasyon katsayısı değerlerinden oluşur.

Seride trendin olduğunu anlamak için ACF grafiğindeki ilk dört gecikmeye bakmak yeterlidir. İlk dört gecikme sınırlar dışındaysa seri için “trende sahiptir” diyebiliriz.

library(fpp)
## Zorunlu paket yükleniyor: forecast
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## Zorunlu paket yükleniyor: fma
## Zorunlu paket yükleniyor: expsmooth
## Zorunlu paket yükleniyor: lmtest
## Zorunlu paket yükleniyor: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Zorunlu paket yükleniyor: tseries
Acf(veri_ts,lag.max = 42,  ylim=c(-1,1), lwd=5,main="Orijinal veri ACF Grafiği")

ACF Grafiğine bakıldığında:

  • Tüm gecikmeler (4 gecikme olması yeterlidir) sınırlar dışında olduğu için zaman serisinin trende sahip olduğu söylenebilir. Bu yüzden serinin farkı alınıp durağan hale getirilmelidir.

  • Trend ile birlikte düzenli dalgalanmaların olduğu gözükse de baskın bir mevsimsellikten şu an için bahsedemeyiz.

Birinci Farkın Alınması

! BİLGİ !

Fark Alınması: Zaman serisinin akışkanlı bir şekilde son değerlerinden belli bir dönem önceki değerlerinin çıkarılması işlemidir. Bu işlem sayesinde serideki trend ya da mevsimsel dalgalanmaları yok etmek mümkün olmaktadır.

veri_birinci_fark <- diff(veri_ts, differences = 1)

Farkı alınmış seri için ACF:

Acf(veri_birinci_fark,lag.max = 42,  ylim=c(-1,1), lwd=5,main="Birinci Fark sonrası ACF Grafiği")

MEVSİMSELLİK

Birinci Farkı alınmış seri için ACF Grafiğine bakıldığında:

  • Yine tüm gecikmeler sınırlar dışında olduğu için birinci farkı alınmış zaman serisinin de trende sahip olduğu söylenebilir. Fakat bir öncekine göre bu ACF grafiğinde baskın bir mevsimsellik görülüyor. Dalgalanmalar ve gecikmelerdeki düzenli sıçramalar bunu destekliyor.

AYRIŞTIRMA YÖNTEMLERİ

Zaman serisini bileşenlerine ayırarak her bir bileşen için tahminleri içeren ve bu bileşenlerin tahmininden zaman serisinin öngörüsünü hesaplayan yönteme Ayrıştırma Yöntemi denmektedir.

Ayrıştırma yöntemi genel olarak iki sınıfa ayrılabilir.
1.Toplamsal Ayrıştırma Yöntemi
2.Çarpımsal Ayrıştırma Yöntemi

Toplamsal Ayrıştırma Yöntemi

Toplamsal model; zaman serisinin, bileşenlerin toplamından oluştuğunu kabul eder.
Zt = Tt + Mt + εt

Matematiksel olarak, Zt=f(Tt, Mt , Ct, εt) şeklinde gösterilip tahmini ise : Z =f(Tt, Mt , Ct)’dir. Bilinen en eski öngörü yöntemlerinden olup kısa dönemli öngörülerde anlaşılması ve yapılması en kolay yöntemdir. Trende ve Mevsimselliğe sahip verilerde kullanılır.

Trend Bileşeni ve Periyodun Bulunması

Trend Bileşeni:

Serinin Trend Bileşeni Regresyon analizi yardımı ile oluşturulur.

veri_trend <- tslm(veri_ts~trend)
  • Burada dikkat edilmesi gereken, denkleme orijinal serinin eklenmiş olmasıdır.

  • Oluşturulan Regresyon denklemindeki fitted.values değişkeni dikkate alınır.

  • fitted.values değişkeni orijinal serinin trend bileşeni olur.

head(veri_trend[["fitted.values"]],n=36)
##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 1973 149788.4 150157.2 150526.1 150895.0 151263.9 151632.8 152001.6 152370.5
## 1974 154214.9 154583.8 154952.7 155321.5 155690.4 156059.3 156428.2 156797.0
## 1975 158641.4 159010.3 159379.2 159748.1 160117.0 160485.8 160854.7 161223.6
##           Sep      Oct      Nov      Dec
## 1973 152739.4 153108.3 153477.1 153846.0
## 1974 157165.9 157534.8 157903.7 158272.6
## 1975 161592.5 161961.3 162330.2 162699.1

Periyodun Bulunması:

Orijinal zaman Serisi ve trend bileşeninin farkını alarak periyodu bulabiliriz.

periyot_trend <- veri_ts - veri_trend[["fitted.values"]]

Serinin periyoduna sahip mevsimsel bileşen serisinin ACF değerleri ile periyodu bulalım:

Acf(periyot_trend,lag.max = 42,  ylim=c(-1,1), lwd=5,plot=FALSE)
## 
## Autocorrelations of series 'periyot_trend', by lag
## 
##      0      1      2      3      4      5      6      7      8      9     10 
##  1.000  0.720  0.265 -0.021  0.043  0.320  0.455  0.318  0.040 -0.025  0.246 
##     11     12     13     14     15     16     17     18     19     20     21 
##  0.673  0.916  0.653  0.218 -0.057  0.012  0.287  0.416  0.281  0.009 -0.057 
##     22     23     24     25     26     27     28     29     30     31     32 
##  0.204  0.622  0.853  0.602  0.185 -0.078 -0.006  0.260  0.387  0.257 -0.015 
##     33     34     35     36     37     38     39     40     41     42 
## -0.079  0.177  0.587  0.814  0.567  0.158 -0.097 -0.029  0.230  0.354

ACF değerlerine bakıldığında:

  • En büyük değerin 12. gecikme (0.916), en büyük ikinci gecikmenin ise 24. gecikme (0.853) olduğu gözükmektedir.

  • 12 ve 24 gecikme arasında toplam 12 değer olduğu için; birinci farkı alınmış serinin periyodunun 12 olduğunu söyleyebiliriz.

Buradaki başlıkta periyot bulma işlemini yapmış ve aynı sonuca ulaşmıştık.

Mevsimsel, döngüsel veya düzensiz dalgalanmaları yok etme ya da belli bir miktar düzleştirme amacıyla basit hareketli ortalama ya da merkezsel hareketli ortalama işlemlerine ihtiyaç duyulmaktadır.

Ayrıştırma Yönteminde merkezsel hareketli ortalamayı mevsimsel bileşeni bulmak için kullanacağız.

Merkezsel Hareketli Ortalama Hesabı

veri_trend_1 <- ma(veri_ts, order = 12, centre = TRUE)

Burada order = germe sayısı, bir önceki adımda bulduğumuz periyot ile aynı olmalıdır.

Mevsimsel Bileşenin Bulunması

Mevsimsel bileşene ulaşmak için yukarıda hesapladığımız merkezsel hareketli ortalama serisini, orijinal seriden çıkartmamız gerekiyor.

mevsim3 <- veri_ts - veri_trend_1
head(mevsim3,n=36)
##               Jan          Feb          Mar          Apr          May
## 1973           NA           NA           NA           NA           NA
## 1974   1244.43125  -5987.08842  -6644.94317  -9240.61225  -8877.00792
## 1975   5386.46054  -1263.04279  -3774.80125  -8881.94913 -11311.41638
##               Jun          Jul          Aug          Sep          Oct
## 1973           NA   9841.39842  14898.72092  14892.45550   3604.40875
## 1974    -77.18058   9125.58383  15241.64129  10288.53987  -2292.94225
## 1975  -2311.87663   8148.75617  13941.57687  10060.55892  -6412.73892
##               Nov          Dec
## 1973  -4435.71604  -5518.18642
## 1974  -8002.64087  -2999.57629
## 1975  -9583.86033  -1785.75867

Mevsim serisinin ortalamaları

Mevsimsel bileşendeki hata teriminin yok edilebilmesi için her bir periyottaki dönemlerin ortalama değerleri hesaplanır.

donemort3<-t(matrix(data=mevsim3, nrow = 12))
## Warning in matrix(data = mevsim3, nrow = 12): veri uzunluğu [587] dize sayısının
## [12] böleni veya tam böleni değil
head(donemort3)
##           [,1]      [,2]      [,3]       [,4]       [,5]        [,6]      [,7]
## [1,]        NA        NA        NA         NA         NA          NA  9841.398
## [2,]  1244.431 -5987.088 -6644.943  -9240.612  -8877.008   -77.18058  9125.584
## [3,]  5386.461 -1263.043 -3774.801  -8881.949 -11311.416 -2311.87663  8148.756
## [4,] 10481.996  2802.820 -3880.936  -9695.276 -11061.992 -4935.45200  7910.461
## [5,] 12666.531  4699.200 -5136.574 -14090.190 -13786.849 -3093.95550 12455.279
## [6,] 11804.552  4676.338 -2511.719 -16272.308 -15786.122 -2368.93296 10589.750
##          [,8]      [,9]     [,10]      [,11]     [,12]
## [1,] 14898.72 14892.455  3604.409  -4435.716 -5518.186
## [2,] 15241.64 10288.540 -2292.942  -8002.641 -2999.576
## [3,] 13941.58 10060.559 -6412.739  -9583.860 -1785.759
## [4,] 12553.10  7480.415 -6545.047  -7306.031  4008.703
## [5,] 15675.59  8854.138 -4461.604 -12721.138 -2238.178
## [6,] 14851.83 12373.875 -4417.750 -12814.542 -3622.708

Periyottaki dönemlerin ortalama değerleri:

colMeans(donemort3, na.rm = T)
##  [1]  12293.710  -8992.596 -12270.776 -27486.215 -19556.515   5455.674
##  [7]  33711.582  37332.788  13396.718 -10784.080 -22267.319  -2109.830

Periyottaki dönemlerin ortalama değerlerinin toplamı:

sum(colMeans(donemort3, na.rm = T))
## [1] -1276.859

Bu değerin 0 olması gerekmektedir. 0 olmadığı için ortalamaların ortalaması alınmalıdır. Bu ortalama değer diğer tüm ortalama değerlerden çıkartılır ve mevsimsel endeks serisi bulunur.

Periyottaki dönemlerin ortalama değerlerinin ortalaması:

mean(colMeans(donemort3, na.rm = T))
## [1] -106.4049

Mevsimsel Endeksin Bulunması

endeks1 <- colMeans(donemort3, na.rm = T) - mean(colMeans(donemort3, na.rm = T))

endeks1
##  [1]  12400.115  -8886.191 -12164.371 -27379.810 -19450.110   5562.079
##  [7]  33817.987  37439.193  13503.123 -10677.675 -22160.914  -2003.426

Bu 12 mevsimsel endeks değeri periyottaki dönemlere dikkat edilerek (ilk döneme karşılık M1; ikinci döneme karşılık M2; üçüncü döneme karşılık M3, … , on ikinci döneme karşılık M12 gelecek şekilde) seri boyunca tekrar tekrar yazılabilmesi için aşağıdaki adım gerçekleştirilir.

İndeks Değerlerini Seri Boyunca Yazdırma İşlemi:

indeks<-  matrix(data = endeks1, nrow = 587)
## Warning in matrix(data = endeks1, nrow = 587): veri uzunluğu [12] dize sayısının
## [587] böleni veya tam böleni değil
head(indeks)
##            [,1]
## [1,]  12400.115
## [2,]  -8886.191
## [3,] -12164.371
## [4,] -27379.810
## [5,] -19450.110
## [6,]   5562.079

Hata Terimli Trend Bileşeninin Bulunması

trendhata <- veri_ts - indeks

Hata Terimli Trend Bileşeninine ait zaman serisi grafiği:

plot.ts(trendhata)

Elde edilen bu trent serisinde hata terimi de olduğundan seriye ‘’trendhata’’ adı verilir. Bu seriyi hata teriminden arındırabilmek amacıyla trendhata serisine doğrusal regresyon uygulanır.

trend1<-tslm(ts(trendhata)~trend)
  • Burada fitted.values değişkeni dikkate alınır.

  • fitted.values değişkeni orijinal serinin trend bileşeni olur.

head(trend1[["fitted.values"]],n=24)
## Time Series:
## Start = 1 
## End = 24 
## Frequency = 1 
##  [1] 149853.0 150221.7 150590.3 150959.0 151327.6 151696.3 152064.9 152433.6
##  [9] 152802.2 153170.9 153539.5 153908.1 154276.8 154645.4 155014.1 155382.7
## [17] 155751.4 156120.0 156488.7 156857.3 157226.0 157594.6 157963.2 158331.9

Tahmin ve Hata Serilerinin Bulunması

Tahmin Bileşenlerini Bulalım:

tahmin = mevsimsel endeks + saf trend serisi

tahmin<- indeks+trend1[["fitted.values"]]
tahmin <- ts(data = tahmin, start = c(1973, 01), end = c(2021, 11), frequency = 12 )
plot(tahmin,main = "Tahmin Serisi Grafiği")

Hata Bileşenlerini Bulalım:

hata = saf trend serisi - tahmin

hata <- ts(veri_ts) - ts(tahmin)
plot(hata,main = "Tahmin serisi için Hata Serisi Grafiği")

Modelin Güvenirliği

Toplamsal modelin orijinal seri üzerinde geçerli bir model olup olmadığını kontrol edelim.

Orijinal seri ile tahmin serisinin uyumu:

plot( window(veri_ts), 
      xlab="Zaman", ylab="",lty=1, col=4, lwd=2,main="Orijinal Seri ve Tahmin Serisinin Birlikte Grafiği")
lines( window(tahmin) ,lty=3,col=2,lwd=3)
legend("topleft",c(expression(paste(OrijinalSeri )),
                   expression(paste(Tahmin ))),
       lwd=c(2,2),lty=c(1,3), cex=0.6, col=c(4,2))

Zaman Serisi Grafiğine bakıldığında:

  • Tahmin ile orijinal seri arasında sapmanın yüksek olduğunu dolayısıyla uyum göstermediğini söyleyebiliriz.

  • Fakat emin olmak için hataların akgürültü olup olmadığına bakabiliriz.

Hatalar Akgürültü mü?

! BİLGİ !

Akgürültü Serisi: Durağanlık koşullarından tek farkı kovaryans teriminin sıfır olmasıdır. Dolayısıyla, akgürültü serisi durağan bir seriden farklı özellikler gösterir.
Örneğin, akgürültü serisi rasgele hareketlere sahip modellenemez bir seri iken durağan serilerin hareketlerinin belli bir sistematiği vardır ve bu nedenle modellenebilmektedir. Akgürültü serisinin tüm gecikmelerindeki otokorelasyon ve kısmi otokorelasyon değerleri önemsizdir.

ACF ve PACF grafıklerinin yorumunda serinin akgürültü serisi olup olmadığına net bir şekilde karar verilemiyorsa, yani ACF veya PACF grafiklerinde birinci gecikme dışında az sayıda güven sınırını biraz geçen ilişkiler var ise bu durumda seriye Box-Ljung Testi uygulanır.

Eğer her gecikme için Box-Ljung Testi sonucunda Ho : rk = 0 yokluk hipotezi kabul edilirse serinin akgürültü serisi olduğu söylenir.

Kaynak: Prof. Dr. Cem Kadılar, Dr. Hatice Öncel Çekim SPSS ve R Uygulamalı Zaman Serileri Analizine Giriş

Ho: Hatalar Akgürültüdür.(Hatalar arasında ilişki yoktur.)
H1: Hatalar Akgürültü değildir.(Hatalar arasında ilişki vardır.)

Hatalar için ACF Grafiği:

Acf(hata, lag.max = 42,  ylim=c(-1,1), lwd=5,main="Hatalar için ACF Grafiği")

Hatalar için ACF Grafiğine bakıldığında:

  • Tüm gecikmelerin sınırları geçtiği gözükmektedir.

  • Hataların akgürültü olmadığı (Ho RED) Söylenebilir. Box-Ljung testi ile de bunu görebiliriz.

Box-Ljung Testi:

Box.test(hata,type = "Ljung",lag = 42)
## 
##  Box-Ljung test
## 
## data:  hata
## X-squared = 9137.7, df = 42, p-value < 2.2e-16

Box-Ljung test sonucuna bakıldığında:

  • p değeri = 0 < α =0.05 ’dir. Yani Ho RED.

  • Hatalar Arasında ilişki olduğunu yani hataların akgürültü olmadığını söyleyebiliriz.

SONUÇ

Bir önceki adımda görüldüğü üzere;

  • Hatalar Arasında ilişki olduğunu yani hataların akgürültü olmadığını gördük.

  • Sonuç olarak ABD’deki aylık elektrik tüketimi serisinin analizi için Toplumsal Ayrıştırma yöntemi uygun değildir.