1. 데이터 리모델링의 이해
1) 데이터 리모델링이란?
- 정의: 수집된 원천 데이터(Raw Data)의 형태를 분석 목적이나 시각화 도구의 요구 조건에 맞게 데이터프레임의 구조(행과 열)를 재구성하는 프로세스다.
- 필요성: 현업이나 공공데이터 포털에서 제공되는 데이터가 항상 분석과 집계에 최적화된 형태로 제공되지는 않기 때문에 리모델링 과정이 필수적이다.
- 주요 패키지: 파이썬 생태계에서는 Pandas가 데이터 리모델링 패키지 역할을 수행한다. (R 언어의 tidyr, reshape2와 궤를 같이함)
💡 NumPy는 왜 리모델링 패키지에 속하지 않을까?
본질적 목적의 차이: NumPy는 배열의 형태를 바꾸는 함수(reshape 등)를 지원하지만, 데이터 형태의 재구성보다는 초고속 행렬 연산을 위한 고성능 수치 계산 라이브러리w에 가깝다.
- 라벨(Label)의 유무: NumPy 배열은 [0][1] 같은 컴퓨터 중심의 주소(방 번호)로만 데이터에 접근한다. 반면, Pandas는 지점, 월 등 인간 중심의 **텍스트 라벨(컬럼명)**을 시스템으로 관리하므로, 이를 기준으로 유연하게 데이터를 녹이고 피벗하는 인간 중심의 리모델링이 가능하다.
- 결론: NumPy는 Pandas 내부에서 초고속 메모리 연산을 담당하는 숨겨진 엔진이고, Pandas는 구조를 뜯어고치는 리모델링 애플리케이션이다.
2) 데이터 형태의 두 가지 분류: Wide Format vs Long Format
데이터 분석 라이브러리와 시각화 도구를 효율적으로 다루기 위해서는 두 포맷의 명확한 차이와 장단점을 이해해야 한다.
① 와이드 포맷 (Wide Format)
- 특징: 사람이 눈으로 읽고 직관적으로 파악하기 좋은 형태다. (.xlsx, .csv 보고서용 포맷)
학생 이름 1학기 국어 1학기 수학 2학기 국어 2학기 수학
| harry | 90 | 85 | 95 | 90 |
| alex | 100 | 100 | 100 | 100 |
- 장점 (인간 중심): 한 개체(예: 학생)의 모든 데이터가 한 줄(Row)에 표현된다. 사람은 정보를 가로로 훑는 데 익숙하며 공간을 적게 차지하여 인쇄용 보고서에 적합하다.
- 단점 (컴퓨터/라이브러리 관점): 데이터의 중요한 의미(학기, 과목 등)가 '컬럼명'에 숨어 있다. 컴퓨터 입장에서 1학기 수학은 단순한 텍스트일 뿐이므로, 전체 학기의 수학 평균을 구하려면 컬럼명을 일일이 파싱해 찾아내는 복잡한 로직이 강제된다. 특히 새로운 학기 데이터가 추가될 때마다 데이터프레임의 열(Column) 구조를 아예 새로 만들어야 하므로 확장성이 최악이다.
② 롱 포맷 (Long Format)
- 특징: 컴퓨터와 분석/시각화 툴(Pandas, Seaborn 등)이 가장 좋아하는 깔끔한(Tidy) 형태다. 기준 열을 고정한 채 데이터를 밑으로 길게 쌓는 방식(Melt)이다.
학생 이름 학기 과목 점수
| harry | 1학기 | 국어 | 90 |
| harry | 1학기 | 수학 | 85 |
| harry | 2학기 | 국어 | 95 |
| harry | 2학기 | 수학 | 90 |
| alex | 1학기 | 국어 | 100 |
| ... | ... | ... | ... |
- 장점 (컴퓨터/라이브러리 관점): '고정된 구조와 손쉬운 필터링'이 가능하다. 새로운 과목이나 학기가 추가되더라도 열 구조는 그대로 유지한 채 행(Row)만 아래로 추가하면 된다. 컴퓨터는 기본적으로 세로(컬럼) 방향 연산에 최적화되어 있으므로 집계 함수를 적용하기에 가장 이상적이다.
- 단점 (인간 중심): 동일한 식별자(harry)가 여러 행에 걸쳐 중복 출력되고 아래로 지나치게 길어져, 스크롤을 내리며 한눈에 데이터를 파악하기 어렵다.
📌 핵심 요약
데이터 구조에서 '행(Row)'의 추가는 비용이 매우 적고 관대하지만, '열(Column)'을 추가하거나 수정하는 것은 데이터 구조 자체를 바꾸는 일이기 때문에 연산 비용이 크고 민감하다. 따라서 열 위주의 와이드 포맷을 행 위주의 롱 포맷으로 전환하는 리모델링이 선행되어야 한다.
2. 데이터 리모델링 실전 파이프라인 (End-to-End 예제)
실제 공공데이터 포털에서 와이드 포맷의 CSV 파일을 다운로드하여
롱 포맷 리모델링 → 전처리 → 그룹 집계 → 보고서용 피벗 테이블 생성
으로 이어지는 전체 분석 파이프라인 흐름이다.
- < 참고>
- .csv → 쉼표로 구분된 값(Comma-Separated Values)을 뜻하는 파일 형식
- https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas.read_csv - 0번 .csv 파일 읽기
- 그룹별 여러 집계 연산 - 4번 데이터 집계 .agg()
- 출력 결과 - 4번 데이터 집계 .reset_index()
- groupby의 기준이 되어 인덱스로 가버린 '지점' 컬럼을 다시 일반 열로 내려주고 인덱스를 기본 숫자(0,1,2..)로 정렬
1) 예제 코드
import pandas as pd
# ==========================================
# 0. [공공데이터 시나리오] pd.read_csv() 로드 단계
# ==========================================
# ※ 실제 공공데이터 포털에서 다운로드한 '지점별_매출.csv' 파일이 아래와 같다고 가정합니다.
# ------------------------------------------
# [지점별_매출.csv 원본 형태]
# 지점,1월,2월
# "서울 ",100,150
# "부산",200,250
# "서울 ",100,150
# "광주",300,350
# ------------------------------------------
#
# [공식 문서 핵심 파라미터 적용 가이드]
# - filepath_or_buffer: '지점별_매출.csv' (읽어올 파일 경로)
# - encoding='utf-8': 한글 깨짐 방지를 위한 표준 인코딩 옵션 (윈도우 환경에선 cp949 사용)
# - header=0: 파일의 몇 번째 행을 컬럼명(헤더)으로 지정할지 설정 (기본값은 0번째 행).
# 만약 파일 첫 줄에 쓸데없는 제목이 있고 2번째 줄부터 데이터가 시작된다면 header=1로 설정하여 정제함.
#
# [코드 실행] 아래 코드를 통해 원천 CSV 파일이 '데이터프레임 단위'로 메모리에 로드됩니다.
# df_wide = pd.read_csv('지점별_매출.csv', encoding='utf-8', header=0)
# (실습 편의를 위해 read_csv 결과물과 동일한 데이터프레임을 수동 생성하여 파이프라인을 시작합니다.)
# ==========================================
# 1. 원본 데이터: 사람이 보기 편하지만 오염된 [와이드 포맷]
# ==========================================
# - '지점'명에 공백 존재 (문자열 오염 및 중복 발생)
df_wide = pd.DataFrame({
'지점': ['서울 ', '부산', '서울 ', '광주'],
'1월': [100, 200, 100, 300],
'2월': [150, 250, 150, 350]
})
print("=== [1] 원본 와이드 포맷 ===")
print(df_wide)
# ==========================================
# 2. 리모델링: 컴퓨터가 좋아하는 [롱 포맷]으로 구조 변경 (Melt)
# ==========================================
# [melt() 핵심 파라미터 3대장 한 줄 요약]
# - id_vars='지점': 세로로 녹이지 않고 기준점으로 고정해 둘 '기둥' 컬럼을 지정합니다.
# - var_name='월': 가로로 나열되어 있던 기존 컬럼명('1월', '2월')들을 모아서 새로 만들 '열 이름'입니다.
# - value_name='매출': 그 컬럼들 밑에 적혀 있던 진짜 숫자(값)들을 모아서 새로 만들 '열 이름'입니다.
df_long = df_wide.melt(
id_vars='지점',
var_name='월',
value_name='매출'
)
print("\\n=== [2] melt 적용 후 롱 포맷 ===")
print(df_long)
# ==========================================
# 3. 데이터 변환(Transformation): 롱 포맷 상태에서 '단 한 줄로' 정제
# ==========================================
# - 롱 포맷은 구조가 고정되어 있어 컬럼이 늘어나도 전처리 코드가 변하지 않음
df_long['지점'] = df_long['지점'].str.strip() # 문자열 처리: 공백 제거로 '서울 '을 '서울'로 통일
df_long = df_long.drop_duplicates() # 중복 제거: 공백이 합쳐지면서 생긴 진짜 중복 행 제거
print("\\n=== [3] 데이터 변환 및 정제 완료 ===")
print(df_long)
# ==========================================
# 4. 데이터 집계(Aggregation): 6대 핵심 함수와 요약 표 완성
# ==========================================
# - 개별 기본 집계 함수 (sum, mean, count, max, min)를 .agg()로 묶어 다중 집계 수행
# - groupby()를 결합하여 지점별로 완벽하게 요약된 표(DataFrame)를 생성
df_result = df_long.groupby('지점')['매출'].agg(['sum', 'mean', 'count', 'max', 'min']).reset_index()
# 팀원들이 보기 편하게 요약 표 컬럼명 정제
df_result.columns = ['지점', '총합(sum)', '평균(mean)', '개수(count)', '최대(max)', '최소(min)']
print("\\n=== [4] 최종 데이터 집계 결과 (요약 표) ===")
print(df_result)
# ==========================================
# 5. 데이터 재구조화: 집계 완료된 데이터를 다시 보고서용 [피벗 테이블]로 변환
# ==========================================
# [공식 문서 pivot() 파라미터 설명]
# - index='지점': 새로운 표의 행(Row) 자리에 위치할 기준 컬럼을 지정합니다.
# - columns='지표': 새로운 표의 열(Column) 자리에 가로로 나열할 기존 행 데이터들을 지정합니다.
# - values='값': 표의 내부에 채워 넣을 진짜 수치형 데이터 컬럼을 지정합니다.
# 집계 표(df_result)를 사람이 가로로 한눈에 비교하기 좋게 '총합'과 '평균' 지표만 골라 피벗을 수행합니다.
df_long_summary = df_result.melt(id_vars='지점', var_name='지표', value_name='값') # 피벗을 보여주기 위해 살짝 롱 포맷화
df_final_pivot = df_long_summary.pivot(index='지점', columns='지표', values='값')
print("\\n=== [5] 최종 보고서용 피벗 테이블 (Pivot 완료) ===")
print(df_final_pivot)
2) 단계별 출력 결과
=== [1] 원본 와이드 포맷 ===
지점 1월 2월
0 서울 100 150
1 부산 200 250
2 서울 100 150
3 광주 300 350
=== [2] melt 적용 후 롱 포맷 ===
지점 월 매출
0 서울 1월 100
1 부산 1월 200
2 서울 1월 100
3 광주 1월 300
4 서울 2월 150
5 부산 2월 250
6 서울 2월 150
7 광주 2월 350
=== [3] 데이터 변환 및 정제 완료 ===
지점 월 매출
0 서울 1월 100
1 부산 1월 200
3 광주 1월 300
4 서울 2월 150
5 부산 2월 250
7 광주 2월 350
=== [4] 최종 데이터 집계 결과 (요약 표) ===
지점 총합(sum) 평균(mean) 개수(count) 최대(max) 최소(min)
0 광주 650 325.0 2 350 300
1 부산 450 225.0 2 250 200
2 서울 250 125.0 2 150 100
=== [5] 최종 보고서용 피벗 테이블 (Pivot 완료) ===
지표 개수(count) 총합(sum) 최대(max) 최소(min) 평균(mean)
지점
광주 2.0 650.0 350.0 300.0 325.0
부산 2.0 450.0 250.0 200.0 225.0
서울 2.0 250.0 150.0 100.0 125.0
3. 핵심 요약 및 결론
- 데이터 전처리와 집계는 유기적인 파이프라인이다: 데이터 리모델링과 전처리, 집계는 각각 분리된 작업이 아니다. 외부 정형 데이터(CSV) 로드 후 [컴퓨터가 좋아하는 롱 포맷 변환 (melt)] → [일괄 데이터 정제] → [그룹 기반 다중 집계 (groupby + agg)]→ [최종 사람 중심 보고서 변환 (pivot)]으로 이어지는 선형적 파이프라인 구조를 가질 때 개발 생산성과 코드 가독성이 극대화된다.
- 리모델링의 본질은 유지보수성 확보다:
- 롱 포맷으로 데이터를 리모델링하면 월별 컬럼이 아무리 우측으로 추가되거나 데이터의 양이 늘어나도 전처리 및 집계 코드가 단 한 줄도 변하지 않는 강력한 확장성을 확보할 수 있다. 이것이 현업 분석가들이 번거로운 형태 변환을 매 프로젝트마다 선행하는 핵심 원동력이다.
'IT' 카테고리의 다른 글
| [Deep Learning] 경사 하강법과 Adam 옵티마이저 차이: 수식과 코드로 이해하는 장단점 비교 (0) | 2026.06.19 |
|---|---|
| [FastAPI] async/await는 왜 필요할까? 비동기 처리의 본질과 모델 추론 API 예제로 이해하기 (0) | 2026.05.30 |