📈📉 비즈니스 어낼리틱스/🕑 시계열 분석

🕑시계열데이터 분석 06 - 시계열 데이터 분해

nyamin9 2023. 4. 13. 23:11

모바일은 화면을 돌려 가로화면으로 보시는 게 읽으시기 편할 수 있습니다. 돌려서 보시는 걸 추천드릴게요!!

 

 


🕑 시계열 분해

 

시계열 분석 모형의 선택은 Y 변수와 그와 관련있는 다른 변수의 유무에 의해 정해집니다.

 


🕑 시계열자료의 구성 및 요인

 

image

 

  1. 추세요인(trend factor) : 장기변동 / 기술의 변화, 인플레이션 / 전반적인 움직임
  2. 순환요인(cycle factor) : 중기변동 / 경기순환주기 / 몇년 단위 반복 움직임 / 파악 어려움 / 계절성 잡은 후 잡기 가능
  3. 계절요인(seasonal factor) : 1년 주기로 발생하는 단기변동
  4. 불규칙요인(irregular factor) : 측정 및 예측이 어려운 오차변동 / 시계열을 위 세 가지 요인으로 설명하고 남은 변동

 

• 보통, 주어진 시계열을 추세(trend), 계절(seasonal), 불규칙(random) 요인으로 분해합니다.

 

• 분해 후, 계절조정 시계열 자료로 변환이 가능합니다.

 

 


🕑 시계열 분해 : decompose( ) 함수

 

decompose( ) 함수는 moving average를 사용해서 시계열 데이터를 각 요인으로 분해합니다.

 

• 일반적으로 가법모형이나 승법모형의 옵션을 줄수 있습니다.

• 자잘하게 움직이는 값을 삭제하고 트렌드를 잡기 용이합니다.

• window 가 넓어질수록 자잘한 값을 잘 없앨 수 있습니다.

• 원래 값에서 seasonal factor를 제거한 것이 바로 계절조정된 데이터입니다.

 

• 가법 분해모형 : $y_i = trend_i + seasonal_i + random_i$

• 승법 분해모형 : $y_i = trend_i * seasonal_i * random_i$ (log transformation 시 사용)

 

• 시간이 흐름에 따라 계절효과가 커지면 승법 분해가 더 적절합니다.

 

oil_decompose <- decompose(oil.ts)

 

decompose( ) 함수 사용 결과,

시계열 데이터는 원본 데이터 x와 계절요인 seasonal, 추세요인 trend, 불규칙 요인 random 으로 분해됩니다.

 

plot(oil_decompose)

image

 

이 데이터를 분해해 보면, 위의 그림과 같은 결과가 나옵니다.

관측값 데이터(observed) 는 일정 주기로 증가-감소의 반복이 눈에 띕니다.

추세(trend) 는 한번 휘청이기는 했지만, 그래도 꾸준한 증가를 보이고 있습니다.

계절성(seasonal)은 확실히 드러나고 있습니다. 이 때문에 원래 데이터가 일정한 주기로 증가-감소를 반복하고 있겠네요.

무작위성(random)은 추세와 계절성을 제거하고 남은 변동성이기 때문에, 눈에 보이는 규칙은 없습니다.

 

 

 

 

☑️ 계절요인

head(oil_decompose$seasonal)
>>

##             Jan        Feb        Mar        Apr        May        Jun
## 1994 1000.67723  -32.73348  539.89350 -335.62435 -467.49340 -737.29896
## 1995 1000.67723  -32.73348  539.89350 -335.62435 -467.49340 -737.29896
## 1996 1000.67723  -32.73348  539.89350 -335.62435 -467.49340 -737.29896
## 1997 1000.67723  -32.73348  539.89350 -335.62435 -467.49340 -737.29896
## 1998 1000.67723  -32.73348  539.89350 -335.62435 -467.49340 -737.29896

##             Jul        Aug        Sep        Oct        Nov        Dec
## 1994 -731.41431 -413.42756 -500.75332  -83.38022  332.99668 1428.55819
## 1995 -731.41431 -413.42756 -500.75332  -83.38022  332.99668 1428.55819
## 1996 -731.41431 -413.42756 -500.75332  -83.38022  332.99668 1428.55819
## 1997 -731.41431 -413.42756 -500.75332  -83.38022  332.99668 1428.55819
## 1998 -731.41431 -413.42756 -500.75332  -83.38022  332.99668 1428.55819

 

 

☑️ 추세요인

head(oil_decompose$trend)
>>

##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 1994       NA       NA       NA       NA       NA       NA 7250.833 7351.792
## 1995 7560.875 7597.792 7640.708 7666.583 7722.625 7798.167 7857.625 7905.125
## 1996 8137.208 8165.583 8201.167 8262.167 8278.583 8290.625 8351.333 8388.583
## 1997 8648.000 8743.292 8832.708 8919.042 9016.583 9078.125 8978.583 8793.208
## 1998 8305.792 8186.500 8077.750 7947.625 7776.917 7624.125 7589.875 7670.875

##           Sep      Oct      Nov      Dec
## 1994 7400.750 7456.958 7525.000 7546.667
## 1995 7979.000 8051.792 8073.875 8099.833
## 1996 8407.042 8432.792 8511.875 8588.208
## 1997 8664.542 8553.083 8449.875 8378.250
## 1998 7742.625 7812.667 7838.833 7836.250

 

 

☑️ 불규칙요인

oil_decompose$random
>>

##               Jan          Feb          Mar          Apr          May
## 1994           NA           NA           NA           NA           NA
## 1995   819.447766   696.941814    61.398163   459.041020  -521.131599
## 1996   916.114433   596.150147   806.939830   304.457687  -988.089932
## 1997  1039.322766   278.441814   358.398163    82.582687  -263.089932
## 1998 -1290.468900  -941.766519  -197.643503  -310.000646  -136.423265

##               Jun          Jul          Aug          Sep          Oct
## 1994           NA  -246.419027  -682.364102  -401.996678   -44.578117
## 1995  -741.867710  -662.210693  -540.697436  -645.246678  -353.411451
## 1996  -700.326043  -792.919027  -706.155769  -537.288345   193.588549
## 1997 -1118.826043  -354.169027   110.219231   130.211655  1220.296883
## 1998  -270.826043   -98.460693  -497.447436   172.128322  -282.286451

##               Nov          Dec
## 1994   199.003322   518.775147
## 1995   709.128322   719.608481
## 1996  -262.871678  1054.233481
## 1997   993.128322  1547.191814
## 1998  -249.830011   276.191814

 

 


🕑 계절조정: seasadj( ) 함수

 

• decompose( ) 함수를 통해 시계열을 분해한 후, seasadj( ) 함수를 적용합니다.

• trend를 제거한 후 계절별 평균을 구해줍니다.

• random 값의 평균이 0이 되도록 seasonality를 잡습니다.

 

# install.packages("forecast")
library(forecast)

oil_seasadj_decompose = seasadj(oil_decompose)
head(oil_seasadj_decompose)
>>

##           Jan      Feb      Mar      Apr      May      Jun
## 1994 7046.323 7205.733 7616.106 6862.624 6831.493 6906.299

 

계절조정 데이터의 plot 결과, 계절이 조정되어 위아래 변동성이 일부 제거됩니다.

Y 변수와의 관계만 따질 때에는 계절성 제거가 굳이 없어도 되지만, 다른 변수와의 관계를 파악할 때는 중요합니다.

 

계절조정된 데이터를 plot 해보면, 원래 값에 비해 계절에 의한 변동성이 줄어든 것을 확인할 수 있습니다.

 

par(mfrow = c(2,1))
plot(oil_decompose$x)
plot(oil_seasadj_decompose)

image

 

 


🕑 시계열 분해 : stl( ) 함수

 

decompose( ) 함수와 동일하게, stl( ) 함수 사용 결과

시계열 데이터는 원본 데이터 x와 계절요인 seasonal, 추세요인 trend, 불규칙 요인 random 으로 분해됩니다.

 

## seasonal and trend decomposition using loess 
## locally estimated scatterplot smoothing
## trend를 잡기 위해 Non parametric linear regression 사용

oil.df=read.csv("BOK_energy_oil.csv")
oil.ts=ts(oil.df$oil, start=c(1994,1), frequency=12)
oil_stl <- stl(oil.ts, s.window = "periodic")
head(oil_stl)
>>

## $time.series
##            seasonal    trend    remainder
## Jan 1994  995.65266 6882.183   169.164244
## Feb 1994   -2.65036 6936.291   239.359025
## Mar 1994  561.82943 6990.400   603.770996
## Apr 1994 -342.64010 7053.968  -184.328234
## May 1994 -480.22962 7117.537  -273.307475



## $weights
##   [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
##  [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
##  [75] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [112] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [149] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [186] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [223] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [260] 1 1 1 1 1 1 1 1 1


## $call
## stl(x = oil.ts, s.window = "periodic")


## $win
##    s    t    l 
## 2681   19   13 


## $deg
## s t l 
## 0 1 1 


## $jump
##   s   t   l 
## 269   2   2

 

plot(oil_stl)

image

 

분해 결과는 앞서 decompose() 함수 사용과 비슷하게 나오는 것 같습니다. 순서만 살짝 다르네요!!

관측값 데이터(observed) 는 일정 주기로 증가-감소의 반복이 눈에 띕니다.

계절성(seasonal)은 확실히 드러나고 있습니다. 이 때문에 원래 데이터가 일정한 주기로 증가-감소를 반복하고 있겠네요.

추세(trend) 는 한번 휘청이기는 했지만, 그래도 꾸준한 증가를 보이고 있습니다.

무작위성(random)은 추세와 계절성을 제거하고 남은 변동성이기 때문에, 눈에 보이는 규칙은 없습니다.

 


🕑 계절조정: seasadj( ) 함수

 

• stl( ) 함수를 통해 시계열을 분해한 후, seasadj( ) 함수를 적용합니다.

• trend를 제거한 후 계절별 평균을 구해줍니다.

• random 값의 평균이 0이 되도록 seasonality를 잡습니다.

 

oil_seasadj_stl = seasadj(oil_stl)
head(oil_seasadj_stl)
>>

##           Jan      Feb      Mar      Apr      May      Jun
## 1994 7051.347 7175.650 7594.171 6869.640 6844.230 6919.067

 

계절조정된 데이터를 plot 해보면, 원래 값에 비해 계절에 의한 변동성이 줄어든 것을 확인할 수 있습니다.

 

plot(oil_seasadj_stl)

image

 

 


🕑 예측 : forecast( ) 함수

 

시계열 분석 이후, forecast( ) 함수를 사용해서 앞으로의 값을 예측할 수 있습니다.

 

oil_forecast_stl <- forecast(oil_stl, method = 'naive')
plot(oil_forecast_stl)

image