빅데이터분석기사 실기 학습자료 3과목 파트3 - 선형 회귀분석 · 로지스틱 회귀 · 실전 풀이
2026. 4. 28. 20:31ㆍ빅데이터분석기사
11111
2222

| [샘플데이터] statsmodels 회귀 실습 데이터: salary age experience score gender dept 4500.0 32 5 85.0 M IT ← salary=종속변수 3800.0 45 12 72.0 F HR ← age,exp,score,gender=독립변수 5200.0 28 3 91.0 M Finance * 회귀: salary ~ age + experience + score + C(gender) * C(gender): 범주형 변수 → 자동으로 더미변수화 |
1. 선형 회귀分석 (statsmodels)
1.1 단순·다중 선형 회귀
| [기출패턴] 기출: "salary에 영향을 미치는 변수를 회귀分석하고 R², F-통계량, 계수, p-value를 구하라" |
| import statsmodels.formula.api as smf import pandas as pd df = pd.read_csv("/data/data.csv") df.dropna(inplace=True) # 결측 제거 (회귀 전 필수) # 단순 선형 회귀: salary ~ age (하나의 독립변수) model1 = smf.ols('salary ~ age', data=df).fit() print("=== 단순 선형 회귀 ===") print(f"R²(결정계수) : {round(model1.rsquared, 4)}") # 설명력 (0~1) print(f"F-통계량 : {round(model1.fvalue, 4)}") # 모델 유의성 print(f"F p-value : {round(model1.f_pvalue, 4)}") print(f"Intercept(절편): {round(model1.params['Intercept'], 4)}") # y절편 print(f"age 계수 : {round(model1.params['age'], 4)}") # age 회귀계수 print(f"age p-value : {round(model1.pvalues['age'], 4)}") # 다중 선형 회귀: C(gender) → gender를 범주형으로 처리 (자동 더미화) model2 = smf.ols('salary ~ age + score + C(gender)', data=df).fit() print(" === 다중 선형 회귀 ===") print(f"조정 R² : {round(model2.rsquared_adj, 4)}") # 변수수 보정 설명력 print(f"F-통계량 : {round(model2.fvalue, 4)}") for name in model2.params.index: c, p = round(model2.params[name], 4), round(model2.pvalues[name], 4) print(f" {name:22s}: 계수={c:9.4f}, p={p:.4f} {'★' if p<=0.05 else ''}") ──────────────────────────────────────────────────── 실행 결과 === 단순 선형 회귀 === R²(결정계수) : 0.3882 ← age 하나로 38.82% 설명 F-통계량 : 633.4821 ← 매우 크다 → 모델 유의함 F p-value : 0.0000 Intercept(절편): 1823.4512 ← age=0일 때 예측 salary (해석 주의) age 계수 : 67.1234 ← age 1세 증가 → salary 67.12 증가 age p-value : 0.0000 ← age는 유의한 설명변수 === 다중 선형 회귀 === 조정 R² : 0.5228 ← 3변수로 52.28% 설명 F-통계량 : 362.1823 Intercept : 계수= 812.3400, p=0.0000 ★ age : 계수= 54.2341, p=0.0000 ★ ← 다른 변수 통제 후 score : 계수= 18.9012, p=0.0000 ★ C(gender)[T.M] : 계수= 123.4512, p=0.0312 ★ ← 남성이 123원 더 높음 |
1.2 결과 해석 핵심
| import statsmodels.formula.api as smf import pandas as pd df = pd.read_csv("/data/data.csv") model = smf.ols('salary ~ age + score', data=df).fit() # 시험에서 자주 묻는 값들 추출 print(f"R² : {round(model.rsquared, 4)}") # R²=0.52: salary 분산의 52%를 age, score가 설명함 print(f"조정 R² : {round(model.rsquared_adj, 4)}") # 변수 추가 시 패널티 부여 → 진짜 설명력 반영 print(f"F-통계량 : {round(model.fvalue, 4)}") print(f"모델 p-value : {round(model.f_pvalue, 4)}") # p<0.05 → 회귀모델 전체가 통계적으로 유의함 print(f" age 회귀계수 : {round(model.params['age'], 4)}") # age 1단위 증가 시 salary 54.23 증가 (다른 변수 고정) print(f"age p-value : {round(model.pvalues['age'], 4)}") # p<0.05 → age는 salary에 유의한 영향을 줌 # 95% 신뢰구간 print(f" 95% 신뢰구간: {model.conf_int().round(4)}") # 신뢰구간이 0을 포함하지 않으면 유의한 계수 ──────────────────────────────────────────────────── 실행 결과 R² : 0.5234 조정 R² : 0.5228 F-통계량 : 548.2341 모델 p-value : 0.0000 ← 모델 전체 유의 age 회귀계수 : 54.2341 ← 나이 1세↑ → 급여 54.2원↑ age p-value : 0.0000 ← 유의한 변수 95% 신뢰구간: 0 1 Intercept 723.12 901.56 ← 0 미포함 → 유의 age 48.12 60.35 ← 0 미포함 → 유의 score 15.34 22.46 ← 0 미포함 → 유의 |
1.3 회귀 가정 검정
| import statsmodels.formula.api as smf from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") model = smf.ols('salary ~ age + score', data=df).fit() residuals = model.resid # 잔차(residual) = 실제값 - 예측값 # 가정1: 잔차 정규성 (Shapiro-Wilk) stat, p = stats.shapiro(residuals) print(f"잔차 정규성 W={round(stat,4)}, p={round(p,4)}") print(f" → {'충족' if p>0.05 else '불충족'}") # 가정2: 잔차 등분산성 (Breusch-Pagan) from statsmodels.stats.diagnostic import het_breuschpagan lm, lm_p, fval, f_p = het_breuschpagan(residuals, model.model.exog) print(f" 등분산성(BP) LM={round(lm,4)}, p={round(lm_p,4)}") print(f" → {'등분산' if lm_p>0.05 else '이분산 → 일반화 최소제곱(GLS) 고려'}") # 가정3: 자기상관 (Durbin-Watson) — 시계열 데이터에서 중요 from statsmodels.stats.stattools import durbin_watson dw = durbin_watson(residuals) print(f" Durbin-Watson: {round(dw,4)}") print(f" → {'자기상관 없음' if 1.5<dw<2.5 else '자기상관 의심'} (기준: 1.5~2.5)") ──────────────────────────────────────────────────── 실행 결과 잔차 정규성 W=0.9923, p=0.1834 → 충족 ← 잔차가 정규분포를 따름 등분산성(BP) LM=3.2341, p=0.1982 → 등분산 ← 잔차 분산이 예측값에 따라 일정 Durbin-Watson: 1.9823 → 자기상관 없음 (1.9823 ≈ 2.0이 이상적) |
2. 로지스틱 회귀分석 (statsmodels)
| import statsmodels.api as sm import pandas as pd, numpy as np df = pd.read_csv("/data/data.csv") df.dropna(inplace=True) df['gender_m'] = (df['gender']=='M').astype(int) # 더미 변수 수동 생성 X = df[['age','salary','gender_m']] y = df['target'] X = sm.add_constant(X) # 상수항(절편) 추가 — sm.Logit에서는 수동 추가 필요! model = sm.Logit(y, X).fit(disp=False) # disp=False: 수렴 로그 숨김 print(f"Pseudo R²(맥파든): {round(model.prsquared, 4)}") # 0.2~0.4: 양호 print(f"LLR p-value : {round(model.llr_pvalue, 4)}") # 모델 전체 유의성 print() for name in model.params.index: coef = model.params[name] p = model.pvalues[name] odds = np.exp(coef) # 오즈비(OR): 1보다 크면 양성 확률 증가 print(f"{name:15s}: coef={round(coef,4)}, OR={round(odds,4)}, p={round(p,4)}") ──────────────────────────────────────────────────── 실행 결과 Pseudo R²(맥파든): 0.2341 ← 0.2~0.4 → 적당한 모델 fit LLR p-value : 0.0000 const : coef=-4.8234, OR=0.0080, p=0.0000 ← 절편 age : coef= 0.0234, OR=1.0237, p=0.0312 ★ ← age↑ → 양성확률↑ salary : coef= 0.0003, OR=1.0003, p=0.0000 ★ ← salary↑ → 양성확률↑ gender_m : coef= 0.1823, OR=1.2000, p=0.1234 ← 유의하지 않음 |
3. 실전 풀이 전략 총정리
3.1 작업형 3유형 풀이 순서 (암기)
| [핵심암기] 3유형 표준 풀이 순서: 1. 데이터 로드 + dropna()로 결측 제거 2. 귀무가설(H0) / 대립가설(H1) 설정 3. 정규성 검정: stats.shapiro() → p값 확인 4. (독립 2집단 t-검정 시) 등분산 검정: stats.levene() 5. 해당 검정 실행 (t/F/chi2/mannwhitneyu 등) 6. 통계량 + p-value print(round(값, 4)) 7. 결론: "귀무가설 기각/채택" 출력 |
3.2 유형별 완성 코드 모음
| # ★ 독립표본 t-검정 완성 코드 (3단계) from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") g1 = df[df['group']=='A']['score'].dropna() g2 = df[df['group']=='B']['score'].dropna() _, p1 = stats.shapiro(g1) # 정규성 A _, p2 = stats.shapiro(g2) # 정규성 B _, lp = stats.levene(g1,g2) # 등분산 t, p = stats.ttest_ind(g1, g2, equal_var=(lp>0.05)) # 등분산 결과 반영 print(round(t, 4)) print(round(p, 4)) ──────────────────────────────────────────────────── 실행 결과 2.3814 ← t-통계량 0.0182 ← p-value (0.05 미만 → 귀무가설 기각) |
| # ★ ANOVA + Tukey 완성 코드 from scipy import stats from statsmodels.stats.multicomp import pairwise_tukeyhsd import pandas as pd df = pd.read_csv("/data/data.csv") groups = [df[df['dept']==d]['salary'].dropna() for d in df['dept'].unique()] f, p = stats.f_oneway(*groups) print(round(f, 4)) print(round(p, 4)) if p <= 0.05: tukey = pairwise_tukeyhsd(df['salary'].dropna(), df.loc[df['salary'].notna(), 'dept']) print(tukey.summary()) # 어떤 쌍이 다른지 확인 ──────────────────────────────────────────────────── 실행 결과 42.8234 ← F-통계량 0.0000 ← 매우 유의 Multiple Comparison of Means - Tukey HSD group1 group2 meandiff p-adj reject Finance HR -1418.27 0.001 True ← 유의한 차이 Finance IT -208.04 0.823 False ← 차이 없음 (p>0.05) IT Sales 1452.38 0.001 True ← 유의한 차이 |
| # ★ 카이제곱 완성 코드 from scipy.stats import chi2_contingency import pandas as pd df = pd.read_csv("/data/data.csv") ct = pd.crosstab(df['var1'], df['var2']) # 교차표 생성 chi2, p, dof, expected = chi2_contingency(ct) print(round(chi2, 4)) print(round(p, 4)) print(dof) # 자유도 출력 (문제에서 요구 시) print(round(expected.min(), 4)) # 기대빈도 최솟값 (5 이상이어야 유효) ──────────────────────────────────────────────────── 실행 결과 2.3412 ← 카이제곱 통계량 0.5041 ← p>0.05 → 연관 없음 3 ← 자유도 = (4-1)×(2-1) 45.2341 ← 기대빈도 최솟값 > 5 → 검정 유효 |
3.3 오답 함정 & 주의사항
| [주의] 자주 틀리는 패턴: 1. dropna() 빠뜨림 → NaN 포함 시 검정 오류 (stat=nan) 2. Levene 생략하고 바로 equal_var=True → 잘못된 검정 방법 3. mode()[0]에서 [0] 누락 → Series 반환 → 오답 4. round() 자릿수 문제 지정과 불일치 (소수점 2 vs 4) 5. 대응표본에 독립표본 t-검정 사용 (ttest_rel 대신 ttest_ind) 6. 카이제곱에서 기대빈도 5 미만 셀 확인 안 함 7. ANOVA 유의해도 Tukey 사후검정 빠뜨림 8. 양측/단측 검정 혼동 (alternative 파라미터 주의) |
3.4 시험 당일 체크리스트
| [핵심암기] 시험 당일 체크리스트: ☐ 데이터 로드 후 isnull().sum() + dropna() 확인 ☐ 정규성 검정 먼저 (shapiro) → 결과에 따라 검정 선택 ☐ 독립 t-검정 시 Levene 등분산 검정 필수 ☐ print(round(통계량, 4)) + print(round(p, 4)) 둘 다 출력 ☐ 소수점 자릿수: 문제 지문 확인 (보통 4자리) ☐ ANOVA 유의 시 Tukey 사후검정 반드시 추가 ☐ 결론 문장 출력: "귀무가설 기각/채택" |
3.5 필수 임포트 전체 모음
| # ★ 3유형 시험 시작 시 붙여넣기 가능 — 전체 임포트 import pandas as pd import numpy as np from scipy import stats from scipy.stats import ( shapiro, # 정규성 검정 ttest_1samp, # 단일표본 t-검정 ttest_ind, # 독립표본 t-검정 ttest_rel, # 대응표본 t-검정 f_oneway, # 일원 ANOVA chi2_contingency, # 카이제곱 독립성 chisquare, # 카이제곱 적합도 pearsonr, # 피어슨 상관 spearmanr, # 스피어만 상관 mannwhitneyu, # Mann-Whitney U (비모수) wilcoxon, # Wilcoxon (비모수 대응) kruskal, # Kruskal-Wallis (비모수 ANOVA) levene, # 등분산 검정 ) import statsmodels.formula.api as smf # 회귀분석 (formula 방식) import statsmodels.api as sm # 회귀분석 (행렬 방식) from statsmodels.stats.multicomp import pairwise_tukeyhsd # Tukey HSD print("임포트 완료!") ──────────────────────────────────────────────────── 실행 결과 임포트 완료! ← 오류 없으면 모든 라이브러리 사용 가능 확인 |
'빅데이터분석기사' 카테고리의 다른 글
| 빅데이터분석기사 실기 학습자료 보충 - 통계검정 심화 · 등분산검정 · 비모수검정 · 불균형처리 (0) | 2026.04.28 |
|---|---|
| 빅데이터분석기사 실기 학습자료 3과목 파트2 - t-검정 · ANOVA · 카이제곱 · 비모수 검정 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 3과목 파트1 - 기술통계 정규성 검정 상관분석 실전 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트4 - 앙상블 심화 · Pipeline · 특성 중요도 · 과적합 진단 · 최종 제출 전략 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트3 - 회귀 알고리즘 완전정복 · 비지도학습(클러스터링/PCA) (0) | 2026.04.28 |