일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 시간형식변환
- Python
- 파이프라인전처리
- 응용이 보이는 선형대수
- adf_test
- loess
- pandas
- seaborn # kdeplot # 데이터분석
- 시계열시각화
- 시계열 #reindex #인덱스 확장 #datetime index #index extention # 데이터전처리
- pandas # 월말 날짜 # 마지막 주 # 날짜계산 # 시계열 # 마지막 주 금요일
- 빈 데이터프레임 #pandas #데이터전처리
- np.split
- stl
- 시계열데이터셋
- 날짜파싱
- timeseries decomposition
- 시계열분해
- 확률
- 플로틀리
- 시계열모듈
- 리눅스개념
- 시계열
- 크롤링자동화
- 이수역 양식집
- 시간형식
- 오제이튜브
- 음수값 #전처리 #선형보간 #pandas #데이터 #데이터분석
- 짧은 시계열 # 금융시계열
- 년월일 데이터
- Today
- Total
먼지뭉치 Data Analysis
[시계열 분석] 정상성이란? 본문
* 공부한 걸 정리한 글이므로 틀린 내용이 있을 수 있습니다.
* 글을 계속 수정하며 업데이트 할 예정입니다.
시계열 데이터 분석을 하기 전 시계열이 정상성을 가지는 지(stationary) 확인합니다.
평균과 분산이 일정해야 분석할 수 있다고 하는데 사실 와닿지 않았었습니다.
그래서 가장 간단한 시계열 AR(1) 이라고 가정하고 정상성일때와 아닐 때를 확인해보았습니다.
먼저 AR(1)의 식은 Yt = a * Yt-1 + white_noise 로 나타낼 수 있습니다.
식을 통해 기간은 2022년 1월1일 부터,
첫번째 Y[0]값을 2,
노이즈(white_noise)는 np.random.rand() 을 통한 난수로,
a(계수)에 따라 시계열 데이터를 만들어보려 합니다.
1. a = 0.9일때
num_timestep = 1000
np.random.seed(100)
time_range = pd.date_range(start='2022-01-01',periods=num_timestep)
# 계수가 0.9인 AR(1) 시계열
a = 0.9
c = 2
y = np.zeros(num_timestep)
y[0] = c
for t in range(1,num_timestep):
noise = np.random.randn()
y[t] = a*y[t-1] + noise
df = pd.DataFrame(y , index=time_range, columns=['y'])
# 시각화
plt.figure(figsize=(10,5),constrained_layout=True)
plt.plot(df['y'], label='y')
plt.xticks(rotation=30)
plt.title(f'AR(1): a = {a}')
plt.legend()
2. a = 1.2
위의 코드에서 앞의 계수값만 1이 넘는 값으로 설정해 보았습니다. 그랬더니 이상한 그래프가 나왔습니다. 분명 첫번째값 2로 넣었는데 왜 계속 0값이지... 라고 생각했지만
확인해보기위해 직접 앞의 0~20, 20~40 데이터를 직접 그려봤습니다. 그 결과 값이 엄청나게 빠르게 증가하고 있는 모습을 볼 수 있었습니다.
(다시 첫번째 그래프를 확인했더니 1e79 가 붙어있었군요..!)
보시다시피 그래프가 끝도 없이 올라가고 있습니다. 이런 데이터라면 분석이 의미가 없을 것 같네요.
3. a = -1.2
이번엔 절대값이 1이상인 음수 값을 넣어보았습니다. 앞의 그래프와 마찬가지로 엄청 큰값이 그래프에 그려졌네요.
마찬가지로 끊어서 그래프를 그려보았을때 양수와 음수를 차례대로 왔다갔다 하고 있는 모습입니다. 역시 값이 너무 커져서 분석을 할 수 없겠네요.
4. a= 1
앞의 경우 절대값이 1보다 컸을 때 데이터가 끝없이 발산한다는 사실을 알았습니다.
그렇다면 a=1 일때는 어떨까 궁금했습니다.
일정한 구간 내에서 데이터가 움직이지만 변동폭이 조금 큰 것 같네요.
정상성인지 아닌지에 대한 결과는 밑에서 확인하겠습니다.
* ADF test
ADF test 란 데이터가 정상성인지 판별해주는 통계적인 방법입니다.
Dicky-Fuller test가 AR(1) 시계열을 판별해주는 테스트이고
더 나아가 AR(2)이상의 시계열을 판별해주는 테스트가 Adjusted Dicky_Fuller test라고 합니다
귀무가설:
대립가설:
유투브에 좋은 adf test 설명 영상이 있어서 설명을 듣고 따라 코드를 쳐봤습니다.
ADF test 에 대한 통계적인 설명이 있으니 시간 있으신 분들은 한번 들어보시면 좋을 것 같습니다.
adfuller 함수를 사용하는 실습 코드입니다.
from statsmodels.tsa.stattools import adfuller
def perform_adf_test(series):
result = adfuller(series)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
영상에서는 AR(2)모형을 통해 시계열 데이터를 만들었습니다.
def make_AR_series(lags, coefs, length):
# 계수를 array 형태로
coefs = np.array(coefs)
# initial values: AR공식 처음 계산에 쓰이는 과거값(yt-1, yt-2, ...)
series = [np.random.normal() for _ in range(lags)]
for _ in range(length):
# 이전값 마지막 lag수 만큼 거꾸로
prev_val = series[-lags:][::-1]
# 노이즈
noise = np.random.normal()
# AR공식에 의한 새로운 값
new_val = np.sum(coefs * np.array(prev_val) ) + noise
series.append(new_val)
return series
* 정상성 테스트 결과 확인
(1) AR(1)
이 코드를 사용해서 앞에서 제가 구했던 AR(1) 시계열들이 정상(stationary)인지 확인해보겠습니다.
a 의 절대값이 1보다 같거나 크면 p-value값이 0.05이상으로 정상이 아님을 알 수 있습니다.
## lag1, a= 0.8 인 경우
series = make_AR_series(1, 0.8, 1000)
perform_adf_test(series)
# 출력값
ADF Statistic: -11.065879
p-value: 0.000000
## lag1, a= 1.2 인 경우
series = make_AR_series(1, 1.2, 100)
perform_adf_test(series)
# 출력값
ADF Statistic: 11.399264
p-value: 1.000000
## lag1, a= 1 인 경우
series = make_AR_series(1, 1, 100)
perform_adf_test(series)
# 출력값
ADF Statistic: -1.804719
p-value: 0.378122
(2) AR(2)
AR(2) 의 결과도 살펴보겠습니다. 계수가 0.5에서 조금만 넘어도 바로 정상성을 띄지 않게 되네요!
## lag2, a= 0.3, 0.5 인 경우
series = make_AR_series(2, [0.3,0.5], 1000)
perform_adf_test(series)
# 출력값
ADF Statistic: -9.052711
p-value: 0.000000
## lag2, a= 0.4, 0.6 인 경우
series = make_AR_series(2, [0.4,0.6], 1000)
perform_adf_test(series)
# 출력값
ADF Statistic: -1.638712
p-value: 0.462934
이번 포스팅에서는 정상성의 직관적인 의미를 한번 정리해보았습니다.
정상성 검증이 안되면 분석을 할 수 없다는 사실을 깨달았습니다. 앞으로 분석하기 전에 꼭 정상성 검증을 할 계획입니다!
감사합니다.
출처: https://www.youtube.com/watch?v=1opjnegd_hA
'데이터분석 > 시계열분석' 카테고리의 다른 글
[시계열 분석] 시계열분해(2) - 추세 구해보기(이동평균, Loess) (0) | 2023.01.18 |
---|---|
[시계열분석] 시계열 분해(1) - 시계열 성분과 분해방법 (0) | 2023.01.14 |
시계열 평가지표(Forecasting Metrics) 정리 (0) | 2022.12.31 |
[시계열 데이터수집] 크롤링 다음페이지 넘기기 (0) | 2022.12.27 |