Fullstack 68

heo4·2026년 7월 22일

Fullstack

목록 보기
23/71

풀스택

Pandas 실전 활용 - groupby로 데이터 요약본 만들기

국비과정에서 배운 Pandas의 groupby를 정리했다. 그룹별 통계를 뽑아내는, 데이터 분석에서 가장 자주 쓰이는 기능 중 하나다.

1. groupby의 핵심 원리: Split - Apply - Combine

groupby는 복잡해 보이지만 딱 3단계만 기억하면 된다.

  1. Split (분할): 기준(예: 항공사)에 따라 데이터를 나눈다.
  2. Apply (적용): 각 그룹에 대해 평균(mean)이나 개수(count)를 계산한다.
  3. Combine (결합): 계산된 결과를 하나의 표로 다시 합친다.

즉 "기준별로 쪼개고 → 각각 계산하고 → 다시 합치는" 흐름이라고 이해하면 된다.


2. 예제

예제 1) 항공사별 평균 가격 구하기

가장 기본이 되는 그룹화 연산이다.

import pandas as pd

# 1. 데이터 불러오기 (인덱스 컬럼 지정)
df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 2. 항공사(airline)별로 그룹을 묶고, 가격(price)의 평균 구하기
# [해석] airline으로 묶어서 -> price 컬럼을 선택해 -> mean(평균)을 내라!
airline_price = df.groupby('airline')['price'].mean()

print("--- 항공사별 평균 항공권 가격 ---")
print(airline_price)

groupby('기준컬럼')['대상컬럼'].통계함수() 형태를 하나의 문장처럼 읽으면 이해가 쉽다. "airline로 묶어서 → price를 선택해 → mean을 내라"는 식으로.

같은 방식으로 기준 컬럼만 바꿔도 된다.

df = pd.read_csv("Clean_Dataset.csv")

airline_price = df.groupby("class")["price"].mean()

print("--- 등급별 평균 항공권 가격 ---")
print(airline_price)

예제 2) 여러 개의 통계 한 번에 보기

평균뿐만 아니라 최댓값, 최솟값, 개수까지 한 번에 보고 싶을 때는 agg()를 쓴다.

import pandas as pd

df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# agg() 함수는 여러 함수를 리스트 형태로 전달할 수 있다.
airline_stats = df.groupby('airline')['price'].agg(['mean', 'max', 'min', 'count'])

print("--- 항공사별 가격 상세 통계 ---")
print(airline_stats)

agg(['mean', 'max', 'min', 'count'])처럼 문자열 리스트로 원하는 통계 함수를 나열하면, 각 그룹에 대해 그 함수들을 전부 계산해서 컬럼별로 정리해준다.


3. 연습문제

Clean_Dataset.csv를 사용해서 출발 도시(source_city)별 평균 비행 시간(duration)을 구하고, 비행 시간이 긴 순서(내림차순)로 정렬해서 출력하기.

정답 코드 보기
import pandas as pd

df = pd.read_csv('clean_dataset.csv')

source_duration = df.groupby('source_city')['duration'].agg(['mean'])

print(source_duration.sort_values(by=['mean'], ascending=False))

마무리

  • groupby는 "Split(분할) → Apply(적용) → Combine(결합)"이라는 3단계로 이해하면 복잡해 보이는 코드도 명확해진다.
  • 통계 하나만 필요하면 .mean(), .max()처럼 바로 붙이고, 여러 개가 필요하면 .agg([...])로 한 번에 뽑는 걸로 구분해서 기억하자.
  • groupby 결과에도 sort_values()를 그대로 적용할 수 있어서, "그룹별 집계 → 정렬"은 세트로 자주 함께 쓰인다.

원-핫 인코딩(One-Hot Encoding) 정리

국비과정에서 배운 원-핫 인코딩을 정리했다. 문자열 데이터를 AI 모델이 이해할 수 있는 숫자로 바꾸는 대표적인 전처리 방법이다. pd.get_dummies() 사용법과 drop_first가 왜 필요한지를 중심으로 다룬다.

1. 원-핫 인코딩 핵심 메소드 (Pandas)

메소드 / 파라미터사용 예시
pd.get_dummies()'성별' 컬럼 하나가 '성별남', '성별여' 두 개의 새 열로 분리됨
columns=['컬럼명']전체 컬럼 중 '항공사', '도시' 등 특정 문자열 컬럼만 선택해서 변환
drop_first=True'남/여' 두 열 중 '남'만 남김 (1이면 남성, 0이면 여성으로 인식해 중복 제거)
dtype=int결과 표의 값이 True/False 대신 1/0이라는 숫자로 출력됨

2. 왜 열을 하나 삭제할까? (drop_first)

문제점: 중복 정보

성별_남이 1인 순간 성별_여는 무조건 0이다. 즉 하나만 알아도 나머지는 100% 예측 가능한 중복 정보다. AI 모델은 이런 불필요한 중복(다중공선성)이 있으면 계산 오류를 낼 확률이 높아진다.

이름성별_남성별_여
철수10
영희01

해결: 하나만 남기기

drop_first=True를 쓰면 열은 하나만 남지만 구분은 여전히 완벽하다. 데이터 양은 줄고, AI는 헷갈리지 않는 최적의 상태가 된다.

이름성별_남정체
철수1남자니까 1
영희00이면 자동으로 여성

3. 예제

예제 1) 가장 쉬운 성별 예제

import pandas as pd

# 1. 샘플 데이터 생성
df_person = pd.DataFrame({'이름': ['철수', '영희', '민수'], '성별': ['남', '여', '남']})

# 2. 원-핫 인코딩 적용 (drop_first=True)
# '성별_남' 열만 남게 되며, 0인 데이터가 여성을 의미함
df_gender = pd.get_dummies(df_person, columns=['성별'], drop_first=True, dtype=int)

print("--- 성별 인코딩 결과 ---")
print(df_gender)

예제 2) 카테고리가 3개인 경우 (항공사)

카테고리가 2개보다 많아도 원리는 같다. drop_first=True를 쓰면 카테고리 개수보다 하나 적은 열이 만들어진다.

import pandas as pd

# 1. 항공사 데이터 생성
df_air = pd.DataFrame({'항공사': ['Air_India', 'Vistara', 'Indigo', 'Vistara']})

# 2. 원-핫 인코딩
# Indigo와 Vistara 열만 남고, 둘 다 0이면 Air_India를 의미함
df_air_enc = pd.get_dummies(df_air, columns=['항공사'], drop_first=True, dtype=int)

print("\n--- 항공사 인코딩 결과 ---")
print(df_air_enc)

카테고리가 3개(Air_India, Vistara, Indigo)면 열이 2개(Vistara, Indigo)만 남는데, 둘 다 0이면 자동으로 나머지 하나(Air_India)를 의미하는 식이다.

예제 3) 실제 데이터에 적용하기

여러 컬럼을 한 번에 인코딩할 수도 있다.

import pandas as pd

# 1. 실제 데이터 로드
df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 2. 인코딩할 컬럼들 리스트업
target_cols = ['airline', 'source_city', 'destination_city']

# 3. 한 번에 인코딩 적용 및 1/0 숫자로 고정
df_final = pd.get_dummies(df, columns=target_cols, drop_first=True, dtype=int)

print(f"\n인코딩 후 컬럼 개수: {df_final.shape[1]}개")
print(df_final.head())

columns 파라미터에 리스트로 여러 컬럼을 넣으면, 지정한 컬럼들만 골라서 한 번에 원-핫 인코딩해준다. 나머지 컬럼은 그대로 유지된다.


4. 연습문제

문제 1

Clean_Dataset.csv를 불러와서 좌석 등급을 나타내는 'class' 컬럼에 대해 원-핫 인코딩을 수행하기.

  • drop_first=True 옵션 사용
  • 결과값이 True/False가 아닌 0과 1로 나오도록 dtype=int 옵션 사용
  • 변환 후 df.columns를 출력해서 어떤 컬럼이 남았는지 확인
풀이 방향 보기
import pandas as pd

df = pd.read_csv('Clean_Dataset.csv', index_col=0)

df = pd.get_dummies(df, columns=['class'], drop_first=True, dtype=int)

print(df.columns)

문제 2

Clean_Dataset.csv에서 'airline'과 'stops' 두 컬럼을 동시에 원-핫 인코딩하기.

  • 인코딩 후 생성된 새로운 표를 답안10이라는 변수에 저장
  • 인코딩 전후 컬럼 개수를 각각 출력해서 비교 (힌트: df.shape)
풀이 방향 보기
import pandas as pd

df = pd.read_csv('Clean_Dataset.csv', index_col=0)

print("인코딩 전 컬럼 개수:", df.shape[1])

답안10 = pd.get_dummies(df, columns=['airline', 'stops'], drop_first=True, dtype=int)

print("인코딩 후 컬럼 개수:", 답안10.shape[1])

마무리

  • 원-핫 인코딩은 문자열(카테고리) 데이터를 0과 1로 이루어진 여러 열로 쪼개서, AI 모델이 계산할 수 있는 숫자 형태로 바꿔주는 전처리 기법이다.
  • drop_first=True는 카테고리 하나를 삭제해도 나머지 값들의 조합으로 완벽히 구분되는, 불필요한 중복(다중공선성)을 없애는 옵션이다.
  • dtype=int를 붙이면 결과가 True/False 대신 1/0으로 나와서 이후 계산이나 확인이 더 편해진다.

AI를 위한 데이터 전처리 정리

국비과정에서 배운 머신러닝용 데이터 전처리를 정리했다. 원-핫 인코딩부터 스케일링, 학습/테스트 데이터 분리, 그리고 가장 중요한 데이터 누수 방지까지 다룬다.

1. 전처리를 위한 메소드 정리 (Scikit-learn & Pandas)

분류메소드 / 함수역할 및 목적
선택 및 삭제select_dtypes()특정 타입(예: 문자열)의 컬럼만 자동으로 추출
선택 및 삭제drop()분석에 방해되는 불필요한 열(ID, 편명 등) 삭제
범주형 변환pd.get_dummies()문자열 데이터를 0과 1의 여러 열로 변환 (원-핫 인코딩)
범주형 변환LabelEncoder()문자를 0, 1, 2 ... 순서 있는 숫자로 변환
수치형 변환StandardScaler()평균 0, 표준편차 1로 데이터 크기 맞춤
수치형 변환MinMaxScaler()최솟값 0, 최댓값 1로 데이터 범위 고정
데이터 분리train_test_split()학습용(문제집)과 검증용(시험지) 데이터로 분리

2. AICE 대비 전처리 가이드

  1. 불필요한 데이터 제거: flight(편명)처럼 고유값이 너무 많은 문자열이나 Unnamed: 0 같은 인덱스는 모델의 혼란만 초래하므로 가장 먼저 지워야 한다.
  2. 데이터 누수(Data Leakage) 금지: 가장 중요하다. 스케일링(fit)은 반드시 학습 데이터(Train)로만 진행해야 한다. 테스트 데이터의 정보를 미리 알게 되면 "컨닝"과 같아서 시험 점수(모델 성능)가 왜곡된다.
  3. 원-핫 인코딩의 drop_first=True: 다중공선성 문제를 피하기 위해 첫 번째 카테고리를 삭제하는 게 통계적으로 더 안전하다.

3. 원-핫 인코딩이란? (다시 짚어보기)

인공지능은 글자를 읽지 못하니, 숫자로 바꿔주되 "공평하게" 바꿔주는 기술이라고 보면 된다.

컴퓨터는 '에어부산', '아시아나' 같은 글자를 이해하지 못한다. 그래서 숫자로 바꿔야 하는데, 만약 에어부산을 1, 아시아나를 2로 바꾸면(레이블 인코딩) AI는 "아시아나가 에어부산보다 2배 더 큰 건가?", "등급이 더 높은 건가?"라고 착각하게 된다.

이런 잘못된 서열을 없애기 위해, 각 항목을 아예 독립적인 새로운 열로 만드는 방식이 원-핫 인코딩이다.

예를 들어 항공사 컬럼에 세 가지 값이 있다면 이렇게 변한다.

번호항공사
1Air_India
2Vistara
3Indigo

↓ 원-핫 인코딩 적용 후

번호Air_IndiaVistaraIndigo
1100
2010
3001

원-핫 인코딩 실습 코드

import pandas as pd

# 1. 아주 단순한 성별 데이터
df_gender = pd.DataFrame({'성별': ['남', '여', '여', '남']})

# 2. 원-핫 인코딩 (하나 지우기 적용)
# '남' 열이 사라지고 '여' 열만 남거나, 그 반대가 된다.
df_simple = pd.get_dummies(df_gender, columns=['성별'], drop_first=True)

print("--- 성별 인코딩 결과 ---")
print(df_simple)
import pandas as pd

# 1. 간단한 예시 데이터 생성
df = pd.DataFrame({'항공사': ['Air_India', 'Vistara', 'Indigo', 'Vistara']})

# 2. 원-핫 인코딩 적용
# drop_first=True: 첫 번째 열을 삭제해서 데이터 중복(다중공선성)을 방지 (시험 꿀팁!)
df_encoded = pd.get_dummies(df, columns=['항공사'], drop_first=True)

print(df_encoded)

4. 예제

예제 1) 문자열 컬럼만 찾아서 한 번에 인코딩

import pandas as pd

# 1. 데이터 로드
df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 2. 분석에 방해되는 고유값/ID성 컬럼 삭제
df = df.drop(columns=['flight'])

# 3. 문자열(object) 타입인 컬럼명만 자동으로 추출
cat_cols = df.select_dtypes(include='object').columns.tolist()
print(f"인코딩 대상: {cat_cols}")

# 4. 원-핫 인코딩 적용 (범주형 -> 숫자형)
df_encoded = pd.get_dummies(df, columns=cat_cols, drop_first=True)

print(df_encoded.head())

select_dtypes(include='object')를 쓰면 문자열 컬럼이 몇 개든 일일이 이름을 나열할 필요 없이 자동으로 찾아낼 수 있다.

예제 2) 데이터 분리 후 올바른 스케일링 (누수 방지)

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 1. CSV 데이터 불러오기
df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 2. 인코딩 (AI가 이해할 수 있게 글자를 숫자로 변환)
df_encoded = pd.get_dummies(df, drop_first=True, dtype=int)

# 3. X(문제)와 y(정답) 분리
X = df_encoded.drop('price', axis=1)
y = df_encoded['price']

# 4. 데이터 분리 (학습용 80% : 테스트용 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 5. 스케일링 (숫자들의 단위/체급 맞추기)
scaler = StandardScaler()

# [중요] 학습 데이터(Train)로만 기준을 잡고(fit) 변환(transform)한다
X_train_s = scaler.fit_transform(X_train)

# [중요] 테스트 데이터(Test)는 학습 때 만든 기준을 그대로 '적용'만 한다
X_test_s = scaler.transform(X_test)

print("--- 전처리 및 스케일링 완료 ---")
print(f"최종 문제 데이터(X_train_s) 형태: {X_train_s.shape}")

⚠️ 데이터 누수(Data Leakage): fit_transform()은 학습 데이터에만 쓰고, 테스트 데이터에는 transform()만 써야 한다. 테스트 데이터로도 fit을 하면, 모델이 시험 문제(테스트 데이터)의 정보를 미리 훔쳐본 것과 같아서 실제 성능보다 좋게 나오는 착시가 생긴다.

예제 3) 결측치 처리와 인코딩의 결합

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder

# 1. 데이터 로드
df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 2. 특정 컬럼(duration)의 결측치를 중앙값으로 채우기
df['duration'] = df['duration'].fillna(df['duration'].median())

# 3. 좌석 등급(class)을 레이블 인코딩 (순서가 있는 경우)
le = LabelEncoder()
df['class'] = le.fit_transform(df['class'])

print(df[['class', 'duration']].head())

💡 LabelEncoder는 "Economy < Business"처럼 값 사이에 순서/서열이 있는 데이터에 적합하다. 반대로 항공사나 도시처럼 순서가 없는 데이터는 원-핫 인코딩을 쓰는 게 맞다.


5. 연습문제

문제 1

특성 선택 및 범주형 변수 처리하기.

  • 'airline', 'source_city', 'destination_city' 컬럼만 원-핫 인코딩 적용
  • 'departure_time', 'arrival_time', 'stops' 컬럼은 분석에서 제외(삭제)
  • 최종 데이터프레임의 열 개수 확인
풀이 방향 보기
import pandas as pd

df = pd.read_csv('Clean_Dataset.csv', index_col=0)

# 1. 불필요한 컬럼 삭제
df = df.drop(columns=['departure_time', 'arrival_time', 'stops'])

# 2. 지정한 컬럼만 원-핫 인코딩
target_cols = ['airline', 'source_city', 'destination_city']
df_encoded = pd.get_dummies(df, columns=target_cols, drop_first=True, dtype=int)

print("최종 컬럼 개수:", df_encoded.shape[1])

문제 2

다음 조건에 맞춰 데이터 전처리하기.

  • 정답 데이터를 price로, 나머지를 독립변수로 설정
  • 학습용:테스트용 = 7:3으로 분리 (random_state=10)
  • MinMaxScaler로 수치형 데이터를 0~1 범위로 조정하되, 데이터 누수가 없도록 처리
풀이 방향 보기
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

df = pd.read_csv('Clean_Dataset.csv', index_col=0)
df_encoded = pd.get_dummies(df, drop_first=True, dtype=int)

X = df_encoded.drop('price', axis=1)
y = df_encoded['price']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=10
)

scaler = MinMaxScaler()

# 학습 데이터로만 기준을 잡고 변환
X_train_s = scaler.fit_transform(X_train)
# 테스트 데이터는 학습 때 만든 기준을 그대로 적용만
X_test_s = scaler.transform(X_test)

마무리

  • 전처리의 기본 순서는 불필요한 컬럼 제거 → 결측치 처리 → 범주형 인코딩 → 학습/테스트 분리 → 스케일링 순서로 흘러간다.
  • 스케일링은 반드시 학습 데이터에 fit, 테스트 데이터엔 transform만 — 이 순서를 바꾸면 데이터 누수가 발생해 모델 성능 평가가 왜곡된다.
  • 순서가 있는 범주(Economy < Business)는 LabelEncoder, 순서가 없는 범주(항공사, 도시)는 get_dummies(원-핫 인코딩)로 구분해서 쓰자.

0개의 댓글