빅데이터분석기사 실기 · Python

작업형 1·2·3에서 쓰는 파이썬 코드 75개

『2027 빠르게 따는 빅데이터분석기사 실기』의 풀이 코드 관례를 따랐고, 모든 코드는 실제로 실행해 확인했다. 시험장 버전(scikit-learn 1.2 이상)에서도 그대로 돈다.

감점 포인트 12개 — 「함정·필수·빈출」 형광펜 암기 모드 — 코드를 가리고 떠올린 뒤 눌러서 확인
01

작업형 1판다스 기본

불러오기 → 확인 → 조건 → 계산 → print. 작업형 1 은 이 다섯 단계 안에서 끝난다.

pandas

불러오기 · 크기 · 앞부분

문제를 열자마자. 컬럼 이름과 자료형부터 본다.

import pandas as pd
import numpy as np

df = pd.read_csv('data/파일명.csv')
print(df.shape)                        # (행, 열)
print(df.head(3).to_string(index=False))
df.info()                              # 자료형 · 결측 개수
print(df.describe())                   # 수치형 요약
pandas

컬럼 선택 · loc / iloc

조건에 맞는 행의 특정 컬럼 값이 필요할 때.

df['score']                         # Series
df[['group', 'score']]              # DataFrame
df.loc[df['flag'] == 1, 'amount']   # 조건 + 컬럼
df.loc[0, 'score']                  # 라벨 기준
df.iloc[0, 2]                       # 위치 기준 (0번 행, 2번 열)
df.iloc[:10]                        # 앞 10행
빈출

조건 필터링 · 다중 조건

「~이면서 ~인」 행을 고를 때. 조건마다 괄호.

cond = (df['flag'] == 1) & (df['group'] == 'G2')   # 조건마다 괄호
print(cond.sum())                       # 조건 만족 행 수
print(df.loc[cond, 'amount'].mean())

df[df['region'].isin(['north', 'east'])]
df[df['score'].between(60, 80)]        # 60 이상 80 이하 (양 끝 포함)
df[~(df['segment'] == 'B')]            # 부정은 ~
sort_values

정렬 후 N번째 값

「상위 N번째」 「가장 큰」 값을 물을 때.

s = df.sort_values('amount', ascending=False)
print(s.iloc[0]['id'])             # 1등
print(s.iloc[2]['amount'])         # 3등 값

# 여러 기준 정렬
df.sort_values(['score', 'age'], ascending=[False, True])

df.nlargest(10, 'amount')          # 상위 10행 바로
함정

value_counts — 이름인가 개수인가

최빈 범주를 물을 때. 답이 이름인지 개수인지 먼저 확인.

vc = df['group'].value_counts()
print(vc.index[0])     # 가장 많은 그룹 「이름」
print(vc.iloc[0])      # 그 그룹의 「개수」

df['group'].value_counts(normalize=True)   # 비율
df['group'].mode()[0]                      # 최빈값
pandas

기초 통계 함수

평균·중앙값·표준편차를 바로 구할 때.

df['score'].sum(); df['score'].mean(); df['score'].median()
df['score'].std()        # 표본표준편차 (ddof=1)
df['score'].std(ddof=0)  # 모표준편차 — 문제에 「모」가 있으면
df['score'].var()
df['score'].quantile(0.75)
df['group'].nunique()    # 고유값 개수
02

작업형 1결측치 · 이상치

「몇 개인가」와 「채운 뒤 계산」이 단골. 채울 값은 반드시 원본에서 먼저 구한다.

isna

결측치 확인 · 제거

「결측치가 몇 개」 「결측 행 제거 후」 문제.

print(df.isna().sum())               # 컬럼별 결측 개수
print(df['views'].isna().sum())
print(df.isna().sum().sum())         # 전체 결측 개수

drop_df = df.dropna(subset=['rating', 'views'])
print(len(df) - len(drop_df))        # 제거된 행 수
fillna

결측치 대체 — 값은 먼저 구한다

「중앙값으로 채운 뒤」 계산하는 문제.

work = df.copy()
med = work['rating'].median()     # 채우기 「전」 값으로 구한다
work['rating'] = work['rating'].fillna(med)

work['views'] = work['views'].fillna(work['views'].mean())
work['status'] = work['status'].fillna(work['status'].mode()[0])
transform

그룹별 값으로 결측치 채우기

「그룹별 평균으로 채워라」가 나올 때.

work = df.copy()
grp_med = work.groupby('group')['views'].transform('median')
work['views'] = work['views'].fillna(grp_med)
# 그룹 전체가 결측이면 전체 중앙값으로 한 번 더
work['views'] = work['views'].fillna(work['views'].median())
quantile

IQR 이상치

「IQR 1.5배 밖」 이상치 개수·제외 평균.

q1 = df['price'].quantile(0.25)
q3 = df['price'].quantile(0.75)
iqr = q3 - q1
lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr

out = (df['price'] < lower) | (df['price'] > upper)
print(out.sum())                      # 이상치 개수
print(df.loc[~out, 'price'].mean())   # 이상치 제외 평균
clip

이상치 바꾸기 · 표준화

경계값 대체, z-score, min-max 문제.

# lower · upper 는 앞 카드(IQR 이상치)에서 구한 값
capped = df['price'].clip(lower, upper)    # 경계값으로 대체

z = (df['score'] - df['score'].mean()) / df['score'].std()   # ddof=1
print((z.abs() > 3).sum())                 # |z| > 3 개수
# scipy.stats.zscore · StandardScaler 는 ddof=0 — 경계 개수가 달라질 수 있다

lo, hi = df['score'].min(), df['score'].max()
mm = (df['score'] - lo) / (hi - lo)              # min-max 0~1
duplicated

중복 처리

「중복 제거 후」 행 수나 값을 물을 때.

print(df.duplicated().sum())                    # 완전 중복 행 수
print(df.duplicated(subset=['id']).sum())       # id 기준 중복
dedup = df.drop_duplicates(subset=['id'], keep='first')
03

작업형 1파생변수 · 문자열 · 날짜

컬럼을 하나 만들고 그걸로 다시 집계하는 2단계 문제가 대부분이다.

pd.cut

파생변수 · 구간 나누기

새 컬럼을 만들거나 구간별로 묶을 때.

df['total'] = df['qty'] * df['unit_price']
df['is_high'] = (df['amount'] >= 150000).astype(int)

bins = [0, 30, 40, 50, float('inf')]
df['age_band'] = pd.cut(df['age'], bins=bins,
                        labels=['~29', '30대', '40대', '50+'],
                        right=False)      # [0,30) [30,40) ...
df['q4'] = pd.qcut(df['score'], 4, labels=False)   # 4분위 0~3
map

값 바꾸기 · map · apply

범주를 숫자로, 조건에 따라 값 지정.

df['flag_txt'] = df['flag'].map({1: 'Y', 0: 'N'})
df['status2'] = df['status'].map({'방문': 1, '취소': -1, '대기': 0})
df['region2'] = df['region'].replace('central', 'center')
df['grade'] = np.where(df['score'] >= 70, 'pass', 'fail')
df['len'] = df['name'].apply(lambda x: len(x))
str

문자열 처리

코드 앞자리, 특정 단어 포함 여부.

df['code'].str.split('-').str[0]          # 'AB-01' → 'AB'
df['code'].str[:2]                        # 앞 두 글자
df['name'].str.lower().str.contains('apple')
df['code'].str.startswith('AB')
df['name'].str.replace(' ', '')
df['name'].str.len()
datetime

날짜 처리

연·월·요일별 집계, 기간 필터.

df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['weekday'] = df['date'].dt.weekday     # 월=0 … 일=6
df['is_weekend'] = (df['weekday'] >= 5).astype(int)
df[(df['date'] >= '2024-03-01') & (df['date'] < '2024-04-01')]
timedelta

날짜 차이 · 기간

「소요 일수」 「경과 시간」을 물을 때.

df['date'] = pd.to_datetime(df['date'])
df['end_date'] = pd.to_datetime(df['end_date'])
df['days'] = (df['end_date'] - df['date']).dt.days
df['hours'] = (df['end_date'] - df['date']).dt.total_seconds() / 3600
04

작업형 1집계 · 병합

groupby 한 줄로 끝나는 문제와, 결과에서 다시 하나를 고르는 문제로 나뉜다.

groupby

groupby 기본

「그룹별 평균·합계」 문제의 기본형.

df.groupby('group')['amount'].mean()
df.groupby('group')['amount'].sum().sort_values(ascending=False)
df.groupby('group').size()             # 그룹별 행 수
df.groupby(['region', 'group'])['score'].mean().reset_index()
agg

agg 이름 붙여 여러 집계

그룹별로 여러 값을 한 번에 볼 때.

summary = df.groupby('region').agg(
    cnt=('id', 'count'),
    amount_sum=('amount', 'sum'),
    score_mean=('score', 'mean'),
).sort_values('amount_sum', ascending=False)
print(summary.round(2))
idxmax

집계 결과에서 하나 고르기

「가장 큰 그룹은?」처럼 집계 뒤 하나를 고를 때.

g = df.groupby('group')['amount'].mean()
print(g.idxmax(), g.max())     # 평균이 가장 큰 그룹과 그 값
print(g.idxmin())

score = df['status'].map({'방문': 1, '취소': -1, '대기': 0})
bal = score.groupby(df['region']).sum()    # 음수도 나오는 합
key = bal.abs().idxmax()       # 절댓값이 가장 큰 그룹
print(key, bal.loc[key])       # 값은 원래 부호로
pivot

pivot_table · crosstab · unstack

두 범주를 행·열로 펼칠 때.

pt = df.pivot_table(index='region', columns='group',
                    values='amount', aggfunc='mean')
ct = pd.crosstab(df['region'], df['group'])            # 빈도
ct_r = pd.crosstab(df['region'], df['group'], normalize='index')  # 행 비율
wide = df.groupby(['region', 'group'])['amount'].mean().unstack()
merge

병합 · 이어 붙이기

파일이 두 개 주어졌을 때.

m = pd.merge(df, other, on='id', how='left')   # inner/left/right/outer
both = pd.concat([df, df], axis=0, ignore_index=True)  # 위아래
side = pd.concat([df, other], axis=1)                  # 좌우
# axis=1 은 키가 아니라 「행 번호」로 붙인다 — id 로 맞추려면 merge
corr

상관계수 · 순위 · 누적

상관계수, 순위, 누적 합 문제.

df[['age', 'score', 'amount']].corr()
df['age'].corr(df['score'])                    # 피어슨
df['age'].corr(df['score'], method='spearman')
df['rank'] = df['amount'].rank(ascending=False, method='min')
df['cum'] = df['amount'].cumsum()
df['prev'] = df['amount'].shift(1)
05

작업형 1답안 처리

값은 맞았는데 형식에서 틀린다. 정수인지, 몇째 자리인지, 버림인지 반올림인지부터 본다.

함정

정수 처리 — int 는 버림이다

답안 형식이 「정수」 「소수 N째 자리」일 때.

x = df['amount'].mean()
print(int(x))          # 소수점 버림 (0 쪽으로 자름)
print(round(x))        # 반올림 → 정수
print(round(x, 2))     # 소수 둘째 자리까지
# 「정수로(소수점 이하 버림)」      → int(x)
# 「소수 셋째 자리에서 반올림」     → round(x, 2)
# round 는 끝이 정확히 .5 면 짝수 쪽으로 간다: round(2.5) → 2, round(3.5) → 4
# 값이 .5 로 딱 떨어지면 출력값을 눈으로 한 번 더 본다
math

음수 · 올림 · 내림

값이 음수일 수 있을 때, 올림·내림 지시가 있을 때.

import math
print(int(-2.7))         # -2  (0 쪽으로)
print(math.floor(-2.7))  # -3  (아래로)
print(math.ceil(2.1))    # 3
np.floor(df['score'])    # Series 버림
np.ceil(df['score'])
sum

처음부터 정수인 값

개수를 물을 때. int() 를 따로 안 씌워도 된다.

print((df['amount'] >= 150000).sum())   # 조건 만족 개수
print(df['views'].isna().sum())         # 결측 개수
print(df['flag'].sum())                 # 0/1 합
print(len(df[df['flag'] == 1]))
필수

최종 답은 값 하나만

답을 입력하기 직전.

cond = df['group'] == 'G1'
print('G1 행 수:', cond.sum())     # 점검용은 설명을 붙여 출력

answer = round(df.loc[cond, 'score'].mean(), 2)
print(answer)                      # 답안 칸에는 이 숫자만 입력
06

작업형 2전처리

target·id 분리 → 결측 → 인코딩 → train 기준으로 컬럼 맞추기. 이 순서만 지키면 된다.

sklearn

라이브러리 · 데이터 불러오기

작업형 2 시작할 때 한 번에.

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.metrics import roc_auc_score, f1_score, accuracy_score
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

train = pd.read_csv('data/train.csv')
test = pd.read_csv('data/test.csv')
print(train.shape, test.shape)
target

target 찾기 · 분류인가 회귀인가

모델을 고르기 전에. 지표와 제출값이 여기서 갈린다.

# train 에만 있는 컬럼 = target 후보
print(set(train.columns) - set(test.columns))
print(train[target_col].value_counts().sort_index())
print(train[target_col].nunique())
# 값 2개   → 이진분류 (ROC-AUC 면 확률 제출)
# 값 여러 개 → 다중분류 (Macro F1 · 클래스 제출)
# 연속값   → 회귀
drop

X · y 분리 — id 는 뺀다

target 과 id 를 입력에서 뺄 때.

X_raw = train.drop(columns=[target_col, id_col]).copy()
y = train[target_col].copy()
test_raw = test.drop(columns=[id_col]).copy()
print(X_raw.shape, y.shape, test_raw.shape)
함정

결측 채우기 — 기준은 train

train·test 결측치를 같은 기준으로 채울 때.

cat_cols = X_raw.select_dtypes(include='object').columns
num_cols = X_raw.select_dtypes(exclude='object').columns

for col in num_cols:
    med = X_raw[col].median()                    # train 에서 구한 값을
    X_raw[col] = X_raw[col].fillna(med)
    test_raw[col] = test_raw[col].fillna(med)    # test 에도 그대로
for col in cat_cols:
    X_raw[col] = X_raw[col].fillna('unknown')
    test_raw[col] = test_raw[col].fillna('unknown')
필수

원-핫 인코딩 + 컬럼 맞추기

문자형 컬럼이 있을 때. test 컬럼을 train 에 맞춘다.

X_enc = pd.get_dummies(X_raw)
test_enc = pd.get_dummies(test_raw)
test_enc = test_enc.reindex(columns=X_enc.columns, fill_value=0)

print(X_enc.columns.equals(test_enc.columns))   # True 여야 한다
LabelEncoder

라벨 인코딩 (대안)

범주가 많아 원-핫이 너무 커질 때.

from sklearn.preprocessing import LabelEncoder

X_le, test_le = X_raw.copy(), test_raw.copy()
for col in cat_cols:
    le = LabelEncoder()
    le.fit(pd.concat([X_le[col], test_le[col]]))   # test 에만 있는 값 대비
    X_le[col] = le.transform(X_le[col])
    test_le[col] = le.transform(test_le[col])
prepare_features

전처리 함수로 묶기 (교재 패턴)

검증용과 최종용에 같은 전처리를 두 번 할 때.

def prepare_features(ref_X, other_X):
    ref_X, other_X = ref_X.copy(), other_X.copy()
    cat = ref_X.select_dtypes(include='object').columns
    num = ref_X.select_dtypes(exclude='object').columns
    for c in num:
        m = ref_X[c].median()
        ref_X[c] = ref_X[c].fillna(m)
        other_X[c] = other_X[c].fillna(m)
    for c in cat:
        ref_X[c] = ref_X[c].fillna('unknown')
        other_X[c] = other_X[c].fillna('unknown')
    ref_X = pd.get_dummies(ref_X)
    other_X = pd.get_dummies(other_X)
    other_X = other_X.reindex(columns=ref_X.columns, fill_value=0)
    return ref_X, other_X

X_raw = train.drop(columns=[target_col, id_col])
test_raw = test.drop(columns=[id_col])
StandardScaler

스케일링 (필요할 때만)

규제가 있는 로지스틱·KNN·SVM 을 쓸 때. 트리·일반 선형회귀엔 불필요.

from sklearn.preprocessing import StandardScaler

X_enc, test_enc = prepare_features(X_raw, test_raw)
sc = StandardScaler()
X_sc = sc.fit_transform(X_enc)      # train 은 fit_transform
test_sc = sc.transform(test_enc)    # test 는 transform 만
# 트리 모델(RandomForest)은 스케일링 없이도 된다
07

작업형 2모델 · 검증

검증으로 점수를 보고, 전체 train 으로 다시 학습해 test 를 예측한다.

train_test_split

검증 데이터 나누기

제출 전에 내 모델 점수를 확인할 때.

X_tr_raw, X_va_raw, y_tr, y_va = train_test_split(
    X_raw, y, test_size=0.2, random_state=0,
    stratify=y)              # 분류면 stratify, 회귀면 빼기
X_tr, X_va = prepare_features(X_tr_raw, X_va_raw)
RandomForest

분류 모델

이진·다중분류 기본 모델.

model = RandomForestClassifier(n_estimators=200, random_state=0)
model.fit(X_tr, y_tr)
pred = model.predict(X_va)
print(accuracy_score(y_va, pred))
함정

양성 확률 꺼내기

평가지표가 ROC-AUC 일 때.

proba = model.predict_proba(X_va)            # (행, 클래스 수)
pos = list(model.classes_).index(1)           # 라벨 1 의 열 위치
# 라벨이 문자열이면 1 대신 문제의 양성 라벨 — 예: .index('Yes')
p1 = proba[:, pos]
print(roc_auc_score(y_va, p1))                # ROC-AUC 는 확률로
metrics

분류 평가지표

검증 점수 확인. 다중분류는 average 지정.

from sklearn.metrics import precision_score, recall_score

accuracy_score(y_va, pred)
f1_score(y_va, pred)                    # 이진 (양성 = 1)
# 라벨이 문자열이면 f1_score(y_va, pred, pos_label='Yes')
f1_score(y_va, pred, average='macro')   # 다중분류 Macro F1
precision_score(y_va, pred); recall_score(y_va, pred)
roc_auc_score(y_va, p1)                 # 확률값 넣기
RandomForest

회귀 모델

target 이 연속값일 때.

Xr_tr_raw, Xr_va_raw, yr_tr, yr_va = train_test_split(
    X_raw, yr, test_size=0.2, random_state=0)
Xr_tr, Xr_va = prepare_features(Xr_tr_raw, Xr_va_raw)

reg = RandomForestRegressor(n_estimators=200, random_state=0)
reg.fit(Xr_tr, yr_tr)
r_pred = reg.predict(Xr_va)
metrics

회귀 평가지표

지표가 MAE·RMSE·RMSLE·R² 일 때.

from sklearn.metrics import mean_squared_log_error

mae = mean_absolute_error(yr_va, r_pred)
mse = mean_squared_error(yr_va, r_pred)
rmse = np.sqrt(mse)                                      # RMSE
rmsle = np.sqrt(mean_squared_log_error(yr_va, np.clip(r_pred, 0, None)))
# 음수 예측이 섞이면 sklearn 1.2 는 오류, 최신은 값이 틀어진다 → 0 으로 자른 뒤 계산
# 지표가 RMSLE 면 제출값도 np.clip(test_pred, 0, None) 으로 자른다
r2 = r2_score(yr_va, r_pred)
sklearn

다른 모델로 바꿔 보기

점수가 낮거나 모델이 지정됐을 때.

from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import GradientBoostingClassifier

LogisticRegression(max_iter=1000).fit(X_tr, y_tr)
DecisionTreeClassifier(max_depth=5, random_state=0).fit(X_tr, y_tr)
GradientBoostingClassifier(random_state=0).fit(X_tr, y_tr)
LinearRegression().fit(Xr_tr, yr_tr)
fit

최종 학습 — 전체 train 으로

검증을 마치고 test 를 예측할 때.

X_full, test_enc = prepare_features(X_raw, test_raw)
final = RandomForestClassifier(n_estimators=200, random_state=0)
final.fit(X_full, y)

pos = list(final.classes_).index(1)
test_pred = final.predict_proba(test_enc)[:, pos]   # 확률 제출
# test_pred = final.predict(test_enc)              # 클래스 제출
08

작업형 2제출 파일

파일이 틀리면 모델이 아무리 좋아도 0점이다. 저장하고 다시 읽어서 확인한다.

필수

result.csv 만들기

예측값을 제출 파일로 저장할 때.

result = pd.DataFrame({'pred': test_pred})
# sample_submission 이 주어지면 복사해서 채운다
# result = sample.copy(); result['pred'] = test_pred
result.to_csv('result.csv', index=False)   # index=False 필수
검증

저장한 파일 다시 읽어 확인

제출 직전 마지막 점검.

check = pd.read_csv('result.csv')
print(check.shape)                     # (test 행 수, 1)
print(check.columns.tolist())          # ['pred']
print(len(check) == len(test))         # True
print(check.isna().sum().sum())        # 0
print(check.head())
pred

제출값 형태 점검

확률·클래스·회귀값이 맞는 형태인지.

print(check['pred'].min(), check['pred'].max())  # 확률이면 0~1
print(check['pred'].value_counts().head())        # 클래스면 분포 확인
# target 이 양수뿐인 회귀면 음수 예측이 없는지도 본다
print((check['pred'] < 0).sum())
09

작업형 3t-검정 · 비율 검정

함수보다 「방향(alternative)」과 「무엇 − 무엇」을 먼저 정한다.

scipy

라이브러리

작업형 3 시작할 때 한 번에.

from scipy import stats
import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.stats.proportion import proportions_ztest
ttest_1samp

단일표본 t-검정

평균이 기준값과 다른지.

r = stats.ttest_1samp(df['x'], 50, alternative='two-sided')
print(round(r.statistic, 4), round(r.pvalue, 4))
함정

검정 방향 alternative

「크다」 「작다」가 문제에 나올 때.

# 대립가설 「평균이 50 보다 크다」 → greater
stats.ttest_1samp(df['x'], 50, alternative='greater')
# 「작다」 → less,  「다르다」 → two-sided (기본값)
# 두 표본이면 「첫 번째 인자 − 두 번째 인자」 기준
stats.ttest_ind(a, b, alternative='less')     # a 평균 < b 평균
shapiro

정규성 · 등분산 검정

t-검정 전에 가정을 확인하라고 할 때.

print(stats.shapiro(a).pvalue)          # p ≥ 0.05 → 정규성 기각 못 함
print(stats.levene(a, b).pvalue)        # p ≥ 0.05 → 등분산 기각 못 함
print(stats.bartlett(a, b).pvalue)
ttest_ind

독립표본 t-검정

서로 다른 두 집단의 평균 비교.

lev_p = stats.levene(a, b).pvalue
r = stats.ttest_ind(a, b, equal_var=(lev_p >= 0.05))   # 등분산 아니면 Welch
print(round(r.statistic, 4), round(r.pvalue, 4))
print(round(a.mean() - b.mean(), 4))     # 평균 차이 방향 확인
ttest_rel

대응표본 t-검정

같은 대상의 전·후 비교.

# 문제가 정한 「A − B」 순서대로 넣는다 (여기선 사후 − 사전)
# 순서를 바꾸면 t 부호와 단측 p-value 가 뒤집힌다
r = stats.ttest_rel(df['after'], df['before'], alternative='greater')
print(round(r.statistic, 4), round(r.pvalue, 4))
print(round((df['after'] - df['before']).mean(), 4))
confidence_interval

신뢰구간

「95% 신뢰구간 하한·상한」을 물을 때.

r = stats.ttest_1samp(df['x'], 50)
ci = r.confidence_interval(confidence_level=0.95)   # scipy 1.10 이상
print(round(ci.low, 4), round(ci.high, 4))

# 버전이 낮아 위가 오류면 — 버전과 상관없이 되는 방법
se = stats.sem(df['x'])
stats.t.interval(0.95, len(df) - 1, loc=df['x'].mean(), scale=se)
t

검정통계량 직접 계산

공식으로 직접 구하라고 할 때, 함수 결과 확인할 때.

n = len(df); m = df['x'].mean(); s = df['x'].std()
t = (m - 50) / (s / np.sqrt(n))
p = 2 * (1 - stats.t.cdf(abs(t), df=n - 1))   # 양측
print(round(t, 4), round(p, 4))
proportions_ztest

비율 검정 (1표본 · 2표본)

「비율이 p 와 다른가」 「두 집단 비율 차이」.

cnt, nobs = df['success'].sum(), len(df)
z, p = proportions_ztest(count=cnt, nobs=nobs, value=0.5)     # 1표본
# 기본은 표준오차를 「표본 비율」로 계산한다 (교재 풀이와 같음)
# 귀무 비율로 계산하라는 문제면 prop_var=0.5 를 더한다

s = df.groupby('cat')['success'].agg(['sum', 'count'])
z2, p2 = proportions_ztest(count=s['sum'].values,
                           nobs=s['count'].values)             # 2표본
10

작업형 3분산분석 · 카이제곱

세 집단 이상의 평균은 ANOVA, 범주끼리의 관계는 카이제곱.

f_oneway

일원분산분석 (scipy)

세 집단 이상의 평균 비교.

groups = [g['x'].values for _, g in df.groupby('group')]
r = stats.f_oneway(*groups)
print(round(r.statistic, 4), round(r.pvalue, 4))
anova_lm

분산분석표 (statsmodels)

분산분석표의 F·p 값, 이원분산분석.

model = ols('x ~ C(group)', data=df).fit()
print(sm.stats.anova_lm(model, typ=2))

# 이원분산분석 (교호작용 포함)
m2 = ols('x ~ C(group) * C(cat)', data=df).fit()
print(sm.stats.anova_lm(m2, typ=2))
# anova_lm 기본은 typ=1 — 집단 크기가 다른 이원분산분석은 typ 에 따라 F 가 달라진다
tukeyhsd

사후검정 (Tukey)

ANOVA 뒤 「어느 집단끼리 다른가」.

from statsmodels.stats.multicomp import pairwise_tukeyhsd

res = pairwise_tukeyhsd(df['x'], df['group'], alpha=0.05)
print(res)
chisquare

카이제곱 적합도

관측 분포가 기대 비율과 같은지.

obs = df['grade'].value_counts().sort_index()      # A B C D
exp_ratio = np.array([0.1, 0.2, 0.3, 0.4])
r = stats.chisquare(obs, f_exp=exp_ratio * obs.sum())   # 합이 같아야 한다
print(round(r.statistic, 4), round(r.pvalue, 4))
chi2_contingency

카이제곱 독립성

두 범주형 변수가 서로 관계있는지.

table = pd.crosstab(df['region'], df['cat'])
chi2, p, dof, expected = stats.chi2_contingency(table)
print(round(chi2, 4), round(p, 4), dof)
print(np.round(expected, 2))
# 2×2 표는 기본이 연속성 보정 — 보정 없이: correction=False
p-value

가설 기각 판단

「기각/채택」을 답으로 고를 때.

alpha = 0.05
p = r.pvalue
print('기각' if p < alpha else '채택')
# p < α → 귀무가설 기각 (차이·관계가 있다)
# p ≥ α → 귀무가설 채택 (기각하지 못한다)
11

작업형 3상관 · 회귀

statsmodels 결과에서 필요한 값 하나만 꺼내는 게 실력이다. summary 전체를 외울 필요는 없다.

pearsonr

상관분석

두 수치형 변수의 상관계수와 유의성.

r, p = stats.pearsonr(df['x'], df['y'])        # 두 값으로 받으면 버전 무관
print(round(r, 4), round(p, 4))
rho, p_s = stats.spearmanr(df['x'], df['y'])
print(round(rho, 4), round(p_s, 4))
sm.OLS

선형회귀 OLS

회귀계수·결정계수·p-value 를 물을 때.

X = sm.add_constant(df[['x', 'x2']])     # 상수항 꼭 추가
model = sm.OLS(df['y'], X).fit()
print(model.summary())
빈출

회귀 결과에서 값 꺼내기

summary 에서 특정 숫자 하나가 필요할 때.

model.params['x']          # 회귀계수
model.pvalues['x']         # 계수 p-value
model.rsquared             # 결정계수 R²
model.rsquared_adj         # 수정된 R²
model.fvalue, model.f_pvalue
model.tvalues['x']
model.params.drop('const').abs().idxmax()   # 계수 절댓값이 가장 큰 변수
ols

formula 로 회귀 (범주형 포함)

범주형 독립변수가 섞여 있을 때.

m = ols('y ~ x + x2 + C(region)', data=df).fit()
print(m.params)
print(m.rsquared)
conf_int

신뢰구간 · 예측

계수 신뢰구간, 새 값에 대한 예측값.

print(model.conf_int(alpha=0.05).loc['x'])     # 계수 95% 신뢰구간

new = pd.DataFrame({'x': [55.0], 'x2': [1]})
new_X = sm.add_constant(new, has_constant='add')[model.params.index]
print(model.predict(new_X).iloc[0])
print(model.get_prediction(new_X).summary_frame(alpha=0.05))
pvalues

유의한 변수만 다시 적합

「유의한 변수만으로 다시 적합」 지시가 있을 때.

X0 = sm.add_constant(df[['x', 'x2', 'x3']])
m0 = sm.OLS(df['y'], X0).fit()
sig = m0.pvalues.drop('const')
cols = sig[sig < 0.05].index.tolist()

m1 = sm.OLS(df['y'], sm.add_constant(df[cols], has_constant='add')).fit()
print(cols, round(m1.rsquared, 4))
get_dummies

더미 변수 만들기

범주형을 회귀에 넣을 때. 기준 범주 하나를 뺀다.

X = pd.get_dummies(df[['x', 'region']], columns=['region'],
                   drop_first=True, dtype=int)   # bool 말고 int
X = sm.add_constant(X)
sm.OLS(df['y'], X).fit().params
12

작업형 3로지스틱 회귀

계수 → exp → 오즈비. 문제에 따로 말이 없으면 「규제 없이」 푼다.

sm.Logit

로지스틱 회귀 (statsmodels)

target 이 0/1 인 회귀분석.

X = sm.add_constant(df[['x', 'x2']])
logit = sm.Logit(df['label'], X).fit(disp=False)  # 반복 로그 숨김
print(logit.params)
print(logit.pvalues)
빈출

오즈비

「오즈비」 「몇 배」를 물을 때.

odds = np.exp(logit.params)
print(round(odds['x'], 4))                        # x 1 증가 시 오즈비
print(round(np.exp(logit.params['x'] * 5), 4))    # x 5 증가 시
print(np.exp(logit.conf_int()).loc['x'])          # 오즈비 신뢰구간
predict

예측 확률 · 오분류율

확률·오분류율·의사 R² 를 물을 때.

prob = logit.predict(X)                 # label=1 일 확률
pred = (prob >= 0.5).astype(int)
err = (pred != df['label']).mean()       # 오분류율
print(round(err, 4), round(1 - err, 4))
print(round(logit.prsquared, 4))         # 의사 R²
print(round(logit.llf, 4), round(logit.aic, 4))   # 로그우도 · AIC
함정

sklearn 으로 같은 값 내기

sklearn 로 풀었는데 계수가 다르게 나올 때.

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression(penalty=None, solver='newton-cholesky',
                        tol=1e-8, max_iter=1000)   # 규제 없이 · 끝까지 수렴 (1.2 이상)
lr.fit(df[['x', 'x2']], df['label'])
print(lr.intercept_, lr.coef_)   # statsmodels Logit 과 넷째 자리까지 같다
# solver·tol 을 빼면 버전에 따라 넷째 자리가 달라진다 — 최종 답은 statsmodels 로
# penalty 인자는 sklearn 1.10 에서 없어질 예정 (1.8·1.9 는 경고만, 시험장 1.2 는 그대로)
# 기본값(penalty='l2') 그대로면 계수가 아예 달라진다
13

시험장시험장에서

인터넷이 안 된다. 함수가 기억나지 않으면 dir 과 help 로 찾는다.

help

함수 이름 · 인자 찾기

함수 이름이나 인자가 기억나지 않을 때.

import sklearn.metrics
print([m for m in dir(sklearn.metrics) if 'score' in m])
print([f for f in dir(stats) if f.startswith('ttest')])
help(stats.ttest_ind)          # 인자 · alternative 설명
option

출력이 잘릴 때

컬럼·행이 「…」로 생략될 때.

pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', 100)
pd.set_option('display.float_format', '{:.4f}'.format)
print(df.head().to_string())
version

버전 확인

함수 인자가 오류 날 때 버전부터.

import pandas, scipy, sklearn
print(pandas.__version__, sklearn.__version__, scipy.__version__)
조건에 맞는 스니펫이 없다다른 말로 찾거나 필터를 풀어 보세요.

빅데이터분석기사 실기 파이썬 스니펫 · pandas · scikit-learn · SciPy · statsmodels — 인쇄(Ctrl+P)하면 버튼 없이 코드만 나온다.