사용한 데이터는 제주관광공사의 입도객 데이터 입니다. (대학교 캡스톤 project)

from statsmodels.tsa.stattools import kpss
total_series = df['total'].dropna()
kpss_stat, p_value, lags, critical_values = kpss(total_series, regression='c')
kpss_result = {
'KPSS Statistic': kpss_stat,
'p-value': p_value,
'Lags Used': lags,
'Critical Values': critical_values
}
kpss_result

귀무가설: 정상시계열이다.
대립가설: 비정상시계열이다.
충격후 구간을 세분화 하는 방법 세그먼트 회귀
세그먼트 회귀(Segmented Regression) 는 Interrupted Time Series (ITS) 분석의 한 기법으로, 시간에 따른 데이터 경향이 특정 시점에서 충격이나 정책 변화로 인해 변화할 때, 그 전후의 데이터를 각각 별도로 분석하는 방법이다. 이 기법은 주로 정책 변화나 외부 이벤트가 변수(종속 변수)에 미치는 영향을 정량적으로 분석할 때 사용된다.
세그먼트 회귀는 다중 회귀 모델의 확장이다. 충격 시점을 기준으로 두 개의 회귀선을 사용해 각 구간의 경향을 추정한다. 모델의 일반적인 형태는 다음과 같다.

import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
df = pd.read_csv('/Users/jinsehyeon/Desktop/big1_data/jejuco.csv', encoding='cp949')
df['dateym'] = pd.to_datetime(df['dateym'])
df.set_index('dateym', inplace=True)
# 충격 변수 생성 (2020년 2월 기준)
df['intervention'] = (df.index >= '2020-02-01').astype(int)
df['time'] = np.arange(len(df))
df['time_after_intervention'] = df['time'] * df['intervention']
x = df[['time', 'intervention', 'time_after_intervention']]
x = sm.add_constant(x) # 상수항 추가
y = df['total']
# 세그먼트 회귀 모델 정의 및 학습
segment_model = sm.OLS(y, x).fit()
print(segment_model.summary())
plt.figure(figsize=(14, 7))
plt.plot(df.index, y, label='Actual Values', color='skyblue')
plt.plot(df.index, segment_model.predict(x), label='Segmented Regression Predictions', color='red', linestyle='--')
plt.axvline(pd.to_datetime('2020-02-01'), color='black', linestyle='--', label='COVID-19 Intervention')
plt.title('Segmented Regression Analysis: COVID-19 Impact')
plt.xlabel('Date')
plt.ylabel('Total')
plt.legend(loc='best')
plt.grid(True)
plt.show()


모든 변수의 p-값이 0.05 이하로 모델의 각 변수는 통계적으로 유의하다.
특히 충격 후 추세 변화(time_after_intervention)의 유의성이 확인된다(p = 0.007). 이는 COVID-19 이후 시간이 지남에 따라 추가적인 감소가 있음을 나타낸다.
하지만 더븐 왓슨의 결과에 따라 잔차에 자기상관이 존재할 가능성을 시사하고 있다.
ACF 그래프 확인
from statsmodels.graphics.tsaplots import plot_acf
plt.figure(figsize=(10, 6))
plot_acf(segment_model.resid, lags=30, alpha=0.05) # 30 lags까지 ACF 플롯
plt.title('ACF of Residuals')
plt.show()

ACF 그래프의 결과 자기상관이 존재한다. 플랏을 확인해보면 시차 1에서 신뢰구간을 벗어나는것을 확인 할 수 있는데 따라서 GEE모델에 AR(1)을 파라미터로 주고 세그먼트 회귀를 같이 사용하여 이를 보완하는 방법이 있다.
GEE(Generalized Estimating Equations): 반복 측정 데이터나 패널 데이터의 분석에 사용되는 강력한 회귀 기법이다. 여러 시점에 걸쳐 같은 개체(환자, 기관 등)에서 수집된 데이터에 내재된 상관관계를 처리하는 데 유용하고. GEE 모델은 주로 시계열 분석이나 반복 측정 설계에서 데이터의 시간적 의존성을 반영하는 데 활용된다.
GEE는 시계열 데이터 분석에서 반복 측정된 시간 시리즈나 복잡한 상관구조를 다루는 데 적합하다. 특히 장기적인 상관성을 갖는 데이터, 예를 들어 환자의 치료 과정 또는 정책 도입 전후의 경제 지표를 분석할 때 유용하다.
시계열 데이터에서 GEE를 활용하는 경우:
실제 적용
import pandas as pd
import numpy as np
import statsmodels.api as sm
from statsmodels.genmod.generalized_estimating_equations import GEE
from statsmodels.genmod.families import Gaussian
from statsmodels.genmod.cov_struct import Autoregressive
df = pd.read_csv('/Users/jinsehyeon/Desktop/big1_data/jejuco.csv', encoding='cp949')
df['dateym'] = pd.to_datetime(df['dateym'])
df.set_index('dateym', inplace=True)
# 2. 충격 변수 생성 (2020년 2월 기준)
df['intervention'] = (df.index >= '2020-02-01').astype(int)
# 3. 시간 변수 및 상호작용 변수 추가
df['time'] = np.arange(len(df))
df['time_after_intervention'] = df['time'] * df['intervention']
x = df[['time', 'intervention', 'time_after_intervention']]
x = sm.add_constant(x) # 상수항 추가
y = df['total']
df['block'] = np.floor(np.arange(len(df)) / 12) # 매 12개월을 한 그룹으로 설정
gee_model = GEE(
y, x, groups=df['block'], family=Gaussian(), cov_struct=Autoregressive()
) #자기회귀 사용
gee_result = gee_model.fit()
print(gee_result.summary())
충격 시점(intervention)을 2020년 2월(한국에서 코로나 확진 시작)로 설정.
시간 변수(time, time_after_intervention)를 생성해 충격 전후의 경향을 분석.

COVID-19 충격의 부정적 영향: 충격 이후 총량의 감소가 명확하게 나타남
시간 경과에 따른 회복 여부 불명확: 충격 이후 시간이 지남에 따라 총량이 추가적으로 감소하는 경향은 보였지만, 통계적으로 유의하지 않아 확신할 수 없다.
y_pred = gee_result.predict(X)
# 시각화
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['total'], label='Actual Values', color='blue')
plt.plot(df.index, y_pred, label='GEE + Segmented Predictions', color='red', linestyle='--')
plt.axvline(pd.to_datetime('2020-02-01'), color='green', linestyle='--', label='Intervention Point')
# 그래프 레이아웃 설정
plt.title('GEE + Segmented Regression Predictions')
plt.xlabel('Date')
plt.ylabel('Total')
plt.legend(loc='best')
plt.grid(True)
plt.show()
