Data Science

ADP 빅분기 이론과 Python 모듈, 실습코드 정리 - 통계편

지지플랏 2025. 4. 18. 16:17
반응형

ADP 시험을 준비하기 위하여 정리했던 방법론과 코드를 저장합니다.빅분기는 범위가 더 좁지만 공통된 부분이 많습니다.  선형계획법이나 기타 내용은 저도 몰라서 못넣었습니다 🤣 잘못된 내용이나 모호한 내용, 추가되어야하는 내용이 있으면 지적해주세요! 다들 시험에 합격하시길 바라요~


0. 목차

클릭시 해당 컨텐츠로 이동합니다.

      https://snowgot.tistory.com/189

       

      ADP 빅분기 이론과 Python 모듈, 실습코드 정리 - 머신러닝 편

      지난번 통계편에 이은 머신러닝문서입니다! 잘못된 내용이나 모호한 내용, 추가되어야하는 내용이 있으면 지적해주세요! 다들 시험에 합격하시길 바라요~0. 목차클릭시 해당 컨텐츠로 이동합니

      snowgot.tistory.com

      1. 모듈별 디렉토리 정리

      •  ADP 지원 버전: Python 3.7.(공지사항)
      • ADP 기본제공 Python Package & version
      pip install ipykernel=5.1.0
      pip install numpy==1.12.6
      pip install pandas==1.1.2
      pip install scipy==1.7.3
      pip install matplotlib==3.0.3
      pip install seaborn==0.9.0
      pip install statsmodels==0.13.2
      pip install pmdarima==2.0.1
      pip scikit-learn==0.23.2

      [제34회ADP실기]기본제공_python_package_list.txt
      0.01MB

      • 기본 모듈 로드
      # 일반모듈
      import warnings
      warnings.filterwarnings('ignore')
      import pandas as pd
      import numpy as np
      import os
      import datetime as dt
      
      # 머신러닝 - 전처리
      from sklearn.preprocessing import StandardScaler, MinMaxScaler, 
      LabelEncoder, OneHotEncoder, RobustScaler
      from sklearn.impute import SimpleImputer, KNNImputer
      from imblearn.over_sampling import SMOTE, RandomOverSampler
      from imblearn.under_sampling import RandomUnderSampler
      from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score, 
      KFold, StratifiedKFold
      
      # 머신러닝 - 모델
      from sklearn.linear_model import LogisticRegression, RidgeClassifier, LinearRegression, 
      Lasso, Ridge, ElasticNet
      from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, 
      RandomForestRegressor, GradientBoostingRegressor
      from sklearn.ensemble import VotingClassifier
      from sklearn.svm import SVC, SVR
      from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
      from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
      
      # 머신러닝 - 비지도
      from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
      from sklearn.decomposition import PCA
      
      # 머신러닝 - 평가
      from sklearn.metrics import (classification_report, confusion_matrix, 
      roc_auc_score, precision_recall_curve, auc,
      mean_squared_error, mean_absolute_error, r2_score, accuracy_score, 
      precision_score, recall_score, f1_score)
      
      from sklearn.metrics.pairwise import cosine_similarity
      
      # 시각화
      import matplotlib.pyplot as plt
      import seaborn as sns
      
      # 통계 - scipy
      import scipy.stats as stats
      from scipy.stats import ttest_ind, ttest_rel, f_oneway, chi2_contingency, 
      mannwhitneyu, wilcoxon, pearsonr, spearmanr, normaltest
      
      # 통계 - statsmodels
      import statsmodels.api as sm
      import statsmodels.formula.api as smf
      from statsmodels.stats.multicomp import pairwise_tukeyhsd
      from statsmodels.stats.outliers_influence import variance_inflation_factor
      from statsmodels.stats.diagnostic import het_breuschpagan
      
      # 시계열
      from statsmodels.tsa.stattools import adfuller, acf, pacf, kpss
      from statsmodels.tsa.seasonal import seasonal_decompose
      from statsmodels.tsa.arima.model import ARIMA
      from statsmodels.tsa.holtwinters import ExponentialSmoothing, SimpleExpSmoothing
      from statsmodels.tsa.statespace.sarimax import SARIMAX
      from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
      
      # pmdarima (자동 ARIMA)
      from pmdarima import auto_arima
      • 한글폰트 설정(선택사항)
      import matplotlib.pyplot as plt
      import platform
      
      def set_matplotlib_font():
          system = platform.system()
      
          if system == "Windows":
              plt.rc('font', family='Malgun Gothic')
          elif system == "Darwin":  # macOS
              plt.rc('font', family='AppleGothic')
          elif system == "Linux":
              plt.rc('font', family='NanumGothic')
          else:
              print("Unknown system. Please set font manually.")
      
          plt.rcParams['axes.unicode_minus'] = False
      
      # 폰트 설정 함수 호출
      set_matplotlib_font()

      1.1. datetime

      datetime
      │
      ├── datetime                   # 날짜와 시간을 모두 처리하는 클래스
      │   ├── now()                  # 현재 날짜와 시간을 반환
      │   ├── strptime()             # 문자열을 datetime 객체로 변환
      │   ├── strftime()             # datetime 객체를 문자열로 변환
      │   ├── year,month, day        # 년도, 월, 일 추출
      │   ├── hour,minute, second    # 시간, 분, 초 추출
      │   ├── date(), time()         # 날짜 (년, 월, 일)만, 시간 (시, 분, 초)만 반환
      │   ├── replace()              # 특정 날짜/시간 값을 변경하여 새로운 datetime 객체 반환
      │   ├── weekday()              # 요일 반환 (월: 0, 일: 6)
      │   └── combine()              # 날짜와 시간을 결합하여 새로운 datetime 객체 생성
      │
      ├── date                       # 날짜만 처리하는 클래스
      │   ├── today()                # 오늘 날짜 반환
      │   ├── fromisoformat()        # ISO 형식의 문자열에서 date 객체 생성
      │   ├── year,month, day        # 년도, 월, 일 추출
      │
      ├── time                       # 시간만 처리하는 클래스
      │   ├── hour,minute, second    # 시간, 분, 초 추출
      │   └── microsecond            # 마이크로초 추출
      │
      ├── timedelta                  # 두 날짜 또는 시간 간의 차이를 계산하는 클래스
      │   ├── days                   # 차이 나는 일수
      │   ├── seconds                # 차이 나는 초
      │   └── total_seconds()        # 총 차이 시간을 초 단위로 반환
      │
      └── timezone                   # 시간대 정보를 다루는 클래스
          ├── utc                    # UTC 시간대 객체
          └── tzinfo                 # 사용자 정의 시간대 설정을 위한 클래스

      1.2. numpy==1.21.6

      numpy
      │
      ├── 기본 통계 함수
      │   ├── mean()                 # 데이터의 평균값 계산
      │   ├── median()               # 데이터의 중앙값 계산
      │   ├── std()                  # 데이터의 표준편차 계산
      │   ├── var()                  # 데이터의 분산 계산
      │   ├── sum()                  # 데이터의 합계 계산
      │   ├── prod()                 # 데이터의 곱 계산
      │
      ├── 퍼센타일 및 백분위 함수
      │   ├── percentile()           # 데이터의 특정 퍼센타일 값 계산
      │   ├── quantile()             # 데이터의 특정 분위 값 계산
      │
      ├── 최소값/최대값 관련 함수
      │   ├── min()                  # 데이터의 최소값 반환
      │   ├── max()                  # 데이터의 최대값 반환
      │   ├── argmin()               # 최소값의 인덱스 반환
      │   ├── argmax()               # 최대값의 인덱스 반환
      │
      ├── 데이터 생성 및 처리 함수
      │   ├── histogram()            # 데이터의 히스토그램 계산
      │   ├── unique()               # 데이터에서 고유 값 반환
      │   ├── bincount()             # 정수 배열의 값의 빈도 계산
      │
      ├── 랜덤 데이터 생성 (통계적 실험 시 사용 가능)
      │   ├── random.randn()         # 표준 정규분포를 따르는 랜덤 값 생성
      │   ├── random.normal()        # 정규분포를 따르는 랜덤 값 생성
      │   ├── random.randint()       # 정수 범위에서 랜덤 값 생성
      │   ├── random.choice()        # 데이터에서 랜덤 샘플 추출

      1.3. scipy==1.7.3

      scipy
      │
      ├── stats                      # 통계 분석과 확률 분포 관련 함수 제공
      │   ├── norm                   # 정규분포 관련 함수 (PDF, CDF, 랜덤 샘플링 등)
      |   |── uniform                # 균등분포
      |   |── bernoulli              # 베르누이 분포
      |   |── binom                  # 이항분포
      │   ├── ttest_ind              # 독립 두 표본에 대한 t-검정
      │   ├── ttest_rel              # 대응표본 t-검정
      │   ├── mannwhitneyu           # Mann-Whitney U 비모수 검정
      │   ├── chi2_contingency        # 카이제곱 독립성 검정
      │   ├── shapiro                # Shapiro-Wilk 정규성 검정
      │   ├── kstest                 # Kolmogorov-Smirnov 검정 (분포 적합성 검정)
      │   ├── probplot               # Q-Q plot 생성 (정규성 시각화)
      │   ├── pearsonr               # Pearson 상관계수 계산
      │   ├── spearmanr              # Spearman 순위 상관계수 계산
      │   └── describe               # 기술 통계량 제공 (평균, 표준편차 등)
      │
      ├── optimize                   # 함수 최적화 및 곡선 피팅 관련 모듈
      │   ├── minimize               # 다변수 함수의 최소값을 찾는 최적화 도구
      │   ├── curve_fit              # 비선형 곡선 피팅 (최소제곱법 기반)
      │   └── root                   # 방정식의 근을 찾는 도구
      │
      ├── linalg                     # 선형대수 관련 함수
      │   ├── inv                    # 행렬의 역행렬 계산
      │   ├── det                    # 행렬식 계산
      │   └── svd                    # 특이값 분해(SVD) 수행
      │
      ├── interpolate                # 데이터 보간 관련 함수
      │   ├── interp1d               # 1차원 선형 보간 함수
      │   └── griddata               # 다차원 보간 수행 (비정형 데이터에 사용)
      │
      └── special                    # 특수 함수 (감마 함수, 베타 함수 등)
          ├── gamma                  # 감마 함수
          └── beta                   # 베타 함수

      1.4. pandas==1.1.2

      pandas
      │
      ├── melt: pivot 형태를 다시바꾸기
      │
      ├── DataFrame                  # 2차원 데이터 구조, 테이블 형태의 데이터 관리
      │   ├── groupby                # 데이터프레임 그룹핑
      │   ├── merge                  # SQL 스타일로 데이터프레임 병합
      │   ├── join                   # 데이터프레임 조인 (인덱스를 기준)
      │   ├── pivot_table            # 피벗 테이블 생성
      │   ├── apply                  # 사용자 정의 함수를 데이터프레임에 적용
      │   ├── isnull                 # 결측치 여부 확인
      │   ├── fillna                 # 결측치 대체
      │   └── drop                   # 행 또는 열 삭제
      │
      ├── Series                     # 1차원 데이터 구조, 배열 형태의 데이터 관리
      │   ├── value_counts           # 고유 값의 빈도수 반환
      │   └── unique                 # 고유 값 반환
      │
      ├── time_series                # 시계열 데이터 처리 도구
      │   ├── to_datetime            # 문자열을 날짜 형식으로 변환
      │   ├── resample               # 시계열 데이터 리샘플링
      │   ├── shift                  # 데이터를 앞이나 뒤로 이동
      │   └── rolling                # 이동 평균 등 롤링 윈도우 계산
      │
      └── plotting                   # 데이터 시각화 도구
          ├── plot                   # 라인 플롯, 기본 시각화 함수
          ├── hist                   # 히스토그램 생성
          ├── boxplot                # 박스 플롯 생성
          └── scatter                # 산점도 생성

      1.5. statsmodel==0.13.2

      statsmodels
      │
      ├── api                        # 주요 모듈에 접근하기 위한 API 제공
      │
      ├── stats                      # 통계적 테스트 및 유틸리티
      │   ├── diagnostic            # 모델 진단 도구 (자기상관, 이분산성 등)
      │   ├── stattools             # 통계 도구 (자기상관 함수, 부분자기상관 함수 등)
      │   ├── multivariate          # 다변량 통계 분석
      │   ├── anova                 # 분산 분석(ANOVA) 관련 함수
      │   │   ├── anova_lm          # 선형 모델에 대한 ANOVA 테이블
      │   │   └── multicomp         # 다중 비교 방법
      │   └── nonparametric         # 비모수 통계 검정 (KDE, 커널 회귀 등)
      │
      ├── duration                   # 생존 분석(Survival Analysis) 관련 모듈
      │   ├── hazard_regression     # 위험 회귀 모델
      │   │   ├── cox               # Cox 비례 위험 모델
      │   │   └── phreg             # 비례 위험 회귀 모델
      │   ├── survfunc              # 생존 함수 추정 (Kaplan-Meier 등)
      │   │   ├── kaplan_meier      # 카플란-마이어 추정량
      │
      ├── tsa                        # 시계열 분석(Time Series Analysis) 관련 모듈
      │   ├── arima                  # ARIMA 모델 구현
      │   ├── statespace            # 상태 공간 모델 (State Space Models)
      │   ├── vector_ar             # 벡터 자기회귀(VAR) 모델
      │   ├── seasonal              # 계절성 분해 (SARIMAX 등)
      │   └── filters               # 칼만 필터, HP 필터 등

      1.6. sklearn==0.23.2

      scikit-learn
      │
      ├── model_selection          # 모델 평가, 검증, 및 데이터 분할
      │   ├── train_test_split      # 데이터를 훈련 세트와 테스트 세트로 분할
      │   ├── cross_val_score       # 교차 검증 점수 계산
      │   ├── GridSearchCV          # 하이퍼파라미터 최적화
      │   └── KFold                 # K-폴드 교차 검증
      │
      ├── preprocessing             # 데이터 전처리 및 스케일링
      │   ├── StandardScaler        # 데이터 표준화 (평균 0, 표준편차 1로 스케일링)
      │   ├── MinMaxScaler          # 데이터 값을 0과 1 사이로 스케일링
      │   ├── LabelEncoder          # 범주형 데이터를 숫자로 변환
      │   └── OneHotEncoder         # 범주형 데이터를 원-핫 인코딩
      │
      ├── decomposition             # 차원 축소 기법
      │   ├── PCA                   # 주성분 분석 (Principal Component Analysis)
      │   ├── TruncatedSVD          # 차원 축소 (Singular Value Decomposition)
      │   └── NMF                   # 비음수 행렬 분해 (Non-negative Matrix Factorization)
      │
      ├── metrics                   # 모델 평가 지표
      │   ├── accuracy_score        # 정확도 평가
      │   ├── confusion_matrix      # 혼동 행렬 계산
      │   ├── classification_report # 분류 모델 평가 보고서
      │   ├── roc_auc_score         # ROC AUC 점수 계산
      │   └── mean_squared_error    # 회귀 모델의 MSE 계산
      │
      ├── linear_model              # 선형 모델
      │   ├── LinearRegression      # 선형 회귀
      │   ├── LogisticRegression    # 로지스틱 회귀
      │   ├── Ridge                 # 릿지 회귀 (L2 정규화)
      │   ├── Lasso                 # 라쏘 회귀 (L1 정규화)
      │   └── ElasticNet            # 엘라스틱넷 회귀 (L1 + L2 정규화)
      │
      ├── ensemble                  # 앙상블 학습
      │   ├── RandomForestClassifier# 랜덤 포레스트 분류기
      │   ├── GradientBoostingClassifier # 그래디언트 부스팅 분류기
      │   ├── RandomForestRegressor # 랜덤 포레스트 회귀
      │   └── GradientBoostingRegressor # 그래디언트 부스팅 회귀
      │
      ├── neighbors                 # 최근접 이웃 알고리즘
      │   ├── KNeighborsClassifier  # K-최근접 이웃 분류기
      │   ├── KNeighborsRegressor   # K-최근접 이웃 회귀
      │   └── NearestNeighbors      # 최근접 이웃 검색
      │
      ├── svm                       # 서포트 벡터 머신
      │   ├── SVC                   # 서포트 벡터 분류기
      │   └── SVR                   # 서포트 벡터 회귀
      │
      ├── tree                      # 결정 트리 알고리즘
      │   ├── DecisionTreeClassifier # 결정 트리 분류기
      │   └── DecisionTreeRegressor  # 결정 트리 회귀
      │
      └── cluster                   # 클러스터링 알고리즘
          ├── KMeans                # K-평균 클러스터링
          ├── DBSCAN                # 밀도 기반 클러스터링
          └── AgglomerativeClustering # 계층적 클러스터링

      2. 데이터 전처리

      • datetime 자료형
        • 날짜와 시간을 표현하는 자료형
        • datetime(2023, 10, 9, 14, 30, 0) # 2023-10-09 14:30:00
        • ts.to_pydatetime() 함수로 ts→ dt변환 가능
      • timstamp 자료형
        • 유닉스 타임 스탬프로, 1970년 1월 1일로부터 경과 시간을 측정
        • pd.Timestamp() 함수로 dt → ts 변환 가능
      • 문자형 자료형 -> datetime
        • pd.to_datetime('2020-01-01 01:00', format = ‘%Y-%m-%d %H:%M’)
      • 날짜의 기간별로 만들기
        • pd.date_range(start='2020-01-01', end='2020-01-31', freq = 'D')
      • 예시
      from datetime import datetime
      
      # 문자열을 datetime 객체로 변환
      date_string = '01/01/2018 00:15'
      date_object = datetime.strptime(date_string, '%m/%d/%Y %H:%M')
      
      # 년, 월, 일, 시간, 분 추출
      year = date_object.year
      month = date_object.month
      day = date_object.day
      hour = date_object.hour
      minute = date_object.minute
      • 특정 시간 기준으로 시간 간격 구하기
      #실용 예제1
      time_mid = '2024-10-09 00:00:00'
      from datetime import datetime
      time_stamp = datetime.strptime(time_mid, '%Y-%m-%d %H:%M:%S')
      (datetime.now() - time_stamp).total_seconds()/60
      
      #실용예제2
      from datetime import datetime
      y = df['datetime'] - df['datetime'].apply(lambda x : datetime.combine(x, datetime.min.time()))
      df['nsd'] = y.apply(lambda td :td.total_seconds()/60)
      • 피벗
      pd.pivot_table(values, index, columns, aggfunc='mean')
      • 언피벗
      pd.melt(id_vars = [기준컬럼], value_vars = [값컬럼], value_name = '값이름')
      • 머지
      pd.merge(df1, df2, how = 'left', on = 'key')

      3. 통계 추정

      3.1. 점 추정

      • 모수를 하나의 값으로 추정하는 방법
      • 모평균에 대한 점추정: $\bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_{i}$
      import numpy as np
      sample_mean = np.mean(data)
      • 모분산에 대한 점추정: $s^{2} = \frac{1}{n-1}\sum_{i=1}^{n}(x_{i} - \bar{x})^2$
        • n-1을 자유도로 나누어 불편성을 보장
      sample_std = np.var(data, ddof = 1) #자유도 n-1
      • 모비율에 대한 점추정: $p^{2} = \frac{x}{n}$
        • $x$: 표본의 사건 횟수
      x = np.sum(x)
      n = len(data)
      
      x/n

      3.2. 구간 추정

      • 모수가 특정 구간 내에 있을 것이라는 신뢰 구간을 제시하는 방법
      • 모평균에 대한 구간 추정
        • $\sigma^{2}$ Known: $ci = \bar{x} \pm z_{\frac{\alpha}{2}}(\frac{\sigma}{\sqrt{n}})$
        • $\sigma^{2}$ UnKnown: $ci = \bar{x} \pm t_{\frac{\alpha}{2}, n-1}(\frac{\sigma}{\sqrt{n}})$
      import numpy as np
      from scipy.stats import t
      
      # 신뢰수준 설정
      confidence_level = 0.95
      alpha = 1 - confidence_level
      
      # 1. 모분산을 알때
      z = stats.norm.ppf(1 - alpha/2)
      margin_of_error = z * (sample_std/np.sqrt(n))
      print(sample_mean- margin_of_error, sample_mean + margin_of_error)
      
      # 2. 모분산을 모를 때
      t_crit = t.ppf(1-alpha /2, df = n-1)
      margin_of_error_t = t_crit *(sample_std/np.sqrt(n))
      print(sample_mean- margin_of_error_t, sample_mean + margin_of_error_t
      
      # 3. t.interval 사용
      stats.t.interval(confidnece_level, df = n-1, loc = sample_min, scale = sample_std/np.sqrt(n))
      • 모 분산에 대한 구간 추정
        • $\left( \frac{(n - 1) s^2}{\chi^2_{1 - \alpha/2, \; n - 1}}, \; \frac{(n - 1) s^2}{\chi^2_{\alpha/2, \; n - 1}} \right)$
      # 자유도
      df = n - 1
      
      # 카이제곱 값 계산
      chi2_lower = stats.chi2.ppf(alpha / 2, df)
      chi2_upper = stats.chi2.ppf(1 - alpha / 2, df)
      
      # 신뢰구간 계산
      lower_bound = (df * sample_variance) / chi2_upper
      upper_bound = (df * sample_variance) / chi2_lower
      
      print(f"{confidence_level*100}% 신뢰구간: ({lower_bound}, {upper_bound})")
      • 모 비율에 대한 구간 추정
        • $\hat{p} \pm z_{\alpha/2}\sqrt{\frac{\hat{p}(1-\hat{p})}{n}}$
      from statsmodels.stats.proportion import proportion_confint
      # 성공 횟수와 전체 시행 횟수
      x = np.sum(data)  # 성공 횟수
      n = len(data)     # 전체 시행 횟수
      
      lower_bound, upper_bound = proportion_confint(success_count, n, alpha=alpha, method='normal')
      
      print(f"{confidence_level*100}% 신뢰구간: ({lower_bound}, {upper_bound})")

      4. 통계 검정 - 모수적 방법

      통계 검정에 대한 마인드맵은 다음 글 참고하세요

      https://snowgot.tistory.com/153

       

      (8) Khan Academy: 유의성 검정과 절차, 통계방법론 정리

      이번 글에서는 추론통계의 핵심 유의성 검정과 등장하는 개념, 그리고 일반적인 통계방법론을 정리해본다.1. 글목차유의성 검정에 필요한 개념1종오류와 2종오류유의성 검정 절차통계검정 절차

      snowgot.tistory.com

      • 정규성 검정
        • $H_o:$ 데이터가 정규분포를 따른다.
        • $H_1:$ 데이터가 정규분포를 따르지 않는다.
        1. shapiro-wilk : 작은 표본(n≤ 50) 에 적합
        2. Kolmogorov-Smirnov: 표본이 클 때 사용, shaprio보다 덜 강력
      • t-test검정을 위한 정규성을 시행할 시, 두 그룹 중에 하나라도 정규성을 만족하지 않으면 바로 맨-휘트니 방법으로 넘어감
      #정규성 검정 - Shapiro-Wilk
      from scipy.stats import shapiro
      statistic, p_value = shapiro(data)
      
      #정규성 검정 - Kolmogorov-Smirnov 검정 
      from scipy.stats import kstest
      statistic, p_value = kstest(data, 'norm')
      
      print(f"Test Statistic: {statistic}")
      print(f"p-value: {p_value}")
      
      if p_value > alpha:
          print("정규성을 따른다고 볼 수 있습니다.")
      else:
          print("정규성을 따른다고 볼 수 없습니다.")
      • 시각화 예제
      from scipy.stats import shapiro, probplot
      import matplotlib.pyplot as plt
      import seaborn as sns
      
      man = df3[df3['성별'] =='남']['급여']
      woman = df3[df3['성별'] =='여']['급여']
      
      # Shapiro-Wilk test
      statistic_m, p_value_m = shapiro(man)
      statistic_w, p_value_w = shapiro(woman)
      
      # Figure 생성
      plt.figure(figsize=(12, 6))
      
      # 1. 남성 그룹 히스토그램과 Q-Q plot
      plt.subplot(2, 2, 1)
      sns.histplot(man, kde=True, label='man', color='blue')
      plt.title(f'Man Salary Distribution\nShapiro p-value: {p_value_m:.3f}')
      plt.legend()
      
      plt.subplot(2, 2, 2)
      probplot(man, dist="norm", plot=plt)
      plt.title('Man Q-Q Plot')
      
      # 2. 여성 그룹 히스토그램과 Q-Q plot
      plt.subplot(2, 2, 3)
      sns.histplot(woman, kde=True, label='woman', color='green')
      plt.title(f'Woman Salary Distribution\nShapiro p-value: {p_value_w:.3f}')
      plt.legend()
      
      plt.subplot(2, 2, 4)
      probplot(woman, dist="norm", plot=plt)
      plt.title('Woman Q-Q Plot')
      
      plt.tight_layout()
      plt.show()
      • 등분산 검정
        • $H_o:$ 두 집단의 분산이 같다.
        • $H_1:$ 두 집단의 분산이 다르다.
      검정 이름 정규성 가정 이상치에 대한 민감도 특징
      Levene 필요 없음 중간 여러 그룹의 분산이 동일한지 검정
      Bartlett 필요함 민감함 정규성 만족 시 Levene보다 검정력 높음
      Fligner 필요 없음 강건함 순위 기반 비모수 검정, 이상치 존재 시 유리
      from scipy.stats import levene, bartlett, fligner
      
      statistic, p_value = levene(data1, data2)
      # statistic, p_value = bartlett(data1, data2)
      # statistic, p_value = fligner(data1, data2)
      • 일표본 t 검정
        • $H_o:$ 표본의 평균이 특정 값과 같다.
        • $H_1:$ 표본의 평균의 특정 값과 같지 않다.
      • 이표본 t 검정
        • $H_o:$ 두 집단의 평균이 같다.
        • $H_1:$ 두 집단의 평균이 다르다.
      이표본 t검정일 때 정규성 & 등분산 검정을 진행하게 되는데, 등분산일 경우 두 표본의 분산을 하나로 합쳐서 추정하는 "합동 분산"활용이 가능해짐. 이는 검정통계량의 분산을 하나로 합치게 되고 좀 더 정확한 추정이 가능하게함. 하지만 등분산이 만족되지 않은 경우 비모수 검정인 맨-휘트니를 진행함
      # 독립표본 t 검정
      from scipy.stats import ttest_ind,ttest_rel
      # 등분산성을 만족하는 경우
      statistic, p_value = ttest_ind(data1, data2, equal_var=True)
      # 등분산성을 만족하지 않는 경우
      # statistic, p_value = ttest_ind(data1, data2, equal_var=False)
      
      #대응표본 t검정
      # statistic, p_value = ttest_rel(data_before, data_after)
      
      print(statistic, p_value)
      • 분산 분석
        • 목적: 그룹간 분산과그룹내 분산을 비교
        • $H_0:$ 모든 그룹의 평균값이 같다.
        • $H_1:$ 적어도 하나 그룹의 평균값이 다른 그룹과 다르다.
      import pandas as pd
      import numpy as np
      
      # 그룹별 데이터 생성 (예시 데이터)
      np.random.seed(123)
      
      group_A = np.random.normal(loc=50, scale=5, size=30)
      group_B = np.random.normal(loc=55, scale=5, size=30)
      group_C = np.random.normal(loc=60, scale=5, size=30)
      
      # 데이터 프레임 생성
      df = pd.DataFrame({
          'score': np.concatenate([group_A, group_B, group_C]),
          'group': ['A'] * 30 + ['B'] * 30 + ['C'] * 30
      })
      
      import statsmodels.api as sm
      from statsmodels.formula.api import ols
      
      # ANOVA 모델 생성
      model = ols('score ~ C(group)', data=df).fit()
      
      # 분산분석표 생성
      anova_table = sm.stats.anova_lm(model, typ=2)
      
      # 결과 출력
      print(anova_table)
      • 사후 분석
        • Tukey’s HSD 검정
      from statsmodels.stats.multicomp import pairwise_tukeyhsd
      
      # 일원분산분석의 사후분석 예시
      tukey_result = pairwise_tukeyhsd(endog=df['score'], groups=df['group'], alpha=0.05)
      
      print(tukey_result)
      • two-way anova
      import statsmodels.api as sm
      from statsmodels.formula.api import ols
      
      # 이원분산분석 모델 생성 (교호작용 포함)
      model = ols('값 ~ C(요인1) * C(요인2)', data=df).fit()
      
      # 분산분석표 생성
      anova_table = sm.stats.anova_lm(model, typ=2)
      # 결과 출력
      print(anova_table)
      • Welch Anova
        • 목적: 그룹 간의 등분산성이 가정이 필요없는 경우 사용
        • $H_0:$ 모든 그룹의 평균이 같다.
        • $H_1:$ 적어도 하나 그룹의 평균값이 다른 그룹과 다르다.
      import numpy as np
      import pandas as pd
      import scipy.stats as stats
      import statsmodels.api as sm
      from statsmodels.formula.api import ols
      
      # 기술 통계량 확인
      print(data.groupby('group').agg(['mean', 'std', 'count']))
      
      # 등분산성 검정 (Levene's test)
      levene_stat, levene_p = stats.levene(group1, group2, group3)
      print(f"\nLevene's test: statistic={levene_stat:.4f}, p-value={levene_p:.4f}")
      if levene_p < 0.05:
          print("The variances are significantly different. Welch ANOVA is appropriate.")
      else:
          print("The variances are not significantly different. Standard ANOVA can be used.")
      
      # Welch ANOVA 수행
      welch_stat, welch_p = stats.f_oneway(group1, group2, group3, welch=True)
      print(f"\nWelch ANOVA: F-statistic={welch_stat:.4f}, p-value={welch_p:.4f}")
      
      if welch_p < 0.05:
          print("Reject null hypothesis: At least one group mean is different.")
      else:
          print("Fail to reject null hypothesis: No significant difference between group means.")
      
      # 사후 검정 (Games-Howell post-hoc test)
      from statsmodels.stats.multicomp import pairwise_tukeyhsd
      # 참고: statsmodels에는 Games-Howell 검정이 직접 구현되어 있지 않아 Tukey HSD를 대신 사용
      # 실제 연구에서는 Games-Howell 테스트 사용 권장 (등분산 가정 필요 없음)
      tukey_results = pairwise_tukeyhsd(data['value'], data['group'], alpha=0.05)
      print("\nPost-hoc test (Tukey HSD, note: Games-Howell would be better for unequal variances):")
      print(tukey_results)

      4. 통계검정 - 비모수적 방법

      4.1. 비모수방법 표 정리

      • 데이터가 특정 분포를 따르지 않거나 데이터 양이 적어 분포가정을 만족시키기 어려울때 사용. 데이터의 순위나 중앙값을 사용
      검정명 대응 표본 그룹 수 데이터 예시 연관 있는 검정
      카이제곱 X 2 or 3 범주형 성별에 따른 선호도 차이 -
      피셔 정확검정 O 2 범주형 성공/실패 비율 비교 카이제곱
      맨 휘트니 X 2 연속형 두 집단의 성적 중앙값 비교 독립표본 t 검정
      크루스칼 왈리스 X 3이상 연속형 여러 그룹의 성적비교 ANOVA
      윌콕슨 O 2 연속형 치료 전후의 차이 대응표본 t검정
      맥니마 O 2 이항형 치료 전후의 호전 약화 여부 대응표본 카이제곱
      부호검정 O 2 연속형/이항형 치료 전후의 비율 변화 대응표본 t검정
      프리드먼 O 3이상 연속형 세 시점에서의 결과 비교 반복측정 ANOVA
      코크란Q O 3이상 이항형 세 시점에서의 성공/실패 비교 반복측정 카이제곱

      4.2. 카이제곱 검정

      1. 독립성 검정
      • $H_0$: 두 범주형 변수는 독립이다.
      • $H_1$: 두 범주형 변수는 독립이 아니다.

      2. 적합도 검정

      • 수식: $\chi^{2} = \sum^{n}{i}\frac{(O{i} - E_{i})^{2}}{E_{i}}$
      • $H_0$: 관측과 기대 비율은 차이가 없다.
      • $H_1$: 관측과 기대 비율은 차이가 있다.

      import numpy as np
      from scipy.stats import chisquare
      
      # 주장하는 방문 비율(%)을 기반으로 기대값을 계산
      expected_ratios = np.array([10, 10, 15, 20, 30, 15])
      total_visits = 200
      expected_counts = (expected_ratios / 100) * total_visits
      
      # 관찰된 방문 수
      observed_counts = np.array([30, 14, 34, 45, 57, 20])
      
      # 카이제곱 적합도 검정을 수행
      chi2_stat, p_val = chisquare(f_obs=observed_counts, f_exp=expected_counts)
      
      # 결과 출력
      print(f"Chi-squared Statistic: {chi2_stat:.3f}") # 11.442
      print(f"P-value: {p_val:.3f}") # 0.043

      3. 동질성 검정

      import numpy as np
      from scipy.stats import chi2_contingency
      
      # 관찰된 데이터: 각 학교에서 학생들이 선호하는 과목의 빈도수
      data = np.array([
          [50, 60, 55],  # 수학 선호
          [40, 45, 50],  # 과학 선호
          [30, 35, 40]   # 문학 선호
      ])
      
      # 카이제곱 통계량, p-value, 자유도, 기대값을 계산
      chi2_stat, p_val, dof, expected = chi2_contingency(data)
      
      # 결과 출력
      print(f"Chi-squared Statistic: {chi2_stat:.3f}"): 0.817
      print(f"P-value: {p_val:.3f}") : 0.936
      print(f"Degrees of Freedom: {dof:.3f}") # 0.400
      print("Expected frequencies:")
      print(expected.round(3))
      
      '''
      [[48.889 57.037 59.074]
       [40.    46.667 48.333]
       [31.111 36.296 37.593]]
      '''

      4.3. Wilcoxon 검정

      • 목적: 짝지어진 관측 값(대응 표본) 이 차이가 0이라는 가설 검정
      • 가정: 데이터는 연속적이거나 ordinal, 데이터는 대칭
      • $H_o:$ 두 그룹의 중앙값 차이는 0이다.
      • $H_1:$ 두 그룹의 중앙값 차이는 0이 아니다.
      from scipy.stats import wilcoxon
      
      # 예시 데이터 (대응 표본)
      before = [20, 21, 22, 23, 24, 25]
      after = [21, 22, 19, 23, 26, 25]
      
      # Wilcoxon 부호 순위 검정
      stat, p_value = wilcoxon(before, after)

      4.4 Mann-Whitney U 검정

      • 목적: 독립된 두 표본간의 중위수 차이 검정
      • 가정: 데이터는 연속적이거나 ordinal, 두 표본은 독립
      • $H_o:$ 두 그룹의 중위 수 차이는 0이다.
      • $H_1:$ 두 그룹의 중위수 차이는 0 이 아니다.
      from scipy.stats import mannwhitneyu
      
      # 예시 데이터 (독립 표본)
      group1 = [14, 16, 18, 20, 22]
      group2 = [18, 20, 22, 24, 26]
      # Mann-Whitney U 검정
      stat, p_value = mannwhitneyu(group1, group2, alternative='two-sided')

      4.5. Kruskal-Wallis 검정

      • 목적: 세 개 이상의 독립된 표본의 중앙값을 비교. anova의 대응
      • 가정: 각 표본은 독립, 데이터는 ordinal
      • $H_o:$ 모든 그룹의 중위수 차이가 0이다.
      • $H_1:$ 적어도 하나 그룹의 중앙값이 다른 그룹과 다르다.
      from scipy.stats import kruskal
      
      # 예시 데이터 (세 그룹의 독립 표본)
      group1 = [10, 12, 14, 16, 18]
      group2 = [15, 17, 19, 21, 23]
      group3 = [24, 26, 28, 30, 32]
      
      # Kruskal-Wallis H 검정
      stat, p_value = kruskal(group1, group2, group3)

      4.6. 맥니마 검정

      • 목적: 이항 데이터에서 전후 또는 대응된 두 집단의 비율 변화
      • 가정: 데이터는 binary, 대응 표본 존재, 표본크기 충분히 커야함
      • $H_0$: 두 대응된 이항 분포간 변화 없음
      • $H_1$: 두 대응된 이항 분포간 변화 있음
      import numpy as np
      from statsmodels.stats.contingency_tables import mcnemar
      
      # 2x2 분할표 생성 (a, b, c, d)
      # 예시 데이터: (성공/실패 전후)
      # [[성공 전/성공 후, 성공 전/실패 후],
      #  [실패 전/성공 후, 실패 전/실패 후]]
      table = np.array([[40, 10],  # 성공 전/후
                        [5, 45]])  # 실패 전/후
      
      # 맥니마 검정 수행
      result = mcnemar(table, exact=True)  # exact=True: 정확한 검정 수행 (표본 크기가 작을 경우)
      
      # 결과 출력
      print('맥니마 검정 통계량:', result.statistic)
      print('p-value:', result.pvalue)

      4.7. 피셔의 정확검정

      • 목적: 작은 표본에서 두 범주형 변수간의 독립성의 검정
      • 가정: 각셀 기대빈도(N≤5) 이항 분포 또는 범주형 자료료 표현됨, 행과 열의 합은 고정
      • $H_0$: 두 변수는 독립적이다.
      • $H_1$: 두 변수는 독립적이지 않다.
      import numpy as np
      from scipy import stats
      
      # 2x2 분할표 데이터 (예시)
      # [[그룹 A, 그룹 B],
      #  [그룹 A, 그룹 B]]
      table = np.array([[8, 2],  # 결과 X
                        [1, 5]]) # 결과 Y
      
      # 피셔의 정확검정 수행
      odds_ratio, p_value = stats.fisher_exact(table, alternative='two-sided')
      
      # 결과 출력
      print('오즈비:', odds_ratio)
      print('p-value:', p_value)

      4.8. 프리드먼 검정

      • 목적: 반복 측정된 세개 그룹 간의 차이를 비교하는 검정
      • 가정: 연속형 or 순위형 데이처 사용, 각 그룹은 동일한 주제/대상에 여러번 측정된 결과
      • $H_0$ : 세 개 이상의 관련된 그룹 간의 차이가 없다.
      • $H_1$: 적어도 하나의 그룹에서 다른 그룹과 유의미한 차이가 있다.
      import numpy as np
      from scipy.stats import friedmanchisquare
      
      # 예시 데이터: 세 개의 처리에 대한 측정값
      # 동일한 대상(피험자)에 대해 세 번의 처리를 반복적으로 측정한 값
      # 행은 피험자, 열은 각각의 처리
      data1 = [10, 20, 30, 40]  # 처리 1
      data2 = [12, 21, 29, 35]  # 처리 2
      data3 = [14, 22, 27, 37]  # 처리 3
      
      # 프리드먼 검정 수행
      statistic, p_value = friedmanchisquare(data1, data2, data3)
      
      # 결과 출력
      print('프리드먼 검정 통계량:', statistic)
      print('p-value:', p_value)

      4.9. 부호검정

      • 목적: 관련된 두 그룹 간의 차이를 평가하는 검정, 중앙 값의 차이를 평가
      • 가정: 대응된 표본
      • $H_0:$ 두 그룹간 중앙값 차이가 없다.
      • $H_1$ : 두 그룹간 중앙값 차이가 있다.
      import numpy as np
      from scipy import stats
      
      # 예시 데이터: 두 그룹에 대한 대응된 표본 (처치 전후 데이터)
      before = [85, 70, 90, 80, 65, 75, 95, 70]  # 처리 전
      after  = [80, 65, 88, 82, 63, 78, 92, 72]  # 처리 후
      
      # 부호검정 수행
      result = stats.binom_test((before > after).sum(), n=len(before), p=0.5, alternative='two-sided')
      
      # 결과 출력
      print('p-value:', result)

      4.10. 코크란 q검정

      • 목적: 세개 이상의 이항 처리에 대한 대응 표본의 비율의 차이를 비교하기 위한 검정
      • 가정: 데이터는 binary, 대응된 표본
      • $H_0$: 세 개 이상의 처리 간에 차이가 없다.
      • $H_1$ : 적어도 하나의 처리에서는 다른 처리와 유의미한 차이가 있다.
      import numpy as np
      import pandas as pd
      from statsmodels.sandbox.stats.runs import cochrans_q
      
      # 예시 데이터: 세 가지 처리에 대한 이항형 결과 (성공/실패)
      # 각 행은 개별 피험자, 각 열은 다른 처리
      data = pd.DataFrame({
          'treatment1': [1, 0, 1, 1, 0],  # 처리 1 결과 (성공: 1, 실패: 0)
          'treatment2': [0, 1, 1, 1, 0],  # 처리 2 결과
          'treatment3': [1, 0, 1, 0, 1],  # 처리 3 결과
      })
      
      # 코크란 Q 검정 수행
      statistic, p_value = cochrans_q(data)
      
      # 결과 출력
      print('코크란 Q 검정 통계량:', statistic)
      print('p-value:', p_value)

      5. 회귀 분석

      • 선형성 가정: 독립변수와 종속변수와 선형
        1. sns.pariplot 혹은 변수간 산점도를 이용해 확인
        2. sns.heatmap(df.corr()) 로 확인
      • 독립성 가정: 관측치들간에 서로 독립
        • 더빈왓슨(Durbin Watson)통계량
          • $DW = \frac{\sum_{t=2}^{n} (e_t - e_{t-1})^2}{\sum_{t=1}^{n} e_t^2}$
          • $H_0$: 잔차 간에는 자기 상관이 없다.
          • $H_1$: 잔차 간에는 자기 상관이 존재 한다.
          • 해석
            • 0에 가까움: 잔차들 간에 양의 자기 상관이 존재
            • 2에 가까움: 잔차들 간 자기 상관이 없다(독립성 가정 만족)
            • 4에 가까움: 잔차들 간의 음의 자기 상관이 존재
      • 등분산 가정: 잔차의 분산은 모든 수준의 독립변수에 대해서 일정
        1. 잔차 vs 예측값 plot
        2. Breush-Pagan 검정
          • $H_0$: 잔차의 분산이 일정하다(등분산성이 있다)
          • $H_1$: 잔차의 분산이 일정하지 않다.(이분산성이 있다)
      import statsmodels.stats.api as sms
      import statsmodel.api as sm
      model = sm.OLS(y,X).fit
      static , pvalue, f_static , f_pv = sms.het_breuschpagan(model.resid,model.model.exog)
      • 정규성 가정: 잔차항이 정규분포를 따름
        1. QQ플랏
        2. sharpiro-wilk 검정
          • $H_0:$ 정규성을 따른다.
          • $H_1:$ 정규성을 따르지 않는다.
      from scipy.stats import shapiro
      static, pvalue = shapiro(model.resid)
      • 전체 코드
      # 1. 잔차 vs 예측값 : 잔차의 등분산성 가정 
      # 2. 잔차의 히스토그램: 잔차의 정규성 가정
      # 3. QQPLOT: 잔차의 정규성 가정
      # 4. 다중공선성: 독립변수의 독립성 가정
      # 5. 더빈왓슨 검정: 잔차의 독립성 가정
      import statsmodels.api as sm
      import matplotlib.pyplot as plt
      import seaborn as sns 
      from statsmodels.stats.outliers_influence import variance_inflation_factor as VIF
      
      def review_lr(X,y, add_const = True):
          if add_const:
              X = sm.add_constant(X)
              model = sm.OLS(y, X).fit()
          else:
              model = sm.OLS(y, X).fit()
          
      
          residuals = model.resid
          fitted_values = model.fittedvalues
      
          plt.figure(figsize = (10,6))
          #1. 잔차 vs 예측값
          plt.subplot(2,2,1)
          sns.residplot(x = fitted_values, y = residuals, lowess = True)
          plt.title('Residual vs Fitted')
      
          # 2. 잔차의 히스토그램
          plt.subplot(2,2,2)
          sns.histplot(residuals, kde = True)
          plt.title('Residuals Distribution')
      
          # 3. 잔차의 QQplot
          plt.subplot(2,2,3)
          sm.qqplot(residuals, line = '45', fit = True, ax=plt.gca())
          plt.title('QQ plot)')
      
          # 4. 다중공선성
          plt.subplot(2,2,4)
          vif_data = pd.DataFrame()
          vif_data['VIF'] = [VIF(X.values,i) for i in range(X.shape[1])]
          vif_data['Feature'] = X.columns
      
          sns.barplot(x = 'VIF', y = 'Feature', data = vif_data)
          plt.title('VIF')
          plt.show()
      
          # 5. 잔차의 독립성 검정: 더빈왓슨검정
          # -> 기본적으로 sm.OLS(Y,X).summary()에서 제공
          dw_stat = sm.stats.durbin_watson(residuals)
          print(f"Durbin-Watson statistic: {dw_stat:.3f}")
          '''
          0에 가까우면 잔차의 양의 자기 상관성
          2에 가까우면 잔차의 독립성 가정 만족
          4에 가까우면 잔차가 음의 자기 상관성을 가짐
          '''
      
          #6. 잔차의 정규성 검정: # Shapiro-Wilk 검정
          from scipy import stats
          residuals = model.resid
          shapiro_test = stats.shapiro(residuals)
      
          print(f"Shapiro-Wilk Test Statistic: {shapiro_test.statistic:3f}")
          print(f"p-value: {shapiro_test.pvalue:3f}")
      
          # 결과 해석
          if shapiro_test.pvalue > 0.05:
              print("p-value가 0.05보다 큼: 잔차가 정규분포를 따를 가능성이 높음 (귀무가설을 기각할 수 없음).")
          else:
              print("p-value가 0.05보다 작음: 잔차가 정규분포를 따르지 않을 가능성이 높음 (귀무가설 기각).")
      		
      		return model.summary()
      y = df['MEDV']
      X = df.drop(columns=['MEDV'])
      review_lr(X,y)

      Durbin-Watson statistic: 1.246
      Shapiro-Wilk Test Statistic: 0.917579
      p-value: 0.000000
      p-value가 0.05보다 작음: 잔차가 정규분포를 따르지 않을 가능성이 높음 (귀무가설 기각).

       

      • 선형회귀 다중공선성 관리 방법
        • 상관관계가 0.7 이상인 것 기준
        • 도메인지식을 바탕으로 중요하다고 생각되는 변수를 유지
        • 다중공선성이 높은 변수들이 많다면 차원 축소 진행
      corr_df = df.drop(columns =['MEDV']).corr().unstack().reset_index()
      corr_df.columns =['col1','col2','corr']
      corr_df =corr_df[corr_df['col1'] != corr_df['col2']]
      	.sort_values('corr').reset_index(drop=True)[::2].reset_index(drop=True)
      display(corr_df)
      
      print('''
      강한 양의 상관관계 및 강한 음의 상관관계를 가지는 컬럼들이 다수 존재한다. 다중공선성이 발생할 여지가 크기에 이를 해결하기 위해 두가지 접근을 진행한다.
      1. vif값을 기준으로 변수를 제거하는 방식
      2. pca를 이용해서 변수간 선형관계를 줄인 축소된 차원으로 분석을 진행
      ''')

      • VIF
        • $VIF_i = \frac{1}{1 - R_i^2}$
        • $R^{2}_{i}$: VIF를 측정하고 싶은 독립변수를 종속변수로 놓고, 나머지 독립변수를 이용해 회귀분석을 진행한 결정계수
        • 즉 결정계수가 90%이 된다는 것은 VIF가 10이 된다는 것
      from statsmodels.stats.outliers_influence import variance_inflation_factor
      
      df_vif = df.drop(columns =['MEDV'])
      vif  = pd.DataFrame()
      vif['VIF Factor'] = [variance_inflation_factor(df_vif.values,i) for i in range(df_vif.shape[1])]
      vif['features'] = df_vif.columns
      display(vif)
      • 방법1) 변수 제거
      • 방법2) 차원축소(PCA)
        • 거리기반의 알고리즘이기 때문에 정규화 필요
        • 전체 변수를 넣어도, 부분변수를 넣어도되나, 전자의 경우 해석력이 많이 손상됌
      from sklearn.decomposition import PCA
      from sklearn.preprocessing import StandardScaler
      
      sc =StandardScaler()
      
      scaled_df = sc.fit_transform(df.drop(columns =['MEDV']))
      pca = PCA(n_components=7)
      pca_df = pca.fit_transform(scaled_df)
      
      X = pca_df
      y = df['MEDV']
      X = sm.add_constant(X)
      
      model = sm.OLS(y,X).fit()
      display(model.summary())
      • 방법3) Lidge/Lasso 회귀
        • Lasso(L1, 절대값):
          • 변수를 선택하고 싶은 경우
          • 일부 변수만 중요하고, 나머지는 무시해도 되는 상황
          • 희소한 데이터셋에서 불필요한 변수를 제거하여 모델의 해석력을 높이고 싶은 경우
        • Ridge(L2, 제곱):
          • 모든 변수가 모델에 중요할 때
          • 다중공선성 문제를 해결하고 과적합을 방지하고 싶은 경우
          • 변수 선택보다는 모델 성능 향상이 더 중요한 경우

      6. 시계열 검정

      • 정상성 검정
      import pandas as pd
      import numpy as np
      from statsmodels.tsa.stattools import adfuller
      
      # ADF 검정 수행
      result = adfuller(data)
      
      print('ADF Statistic:', result[0])
      print('p-value:', result[1])
      • 잔차 분석
      arima_model.plot_diagnostics
      plt.show()
      • 잔차의 자기상관성 확인:Ljung-box 검정
        • $H_0$: 잔차끼리의 자기 상관이 없다
        • $H_1$: 잔차끼리의 자기 상관이 있다
      from statsmodels.stats.diagnostic import acorr_ljungbox
      
      # Ljung-Box 검정 (잔차의 독립성 검정)
      ljung_box_test = acorr_ljungbox(arima_model.resid, lags=[10], return_df=True)
      print(ljung_box_test)
      • 시계열 분해
      from statsmodels.tsa.seasonal import seasonal_decompose
      
      # 시계열 분해 (Additive 모델)
      # period는 데이터의 계절성 주기 설정 (예: 월별 데이터의 경우 12)
      decomposition = seasonal_decompose(data, model='additive', period=12)
      
      # 분해 결과 시각화
      decomposition.plot()
      plt.show()
      • 지수 평활 모형
      from statsmodels.tsa.holtwinters import ExponentialSmoothing
      
      # 단순 지수 평활 모델 적합
      model = ExponentialSmoothing(data, trend=None, seasonal=None)
      model_fit = model.fit(smoothing_level=0.8, optimized=False)
      
      # 예측값 생성
      fitted_values = model_fit.fittedvalues
      
      # 원본 데이터와 예측값 비교
      plt.figure(figsize=(12, 6))
      plt.plot(data, label='원본 데이터')
      plt.plot(fitted_values, label='예측값', color='red')
      plt.legend()
      plt.show()

      6.1. 자기회귀(AR) 모형

      • 현재 값이 과거 값들의 선형 조합으로 표현될 수 있다고 가정
      • 자기상관에 강한 시계열과 추세나 패턴이 지속되는 경향이 있을때 유용(Ex 주식, 기온 데이터)
      • PACF: p 시차 이후 급격히 0에 가까워지며, ACF는 점진적으로 감소
      from statsmodels.tsa.ar_model import AutoReg
      model_ar = AutoReg(data, lags=p).fit()
      forecast = model_ar.forecast(steps=10)

      6.1. PACF

      • 편자기상관함수는 현재 값과 특정 시점이 값의 상관관계를 구하기 위한 함수
      • 시차가 2라면 $y_t$와 $y_{t-2}$의 두 시차를 고려하며 중간 시차 $y_{t-1}$이 영향을 제거
      • 첫 번째 선은 차수 1(lag1)
      • 다음 그래프를 보고 AR(2) 결정

      파란선: 유의성 경계

      6.3.  MA 모형

      • 현재 값이 과거의 오차항(예측 오류)의 선형 조합으로 표현된다고 가정
      • 단기적인 충격이나 이벤트의 반응을 모델링 하는데 유용(주가 실적 발표)
      • PACF: 점진적으로 감소, ACF: q  시차 이후 급격히 0에 가까워짐
      # MA(q) 모델 - ARMA로 구현
      from statsmodels.tsa.arima.model import ARIMA
      model_ma = ARIMA(data, order=(0,0,q)).fit()
      forecast = model_ma.forecast(steps=10)

      6.4. ACF(Auto Correlation Function)

      • 자기 상관 함수는 각 시차(lag)에 대해 현재 값과 과거 값의 상관관계를 계산, 시차 q를 결정
      • 첫 번째 세로 선은 차수 0으로 자기와의 상관관계(항상 1.0)
      • 다음은 MA(3)이 결정되는 ACF 그림

      • ACF, PACF 그리기 
      import matplotlib.pyplot as plt
      from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
      
      # 한 그림에 두 플롯 함께 표시하기
      fig, axes = plt.subplots(2, 1, figsize=(12, 8))
      plot_acf(data, lags=40, alpha=0.05, ax=axes[0])
      axes[0].set_title('ACF')
      plot_pacf(data, lags=40, alpha=0.05, ax=axes[1])
      axes[1].set_title('PACF')
      plt.tight_layout()
      plt.show()

      6.5. ARIMA

      • ARIMA
      from statsmodels.tsa.arima.model import ARIMA
      import matplotlib.pyplot as plt
      
      # ARIMA 모델 적합 (p=1, d=1, q=1 파라미터로 예시)
      model = ARIMA(data, order=(1, 1, 1))
      model_fit = model.fit()
      
      # 예측값 생성
      fitted_values = model_fit.fittedvalues
      
      # 원본 데이터와 예측값 비교
      plt.figure(figsize=(12, 6))
      plt.plot(data, label='원본 데이터')
      plt.plot(fitted_values, label='ARIMA 예측값', color='red')
      plt.legend()
      plt.title('ARIMA 모델 적합 결과')
      plt.show()
      
      # 모델 요약 출력 (선택사항)
      print(model_fit.summary())
      • SARIMA
      from statsmodels.tsa.statespace.sarimax import SARIMAX
      
      # SARIMA 모델 적합 (p, d, q, P, D, Q, m 설정)
      p = 1  # AR 차수
      d = 1  # 차분 차수
      q = 1  # MA 차수
      P = 1  # 계절 AR 차수
      D = 1  # 계절 차분 차수
      Q = 1  # 계절 MA 차수
      m = 12  # 계절 주기 (예: 월별 데이터의 경우 12)
      
      model = SARIMAX(data, order=(p, d, q), seasonal_order=(P, D, Q, m))
      model_fit = model.fit()
      
      print(model_fit.summary())
      
      # 예측
      forecast = model_fit.forecast(steps=12)
      print(forecast)

      6.6 auto ARIMA

      import pmdarima as pm
      from statsmodels.tsa.arima.model import ARIMA
      
      data = df.copy()
      # 자동으로 최적의 ARIMA 모델 찾기
      auto_model = pm.auto_arima(data, 
                                start_p=0, start_q=0,
                                max_p=5, max_q=5,
                                d=None, max_d=2,
                                seasonal=False,
                                trace=True,
                                error_action='ignore',
                                suppress_warnings=True,
                                stepwise=True)
      
      print(f"최적의 ARIMA 모델 파라미터: {auto_model.order}")
      
      # 최적 모델 적합
      best_model = ARIMA(data, order=auto_model.order)
      best_model_fit = best_model.fit()
      
      # 예측값 생성
      best_fitted_values = best_model_fit.fittedvalues
      
      # 원본 데이터와 예측값 비교
      plt.figure(figsize=(12, 6))
      plt.plot(data, label='원본 데이터')
      plt.plot(best_fitted_values, label=f'최적 ARIMA{auto_model.order} 예측값', color='red')
      plt.legend()
      plt.title('optimization result')
      
      #진단코드
      model.plot_diagnostics(figsize=(12, 8))
      plt.tight_layout()
      plt.show()

       

      • VAR 모형
      from statsmodels.tsa.vector_ar.var_model import VAR
      
      # 데이터 분할 (학습 및 테스트 데이터)
      train_data = df[:-10]
      test_data = df[-10:]
      
      # VAR 모델 적합
      model = VAR(train_data)
      model_fit = model.fit(maxlags=15, ic='aic')
      
      print(model_fit.summary())
      
      # 예측
      lag_order = model_fit.k_ar
      forecast_input = train_data.values[-lag_order:]
      forecast = model_fit.forecast(y=forecast_input, steps=10)
      
      # 예측 결과를 데이터프레임으로 변환
      forecast_df = pd.DataFrame(forecast, index=test_data.index, columns=df.columns)
      
      print(forecast_df)

      7. 문서기록

      • 2025.04.18. 최초 작성
      • 2025.04.22. 머신러닝 항목 분리
      • 2025.04.25. stastsmodel 디렉토리 등 추가

       

       

      반응형