차분을 하는 이유는 non-stationary한 데이터를 차분을 통해 stationary하게 만들어주는 것이다.
데이터를 안정화하는 작업은 제곱, 로그화, 루트, 차분이 있는데 이번에는 차분을 해볼 것이다.
정상성에 대해서는 다음 포스트를 참고하면 된다.
2022.01.19 - [공부/모델링] - Stationary test (정상성 검정) python
이번에는 정상성 검정 포스트에서 다룬 데이터를 기반으로 차분을 진행해 볼 것이다.
차분은 t 시점의 데이터가 t-1 시점 데이터에 비해 얼마나 증감했는지 알 수 있게 된다.
식은 다음과 같다.
식을 보면 알 수 있듯, k개의 시점이 있는 데이터에서 1차 차분을 진행하게 되면, 총 n 개의 데이터가 소실되는 단점이 존재한다.
1차 차분에 대한 식은 다음과 같다.
이를 파이썬으로 확인해보자
데이터는 앞 포스트와 동일한 divvy_data를 활용하였다.
rides = data["rides"].to_frame(name="rides") # 데이터의 행을 역순으로 뒤집는 부분
rides = rides.loc[::-1]
rides["lag_1"] = rides["rides"].shift(periods=1)
print(rides)
>>>
rides lag_1
date
12/31/2017 593 NaN
12/30/2017 519 593.0
12/29/2017 1049 519.0
12/28/2017 1267 1049.0
12/27/2017 1117 1267.0
... ... ...
1/5/2014 32 1.0
1/4/2014 181 32.0
1/3/2014 6 181.0
1/2/2014 111 6.0
1/1/2014 95 111.0
shift함수를 통해 t기의 데이터를 t-1기로 밀어낸 부분이다. 따라서 index의 값은 lag_1에서 하나씩 밀린 것을 확인할 수 있다.
그렇다면 이번엔 차분을 해보자.
차분은 직접 빼는 부분 (diff_1 = rides column - lag_1 column) & diff 함수를 이용한 부분으로 데이터를 구해보았다.
rides['직접 구한 diff_1'] = rides['rides'] - rides['lag_1']
rides['함수로 구한 diff_1'] = rides['rides'].diff(1)
print(rides)
>>>
rides lag_1 직접 구한 diff_1 함수로 구한 diff_1
date
12/31/2017 593 NaN NaN NaN
12/30/2017 519 593.0 -74.0 -74.0
12/29/2017 1049 519.0 530.0 530.0
12/28/2017 1267 1049.0 218.0 218.0
12/27/2017 1117 1267.0 -150.0 -150.0
... ... ... ... ...
1/5/2014 32 1.0 31.0 31.0
1/4/2014 181 32.0 149.0 149.0
1/3/2014 6 181.0 -175.0 -175.0
1/2/2014 111 6.0 105.0 105.0
1/1/2014 95 111.0 -16.0 -16.0
즉, 1차 차분을 하는 방식은 lag_1로 데이터를 하나씩 미룬다음 그것을 직접 뺴주는 방법이라고 보면 된다.
2차 차분의 경우, 거의 사용할 일은 없다. 하지만 식을 보면 다음과 같이 쓸 수 있다.
따라서 이를 파이썬으로 구현하면 다음과 같다. (기존에는 lag_2로 단순히 시기를 2단계 미뤄서 진행했었는데, 이 부분이 잘못되었다고 지적해주시는 분 덕분에 올바르게 수정할 수 있게되었음)
# 앞서 1차 차분에서 진행했던 값의 컬럼을 변경해주고 drop한다
rides["diff_1"] = rides["함수로 구한 diff_1"]
rides = rides.drop(columns=['함수로 구한 diff_1', '직접 구한 diff_1'])
# 2차 차분을 시행하기 위해 1차 차분 값을 lag=1 적용하여 미뤄준다
rides['diff_1 + lag_1'] = rides['diff_1'].shift(1)
# 2차 차분값 도출
rides['diff_1 + lag_1'] = rides['diff_1'].shift(1)
rides['직접 구한 diff_2'] = rides['diff_1'] - rides['diff_1 + lag_1']
rides['함수로 구한 diff_2'] = rides['rides'].diff().diff()
print(rides)
>>>
rides lag_1 diff_1 diff_1 + lag_1 직접 구한 diff_2 함수로 구한 diff_2
date
12/31/2017 593 NaN NaN NaN NaN NaN
12/30/2017 519 593.0 -74.0 NaN NaN NaN
12/29/2017 1049 519.0 530.0 -74.0 604.0 604.0
12/28/2017 1267 1049.0 218.0 530.0 -312.0 -312.0
12/27/2017 1117 1267.0 -150.0 218.0 -368.0 -368.0
... ... ... ... ... ... ...
1/5/2014 32 1.0 31.0 -830.0 861.0 861.0
1/4/2014 181 32.0 149.0 31.0 118.0 118.0
1/3/2014 6 181.0 -175.0 149.0 -324.0 -324.0
1/2/2014 111 6.0 105.0 -175.0 280.0 280.0
1/1/2014 95 111.0 -16.0 105.0 -121.0 -121.0
그러면 차분을 했던 데이터의 정상성을 검정해보자
diff_data = data['rides'].diff(1).dropna()
# 표 그리기
plt.figure(figsize=(16,9))
plt.plot(diff_data.values, alpha=.7)
plt.hlines(y=diff_data.mean(), xmin=-50, xmax=1500, colors='red', linestyles='dashed')
plt.ylabel('divvy_rider')
plt.show()
추가)
2차차분에 대한 시각화는 다음과 같다.
diff_data = data['rides'].diff().diff().dropna()
# 표 그리기
plt.figure(figsize=(16,9))
plt.plot(diff_data.values, alpha=.7)
plt.hlines(y=diff_data.mean(), xmin=-50, xmax=1500, colors='red', linestyles='dashed')
plt.ylabel('divvy_rider')
plt.show()
ADF, KPSS 검정은 앞 포스트를 참고하면 된다.
adf_test(diff_data)
>>>
Results of Dickey-Fuller Test:
Test Statistic -9.252496e+00
p-value 9.827854e-14
Lags Used 2.100000e+01
Number of Observations Used 1.435000e+03
Critical Value (1%) -3.965093e+00
Critical Value (5%) -3.413554e+00
Critical Value (10%) -3.128854e+00
dtype: float64
정상시계열이 아니라는 귀무가설을 5.0%의 유의수준으로 기각할 수 있으므로 해당 데이터는 정상성이 보장됩니다.
kpss_test(diff_data)
>>>
Results of KPSS Test:
Test Statistic 0.043502
p-value 0.100000
Lags Used 52.000000
Critical Value (10%) 0.119000
Critical Value (5%) 0.146000
Critical Value (2.5%) 0.176000
Critical Value (1%) 0.216000
dtype: float64
정상시계열이 맞다는 귀무가설을 5.0%의 유의수준으로 기각할 수 없으므로 해당 데이터는 정상성이 보장됩니다.
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/statsmodels/tsa/stattools.py:2015: InterpolationWarning: The test statistic is outside of the range of p-values available in the
look-up table. The actual p-value is greater than the p-value returned.
이렇게 이번에는 차분을 통해서 비정상 시계열을 안정화하는 작업을 해보았다. (물론 정상화를 위해서는 차분외에도 log 치환 등도 존재한다. 하지만 이번에는 차분만 다루는 것으로 하였다)
다음글에서 ACF가 이어집니다.
2022.01.20 - [공부/모델링] - ACF (auto-correlative function, 자기상관함수) python
'공부 > 통계학' 카테고리의 다른 글
PACF (Partial Auto Correlation Function, 편자기상관함수) python (0) | 2022.01.20 |
---|---|
ACF (auto-correlative function, 자기상관함수) python (0) | 2022.01.20 |
Stationary test (정상성 검정) python (0) | 2022.01.19 |
Stepwise Feature Selection (단계선택법) python (0) | 2022.01.14 |
Backward Feature Selection (후진제거법) python (0) | 2022.01.13 |
댓글