반응형
🔧 함수 매핑 (apply, map)
판다스에서 데이터 변환의 핵심은 함수 매핑입니다.
- 데이터(Series, DataFrame)의 각 원소에 함수를 적용하는 것
- 반복문(for) 없이도 각 값에 같은 작업을 할 수 있게 해 줌
📌 시리즈에 함수 적용
- 시리즈의 각 원소에 함수 1번씩 적용
- 사용자 정의 함수나 람다 함수 모두 가능
import pandas as pd
import numpy as np
# 샘플 데이터 생성
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'age': [25, 30, 35, 28],
'salary': [50000, 60000, 70000, 55000]
})
display(df)
# 사용자 정의 함수 적용
def add_10(n):
return n + 10
# 시리즈에 함수 적용
sr1 = df['age'].apply(add_10)
print("add_10 함수 적용 결과:")
print(sr1)
# 람다 함수 사용
sr2 = df['age'].apply(lambda n: n + 10)
print("\n람다 함수 적용 결과:")
print(sr2)
📌 데이터프레임에 함수 적용
# 통계 계산 함수
def calculate_stats(series):
return pd.Series({
'mean': series.mean(),
'std': series.std(),
'min': series.min(),
'max': series.max()
})
# 각 열에 함수 적용 (axis=0)
numeric_df = df[['age', 'salary']]
result_df = numeric_df.apply(calculate_stats, axis=0)
print("각 열에 통계 함수 적용:")
print(result_df)
# 각 행에 함수 적용 (axis=1)
result_sr = numeric_df.apply(lambda x: x.max() - x.min(), axis=1)
print("\n각 행의 최대값-최소값 차이:")
print(result_sr)
🔍 조건부 필터링과 분류
조건에 따른 데이터 필터링과 새로운 열 생성 방법입니다.
📌 조건부 열 추가
# 조건에 따른 분류
df['High_Performer'] = df.apply(lambda row: 'Yes' if row['salary'] > 55000 else 'No', axis=1)
print("고성과자 분류 추가:")
print(df)
# 나이가 평균보다 높은 사람들만 필터링
avg_age = df['age'].mean()
high_age_filter = df['age'] > avg_age
filtered_df = df[high_age_filter]
print(f"\n평균 나이({avg_age:.1f})보다 높은 사람들:")
print(filtered_df)
문자열 포맷팅(f-string) 문법 복습!
- :.0f : 정수처럼 출력
- :.1f : 소수점 1자리까지 실수(float) 형태로 출력
- :.2f : 소수점 2자리까지 실수(float) 형태로 출력
- :, : 천 단위로 콤마 붙여서 출력
- :.1% : 퍼센트로 출력
⚡ pipe() 메소드와 체이닝
메소드 체이닝을 통한 연속적인 데이터 처리입니다.
# 데이터 처리 함수들
def add_bonus_column(df):
df['bonus'] = df['salary'] * 0.1
return df
def categorize_age(df):
df['age_group'] = df['age'].apply(lambda x: 'Young' if x < 30 else 'Senior')
return df
def calculate_total_compensation(df):
df['total_comp'] = df['salary'] + df['bonus']
return df
# 여러 함수를 체이닝으로 연결
result = (df.pipe(add_bonus_column)
.pipe(categorize_age)
.pipe(calculate_total_compensation))
print("파이프 체이닝 결과:")
print(result)
📊 그룹 연산 (GroupBy)
그룹별 집계와 변환의 강력한 기능입니다.
📌 기본 그룹화
# 타이타닉 데이터셋 예시
titanic_data = pd.DataFrame({
'class': ['First', 'Second', 'Third', 'First', 'Second', 'Third'],
'sex': ['male', 'female', 'male', 'female', 'male', 'female'],
'age': [22, 38, 26, 35, 45, 29],
'fare': [71.28, 71.28, 7.92, 53.10, 13.00, 7.75]
})
print("원본 타이타닉 데이터:")
print(titanic_data)
# 단일 기준 그룹화
grouped = titanic_data.groupby('class')
print("\n클래스별 평균 나이:")
print(grouped['age'].mean())
# 다중 기준 그룹화
grouped_two = titanic_data.groupby(['class', 'sex'])
print("\n클래스와 성별 그룹화:")
print(grouped_two.size())
# 집계 함수 적용
result = titanic_data.groupby('class').agg({
'age': 'mean',
'fare': ['min', 'max']
})
print("\n클래스별 집계 결과:")
print(result)
- .size() : 그룹에 속한 행(row) 개수 세어주는 함수, 결측치(NaN) 포함, 그룹에 속한 행 수 그대로 세어줌, len(그룹) 이거랑 거의 같은 의미
- .count() : 특정 컬럼의 값 개수, 결측치(NaN) 제외
- .agg() : 그룹별로 여러 통계를 한 번에 계산
📌 변환(Transformation)
그룹별로 계산은 하지만, 결과의 “길이(shape)”는 원본과 동일하게 유지, 새 컬럼 만들 때 필수
# 그룹별 누적합
titanic_data['fare_cumsum'] = titanic_data.groupby('class')['fare'].cumsum()
print("그룹별 요금 누적합:")
print(titanic_data[['class', 'fare', 'fare_cumsum']])
# z-score 계산
titanic_data['age_zscore'] = titanic_data.groupby('class')['age'].transform(
lambda x: (x - x.mean()) / x.std()
)
print("\n클래스별 나이 z-score:")
print(titanic_data[['class', 'age', 'age_zscore']])
🔗 데이터프레임 연결과 병합
여러 데이터프레임을 결합하는 방법입니다.
📌 연결(Concatenation)
- 구조가 비슷한 데이터
- 인덱스 기준으로 정렬
- join 개념 없음
- 위아래, 좌우로 붙이기
# 샘플 데이터프레임들
df1 = pd.DataFrame({
'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie'],
'score': [85, 90, 88]
})
df2 = pd.DataFrame({
'id': [4, 5, 6],
'name': ['Diana', 'Eve', 'Frank'],
'score': [92, 87, 85]
})
print("df1:")
print(df1)
print("\ndf2:")
print(df2)
# 수직 연결
result1 = pd.concat([df1, df2], axis=0, ignore_index=True)
print("\n수직 연결 결과:")
print(result1)
# 수평 연결용 데이터
df3 = pd.DataFrame({
'age': [25, 30, 35],
'city': ['Seoul', 'Busan', 'Incheon']
})
result2 = pd.concat([df1, df3], axis=1)
print("\n수평 연결 결과:")
print(result2)
- axis=0 : 밑에 붙이기
- axis=1 : 옆에 붙이기
- ignore_index=True : 인덱스 새로 붙이기
📌 병합(Merge)
- 키로 결합
- SQL의 JOIN과 동일
- 행 개수 변할 수 있음
- 관계형 데이터 결합
# 병합용 데이터프레임들
students = pd.DataFrame({
'id': [1, 2, 3, 4],
'name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'class': ['A', 'B', 'A', 'C']
})
grades = pd.DataFrame({
'id': [1, 2, 3, 5],
'subject': ['Math', 'Science', 'English', 'History'],
'grade': [95, 88, 92, 85]
})
print("students 데이터:")
print(students)
print("\ngrades 데이터:")
print(grades)
# Inner Join
merge_inner = pd.merge(students, grades, how='inner', on='id')
print("\nInner Join 결과:")
print(merge_inner)
# Left Join
merge_left = pd.merge(students, grades, how='left', on='id')
print("\nLeft Join 결과:")
print(merge_left)
- on = : 두 DataFrame을 연결할 “공통 기준 컬럼(키)”
< join 방식 (how) >
| how | 설명 |
|---|---|
| inner | 교집합 (기본) |
| left | 왼쪽 기준 |
| right | 오른쪽 기준 |
| outer | 합집합 |
📋 피벗 테이블과 재구조화
데이터의 형태를 변환하는 핵심 도구입니다.
📌 피벗 테이블
그룹화 + 집계를 한 번에 하면서 테이블 모양까지 바꿔주는 함수
aggfunc = 중복 데이터를 어떻게 하나로 만들지 정함
< 자주 쓰는 aggfunc 종류 >
- aggfunc='sum'
- aggfunc='mean'
- aggfunc='count'
- aggfunc='min'
- aggfunc='max'
📌 스택/언스택
index ↔ column을 서로 이동, MultiIndex를 다룰 때나 테이블 구조를 유연하게 바꿀 때 사용
- stack (column → index)
- unstack (index → column)
# 스택/언스택용 데이터
df_stack = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
}, index=['X', 'Y', 'Z'])
print("원본 데이터:")
print(df_stack)
# 스택: 열을 행으로 변환
stacked = df_stack.stack()
print("\n스택 결과 (열→행):")
print(stacked)
# 언스택: 행을 열로 변환
unstacked = stacked.unstack()
print("\n언스택 결과 (행→열):")
print(unstacked)
📌 Melt (wide → long)
여러 컬럼을 한 컬럼으로 접어서(long 형태) 세로로 늘리는 것
# Melt용 데이터 (Wide 형태)
wide_df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'City': ['Seoul', 'Busan', 'Incheon'],
'Math': [85, 90, 88],
'Science': [92, 87, 85],
'English': [78, 95, 92]
})
print("Wide 형태 데이터:")
print(wide_df)
# Wide to Long 형태 변환
melted_df = wide_df.melt(
id_vars=['Name', 'City'],
var_name='Subject',
value_name='Score'
)
print("\nMelt 결과 (Wide → Long):")
print(melted_df)
< Wide 형태 >
- 과목이 열(column)로 퍼져 있음
- 사람 1명 = 행 1줄
< Long 형태 >
- 분석/시각화/ML에 자주 씀
- 과목이 행(row)으로 내려옴
- “한 관측치 = (사람, 도시, 과목, 점수)” 같은 형태
< 각 파라미터 뜻 >
- id_vars : 그대로 들고 갈 컬럼
- var_name : 그대로 들고 갈 컬럼 제외하고 나머지 컬럼이 들어갈 곳의 컬럼 이름
- value_name : 접힐 컬럼의 값이 들어갈 곳의 컬럼 이름
'IT' 카테고리의 다른 글
| 통계학 기초 - 2 (0) | 2026.04.15 |
|---|---|
| 통계학 기초 - 1 (0) | 2026.04.15 |
| 판다스(Pandas) - Series와 DataFrame (1) | 2026.04.11 |
| 파이썬 클래스(Class)? (0) | 2026.04.11 |
| 파이썬 람다, 일급 객체 (1) | 2026.04.11 |