8.1 정상성과 차분

정상성(stationarity)을 나타내는 시계열은 시계열의 특징이 해당 시계열이 관측된 시간에 무관합니다.15 따라서, 추세나 계절성이 있는 시계열은 정상성을 나타내는 시계열이 아닙니다 — 추세와 계절성은 서로 다른 시간에 시계열의 값에 영향을 줄 것이기 때문입니다. 반면에, 백색잡음(white noise) 시계열은 정상성을 나타내는 시계열입니다 — 언제 관찰하는지에 상관이 없고, 시간에 따라 어떤 시점에서 보더라도 똑같이 보일 것이기 때문입니다.

몇 가지 경우는 헷갈릴 수 있습니다 — 주기성 행동을 가지고 있는 (하지만 추세나 계절성은 없는) 시계열은 정상성을 나타내는 시계열입니다. 왜냐하면 주기가 고정된 길이를 갖고 있지 않기 때문에, 시계열을 관측하기 전에 주기의 고점이나 저점이 어디일지 확실하게 알 수 없습니다.

일반적으로는, 정상성을 나타내는 시계열은 장기적으로 볼 때 예측할 수 있는 패턴을 나타내지 않을 것입니다. (어떤 주기적인 행동이 있을 수 있더라도) 시간 그래프는 시계열이 일정한 분산을 갖고 대략적으로 평평하게 될 것을 나타낼 것입니다.

다음의 시계열 중에서 어떤 것이 정상성을 나타낼까요? (a) 200 거래일 동안의 구글 주식 가격; (b) 200 거래일 동안의 구글 주식 가격의 일일 변동; (c) 미국의 연간 파업 수; (d) 미국에서 판매되는 새로운 단독 주택의 월별 판매액; (e) 미국에서 계란 12개의 연간 가격 (고정 달러); (f) 호주 빅토리아 주에서 매월 도살한 돼지의 전체 수; (g) 캐나다 북서부의 맥킨지 강 지역에서 연간 포획된 스라소니의 전체 수; (h) 호주 월별 맥주 생산량; (i) 호주 월별 전기 생산량.

Figure 8.1: 다음의 시계열 중에서 어떤 것이 정상성을 나타낼까요? (a) 200 거래일 동안의 구글 주식 가격; (b) 200 거래일 동안의 구글 주식 가격의 일일 변동; (c) 미국의 연간 파업 수; (d) 미국에서 판매되는 새로운 단독 주택의 월별 판매액; (e) 미국에서 계란 12개의 연간 가격 (고정 달러); (f) 호주 빅토리아 주에서 매월 도살한 돼지의 전체 수; (g) 캐나다 북서부의 맥킨지 강 지역에서 연간 포획된 스라소니의 전체 수; (h) 호주 월별 맥주 생산량; (i) 호주 월별 전기 생산량.

그림 8.1에 나타낸 9개의 시계열을 살펴봅시다. 이 중에서 어떤 것이 정상성을 나타내는 시계열이라고 생각합니까?

분명하게 계절성이 보이는 (d), (h), (i)는 후보가 되지 못합니다. 추세가 있고 수준이 변하는 (a), (c), (e), (f), (i)도 후보가 되지 못합니다. 분산이 증가하는 (i)도 후보가 되지 못합니다. 그러면 (b)와 (g)만 정상성을 나타내는 시계열 후보로 남았습니다.

언뜻 보면 시계열 (g)에서 나타나는 뚜렷한 주기(cycle) 때문에 정상성을 나타내는 시계열이 아닌 것처럼 보일 수 있습니다. 하지만 이러한 주기는 불규칙적(aperiodic)입니다 — 먹이를 구하기 힘들만큼 살쾡이 개체수가 너무 많이 늘어나 번식을 멈춰서, 개체수가 작은 숫자로 줄어들고, 그 다음 먹이를 구할 수 있게 되어 개체수가 다시 늘어나는 식이기 때문입니다. 장기적으로 볼 때, 이러한 주기의 시작이나 끝은 예측할 수 없습니다. 따라서 이 시계열은 정상성을 나타내는 시계열입니다.

차분

그림 8.1의 패널 (a)의 구글(Google) 주식 가격이 정상성을 나타내는 시계열이 아니었지만 패널 (b)의 일별 변화는 정상성을 나타냈다는 것에 주목합시다. 이 그림은 정상성을 나타내지 않는 시계열을 정상성을 나타내도록 만드는 한 가지 방법을 나타냅니다 — 연이은 관측값들의 차이를 계산하는 것입니다. 이것은 차분(differencing)로 알려져 있습니다.

로그 같은 변환은 시계열의 분산 변화를 일정하게 만드는데 도움이 될 수 있습니다. 차분(differencing)은 시계열의 수준에서 나타나는 변화를 제거하여 시계열의 평균 변화를 일정하게 만드는데 도움이 될 수 있습니다. 결과적으로 추세나 계절성이 제거(또는 감소)됩니다.

정상성을 나타내지 않는 시계열을 찾아낼 때 데이터의 시간 그래프를 살펴보는 것만큼, ACF 그래프도 유용합니다. 정상성을 나타내지 않는 데이터에서는 ACF가 느리게 감소하지만, 정상성을 나타내는 시계열에서는, ACF가 비교적 빠르게 0으로 떨어질 것입니다. 그리고 정상성을 나타내지 않는 데이터에서 \(r_1\)은 종종 큰 양수 값을 갖습니다.

구글 주식 가격의 ACF (왼쪽) 그리고 일별 변동 (오른쪽).

Figure 8.2: 구글 주식 가격의 ACF (왼쪽) 그리고 일별 변동 (오른쪽).

Box.test(diff(goog200), lag=10, type="Ljung-Box")
#> 
#> 	Box-Ljung test
#> 
#> data:  diff(goog200)
#> X-squared = 11, df = 10, p-value = 0.4

차분을 구한 구글 주식 가격의 ACF는 단순히 백색잡음(white noise) 시계열처럼 생겼습니다. 95% 한계 바깥에 자기상관(autocorrelation) 값이 없고, 융-박스(Ljung-Box) \(Q^*\) 통계는 \(h=10\)에 대해 0.355라는 p-값을 갖습니다. 이 결과는 구글 주식 가격의 일별 변동이 기본적으로는 이전 거래일의 데이터와 상관이 없는 무작위적인 양이라는 것을 말해줍니다.

확률보행 모델

차분(difference)을 구한 시계열은 원래의 시계열에서 연이은 관측값의 차이이고, 다음과 같이 쓸 수 있습니다. \[ y'_t = y_t - y_{t-1}. \] 첫 번째 관측값에 대한 차분 \(y_1'\)을 계산할 수 없기 때문에 차분을 구한 시계열은 \(T-1\)개의 값만 가질 것입니다.

차분을 구한 시계열이 백색잡음(white noise)이면, 원래 시계열에 대한 모델은 다음과 같이 쓸 수 있습니다. \[ y_t - y_{t-1} = \varepsilon_t, \] 여기에서 \(\varepsilon_t\) 은 백색잡음(white noise)을 의미합니다. 이것을 정리하면 “확률보행(random walk)” 모델을 얻습니다. \[ y_t = y_{t-1} + \varepsilon_t. \] 확률보행(random walk) 모델은 정상성을 나타내지 않는 데이터, 특별히 금융이나 경제 데이터를 다룰 때 널리 사용되고 있습니다. 확률보행에는 보통 다음과 같은 특징이 있습니다:

  • 누가 봐도 알 수 있는 긴 주기를 갖는 상향 또는 하향 추세가 있습니다.
  • 갑작스럽고 예측할 수 없는 방향 변화가 있습니다.

미래 이동을 예측할 수 없고 위로 갈 확률이나 아래로 갈 확률이 정확하게 같기 때문에 확률보행 모델에서 낸 예측값은 마지막 관측값과 같습니다. 따라서, 확률보행 모델은 3.1 절에서 처음 소개했던 단순(naïve) 예측값을 뒷받침합니다.

밀접하게 연관된 모델은 차분값이 0이 아닌 평균값을 갖게 합니다. 그러면, \[ y_t - y_{t-1} = c + \varepsilon_t\quad\text{or}\quad {y_t = c + y_{t-1} + \varepsilon_t}\: . \] \(c\)값은 연이은 관측값의 차이의 평균입니다. \(c\)가 양수이면, 평균 변화는 \(y_t\) 값에 따라 증가합니다. 따라서, \(y_t\)는 위쪽 방향으로 이동하는 경향을 나타낼 것입니다. 하지만 \(c\)가 음수이면, \(y_t\)는 아래쪽 방향으로 이동하는 경향을 나타낼 것입니다.

이것이 바로 3.1 절에서도 다룬 표류 기법(drift model) 속에 숨어있는 모델입니다.

2차 차분

가끔 차분(difference)을 구한 데이터가 정상성(stationarity)이 없다고 보일 수도 있습니다. 정상성을 나타내는 시계열을 얻기 위해 데이터에서 다음과 같이 한 번 더 차분을 구하는 작업이 필요할 수도 있습니다: \[\begin{align*} y''_{t} &= y'_{t} - y'_{t - 1} \\ &= (y_t - y_{t-1}) - (y_{t-1}-y_{t-2})\\ &= y_t - 2y_{t-1} +y_{t-2}. \end{align*}\] 이 경우에는, \(y_t''\)\(T-2\)개의 값을 가질 것입니다. 그러면, 원본 데이터의 “변화에서 나타나는 변화”를 모델링하게 되는 셈입니다. 실제 상황에서는, 2차 차분 이상으로 구해야 하는 경우는 거의 일어나지 않습니다.

계절성 차분

계절성 차분(seasonal differencing)은 관측치와, 같은 계절의 이전 관측값과의 차이를 말합니다. 따라서 \[ y'_t = y_t - y_{t-m}, \] 여기에서 \(m\)은 계절의 개수입니다. \(m\) 주기 시차 뒤의 관측을 빼기 때문에 시차 \(m\) 차분이라고 부르기도 합니다.

계절성으로 차분을 구한 데이터가 백색잡음(white noise)으로 보이면, 원본 데이터에 대해 적절한 모델은 \[ y_t = y_{t-m}+\varepsilon_t. \] 이 모델에서 낸 예측값은 관련 있는 계절의 마지막 관측값과 같습니다. 즉, 이 모델은 3.1 절에서 소개했던 계절성 단순(seasonal naïve) 예측값을 냅니다.

그림 8.3의 아래쪽 패널은 호주에서 팔린 A10 약물(당뇨병 약)의 월별 처방전의 수에 로그를 취하여 계절성 차분을 구한 결과를 나타냅니다. 변환과 차분을 통해 시계열이 정상성을 나타내는 것처럼 보입니다.

cbind("판매량 (백만 달러)" = a10,
      "월별 로그 판매량" = log(a10),
      "로그 눈금에서 연간 변동" = diff(log(a10),12)) %>%
  autoplot(facets=TRUE) +
    xlab("연도") + ylab("") +
    ggtitle("당뇨병 약 판매량")
A10 (당뇨병 약) 판매량 데이터에 로그를 취한 것과 계절성 차분을 구한 것. 로그를 취하여 분산이 안정화되는 반면에, 계절성 차분은 계절성과 추세를 제거합니다.

Figure 8.3: A10 (당뇨병 약) 판매량 데이터에 로그를 취한 것과 계절성 차분을 구한 것. 로그를 취하여 분산이 안정화되는 반면에, 계절성 차분은 계절성과 추세를 제거합니다.

보통의 차분와 계절성 차분을 구분하기 위해, 때때로 보통의 차분을 시차 1에서 차분을 구한다는 의미로 “1차 차분(first difference)”라고 부릅니다.

그림 8.4에서 나타낸 것처럼, 계절성을 나타내는 데이터를 얻기 위해 계절성 차분과 1차 차분 둘 다 구하는 것이 필요하기도 합니다. 여기에서는, 데이터를 먼저 로그로 변환하고(두 번째 패널), 그리고 나서 계절성 차분을 계산했습니다(세 번째 패널). 데이터에서 여전히 정상성이 보이지 않는 것 같아서, 1차 차분을 더 많이 계산했습니다(아래 패널).

cbind("10억 kWh" = usmelec,
      "로그" = log(usmelec),
      "계절성\n 차분 로그값" =
        diff(log(usmelec),12),
      "두 번\n 차분을 구한 로그값" =
        diff(diff(log(usmelec),12),1)) %>%
  autoplot(facets=TRUE) +
    xlab("연도") + ylab("") +
    ggtitle("미국 월별 순 전기 생산량")
상단 패널: 미국 순 전기 생산량 (10억 kWh). 다른 패널은 같은 데이터를 변환시키고 차분을 구한 것을 나타냅니다.

Figure 8.4: 상단 패널: 미국 순 전기 생산량 (10억 kWh). 다른 패널은 같은 데이터를 변환시키고 차분을 구한 것을 나타냅니다.

어떤 차분(difference)을 구할지 정할 때는 주관적인 요소가 어느정도 들어갑니다. 그림 8.3의 계절성 차분(seasonal difference)을 구한 데이터는 그림 8.4의 계절성 차분을 구한 데이터와는 그렇게 많이 다른 모습을 나타내지 않습니다. 후자(그림 8.4)의 경우에는 계절성 차분을 구한 데이터로 결정했어야만 했고, 차분을 더 구하지 않아도 됐습니다. 전자(그림 8.3)의 경우에는 데이터에서 정상성(stationarity)이 충분히 나타나지 않아서 차분을 더 구해야 했습니다. 차분을 구하는 것에 대한 몇 가지 형식적인 검정을 아래에서 다룰 것이지만, 모델링 과정에서 항상 몇 가지 선택이 존재하고, 분석하는 사람마다 다른 선택을 할 수도 있습니다.

\(y'_t = y_t - y_{t-m}\)가 계절성 차분(seasonal difference)을 구한 시계열을 나타낸다면, 두 번 차이를 구한 시계열은 다음과 같습니다. \[\begin{align*} y''_t &= y'_t - y'_{t-1} \\ &= (y_t - y_{t-m}) - (y_{t-1} - y_{t-m-1}) \\ &= y_t -y_{t-1} - y_{t-m} + y_{t-m-1}\: \end{align*}\] 계절성 차분과 1차 차분을 둘 다 적용할 때, 어떤 것을 먼저 적용하더라도 차이는 없습니다 — 결과가 같을 것입니다. 하지만, 데이터에 계절성 패턴이 강하게 나타나면, 계절성 차분을 먼저 계산하는 것을 추천합니다. 왜냐하면, 때때로 결과 시계열에서 정상성이 나타나기도 해서 이런 경우에는 1차 차분을 구할 필요가 없게 되기 때문입니다. 1차 차분을 먼저 계산했다면, 여전히 남아있는 계절성이 나타날 것입니다.

차분을 구했다면, 차분 값이 해석 가능할 것이라는 것은 중요합니다. 첫 번째 차분값은 한 관측값과 그 다음 관측값 사이의 변화입니다. 계절성 차분값은 한 해와 그 다음 해 사이의 변화입니다. 다른 시차값(lagged value)은 직관적으로 해석하기가 쉽지 않기 때문에 사용하지 않는 것이 좋습니다.

단위근검정

단위근검정(unit root tests)은 더 객관적으로 차분을 구하는 것이 필요할 지 결정하기 위해 사용하는 한 가지 방법입니다. 차분을 구하는 것이 필요한지 결정하는 상황을 위해 설계된 통계적 가설 검정들이 존재합니다.

사용할 수 있는 단위근검정은 다양하고, 서로 다른 가정에 기초하고 있으며, 상반되는 답을 낼 수도 있습니다. 분석 과정에서 퀴아트코프스키-필립스-슈미트-신(Kwiatkowski-Phillips-Schmidt-Shin) (KPSS) 검정 (Kwiatkowski, Phillips, Schmidt, & Shin, 1992)을 사용하겠습니다. 이 검정은 데이터에 정상성이 나타난다는 것이 귀무가설(null hypothesis)이고, 귀무 가설이 거짓이라는 증거를 찾으려고 합니다. 결과적으로, 작은 p-값(예를 들면, 0.05보다 작은)은 차이를 구하는 것이 필요하다는 것을 나타냅니다. 검정은 urca 패키지ur.kpss() 함수를 사용하여 수행할 수 있습니다.

예를 들어, 이것을 구글 주식 가격 데이터에 적용해봅시다.

library(urca)
goog %>% ur.kpss() %>% summary()
#> 
#> ####################### 
#> # KPSS Unit Root Test # 
#> ####################### 
#> 
#> Test is of type: mu with 7 lags. 
#> 
#> Value of test-statistic is: 10.72 
#> 
#> Critical value for a significance level of: 
#>                 10pct  5pct 2.5pct  1pct
#> critical values 0.347 0.463  0.574 0.739

검정 통계가 1% 임계값보다 훨씬 큽니다. 이것은 귀무가설(null hypothesis)이 기각된다는 것을 의미합니다. 즉, 데이터가 정상성(stationarity)을 가지고 있지 않습니다. 데이터에 차분을 수행할 수 있고 검정을 다시 적용할 수 있습니다.

goog %>% diff() %>% ur.kpss() %>% summary()
#> 
#> ####################### 
#> # KPSS Unit Root Test # 
#> ####################### 
#> 
#> Test is of type: mu with 7 lags. 
#> 
#> Value of test-statistic is: 0.0324 
#> 
#> Critical value for a significance level of: 
#>                 10pct  5pct 2.5pct  1pct
#> critical values 0.347 0.463  0.574 0.739

이번에는 검정 통계가 작고, 정상성(stationarity)이 나타나는 데이터에서 볼 수 있는 것처럼 범위 안에 잘 들어갑니다. 따라서 차분을 구한 데이터가 정상성을 나타낸다고 결론 내릴 수 있습니다.

1차 차분의 적당한 횟수를 결정하기 위해 여러번의 KPSS 검정을 사용하는 이 과정을 ndiffs()로 수행할 수 있습니다.

ndiffs(goog)
#> [1] 1

위의 KPSS 검정들에서 본 것처럼, goog 데이터가 정상성을 나타내도록 하려면 한 번의 차분(difference)이 필요합니다.

계절성 차분(seasonal difference)이 필요한지 결정하기 위한 비슷한 함수는 nsdiffs()입니다. 이 함수는 필요한 계절성 차분의 적당한 횟수를 결정하기 위해 6.7 절에서 소개한 계절성 강도 측정량을 사용합니다. \(F_S<0.64\)이면, 계절성 차분이 필요없다고 알려주고, 이외의 경우에는 하나의 계절성 차분이 필요하다 알려줍니다.

nsdiffs()를 미국 월별 전력 데이터에 로그를 씌운 결과에 적용할 수 있습니다.

usmelec %>% log() %>% nsdiffs()
#> [1] 1
usmelec %>% log() %>% diff(lag=12) %>% ndiffs()
#> [1] 1

nsdiffs()의 결과가 1이기 때문에(이것은 한 번 계절성 차분이 필요하다는 것을 가리킵니다), ndiffs() 함수를 계절성 차분을 구한 데이터에 적용합니다. 이러한 함수는 계절성 차분과 1차 차분 둘 다 수행해야한다는 것을 나타냅니다.

참고 문헌

Kwiatkowski, D., Phillips, P. C. B., Schmidt, P., & Shin, Y. (1992). Testing the null hypothesis of stationarity against the alternative of a unit root: How sure are we that economic time series have a unit root? Journal of Econometrics, 54(1-3), 159–178. https://doi.org/10.1016/0304-4076(92)90104-Y


  1. 더 정확하게는, \(\{y_t\}\)정상성을 나타내는 시계열이라면, 모든 \(s\)에 대해, \((y_t,\dots,y_{t+s})\)의 분포가 \(t\)에 무관합니다.↩︎