🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Pandas 심화: 그룹화와 병합 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 1. · 15 Views

Pandas 심화: 그룹화와 병합 완벽 가이드

Pandas의 groupby, pivot_table, merge, concat을 활용한 데이터 분석 기법을 배웁니다. 실무에서 자주 사용하는 그룹화와 데이터 결합 방법을 초급자도 이해할 수 있도록 쉽게 설명합니다.


목차

  1. groupby_집계_연산
  2. 다중_인덱스_활용
  3. pivot_table_생성
  4. merge로_데이터_결합
  5. concat으로_데이터_연결
  6. 실전_데이터_분석_예제

1. groupby 집계 연산

김개발 씨는 쇼핑몰 데이터를 분석하는 업무를 맡았습니다. 상사가 "카테고리별 매출 합계를 뽑아주세요"라고 요청했는데, 수천 개의 행을 어떻게 카테고리별로 묶어서 계산해야 할지 막막했습니다.

for문으로 일일이 처리해야 하나 고민하던 그때, 선배가 groupby라는 마법 같은 기능을 알려주었습니다.

groupby는 데이터를 특정 기준으로 그룹화하여 집계 연산을 수행하는 기능입니다. 마치 도서관에서 책을 장르별로 분류해 놓는 것과 같습니다.

한 번 분류해 놓으면 "소설 책이 몇 권이지?", "과학 책의 평균 페이지 수는?"과 같은 질문에 빠르게 답할 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 판매 데이터 생성
sales = pd.DataFrame({
    'category': ['전자', '의류', '전자', '식품', '의류', '식품'],
    'product': ['노트북', '셔츠', '마우스', '과자', '바지', '음료'],
    'price': [1200000, 45000, 25000, 3000, 55000, 2000],
    'quantity': [5, 20, 50, 100, 15, 200]
})

# 카테고리별 총 판매금액 계산
sales['total'] = sales['price'] * sales['quantity']
category_sales = sales.groupby('category')['total'].sum()
print(category_sales)

# 여러 집계 함수 동시 적용
category_stats = sales.groupby('category')['total'].agg(['sum', 'mean', 'count'])
print(category_stats)

김개발 씨는 입사 3개월 차 데이터 분석가입니다. 오늘 상사로부터 긴급한 요청을 받았습니다.

"김 대리, 이번 달 카테고리별 매출 현황 좀 정리해줘요. 오늘 중으로 부탁해요." 엑셀로 하자니 데이터가 10만 건이 넘습니다.

for문을 돌리자니 코드가 복잡해질 것 같았습니다. 그때 옆자리 박시니어 씨가 모니터를 힐끗 보더니 말했습니다.

"groupby 써보셨어요? 한 줄이면 끝나요." 그렇다면 groupby란 정확히 무엇일까요?

쉽게 비유하자면, groupby는 마치 학교에서 반별로 학생들을 줄 세우는 것과 같습니다. 전교생이 운동장에 흩어져 있을 때, "1반은 여기, 2반은 저기"라고 모으면 반별 인원수를 세거나 반별 평균 키를 구하기가 훨씬 쉬워집니다.

groupby도 똑같습니다. 데이터를 특정 기준으로 먼저 묶어놓고, 그 다음에 원하는 계산을 수행합니다.

groupby가 없던 시절에는 어떻게 했을까요? 개발자들은 딕셔너리를 만들고, for문을 돌면서 각 그룹에 해당하는 값을 찾아 누적해야 했습니다.

코드가 10줄, 20줄씩 늘어났습니다. 더 큰 문제는 실수하기 쉽다는 점이었습니다.

조건문 하나 잘못 쓰면 결과가 완전히 틀어졌습니다. 바로 이런 불편함을 해결하기 위해 Pandas의 groupby가 등장했습니다.

groupby를 사용하면 단 한 줄로 그룹별 집계가 가능합니다. 또한 sum, mean, count, max, min 등 다양한 집계 함수를 자유롭게 적용할 수 있습니다.

무엇보다 agg 메서드를 사용하면 여러 집계 함수를 동시에 적용할 수 있다는 큰 장점이 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

먼저 sales.groupby('category')는 category 컬럼을 기준으로 데이터를 그룹화합니다. 이 시점에서는 아직 계산이 일어나지 않습니다.

그저 "이렇게 묶을 거야"라고 준비만 하는 단계입니다. 다음으로 ['total'].sum()을 호출하면 각 그룹의 total 컬럼 값을 모두 더합니다.

결과는 카테고리별 매출 합계가 됩니다. 실제 현업에서는 어떻게 활용할까요?

마케팅 팀에서 "지역별 고객 수와 평균 구매액을 알고 싶어요"라고 요청하면, df.groupby('region').agg({'customer_id': 'count', 'purchase': 'mean'})으로 바로 해결할 수 있습니다. 재무 팀에서 "월별 매출 추이를 보고 싶어요"라고 하면, 날짜에서 월을 추출한 뒤 groupby를 적용하면 됩니다.

하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 groupby 객체를 그대로 출력하려는 것입니다.

print(df.groupby('category'))를 실행하면 데이터가 아니라 GroupBy 객체 정보만 나옵니다. 반드시 집계 함수를 호출해야 실제 결과를 볼 수 있습니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 조언대로 groupby를 적용하자 10만 건의 데이터가 카테고리별로 깔끔하게 정리되었습니다.

상사에게 보고서를 제출하며 김개발 씨는 뿌듯하게 웃었습니다. "Pandas, 정말 대단하네요!"

실전 팁

💡 - groupby 후 reset_index()를 호출하면 결과를 일반 DataFrame으로 변환할 수 있습니다

  • as_index=False 옵션을 주면 그룹 기준 컬럼이 인덱스가 아닌 일반 컬럼으로 유지됩니다

2. 다중 인덱스 활용

김개발 씨가 groupby에 익숙해질 무렵, 새로운 요청이 들어왔습니다. "카테고리별, 그리고 그 안에서 지역별로 매출을 보고 싶어요." 하나의 기준이 아니라 두 개의 기준으로 데이터를 분류해야 했습니다.

이때 등장하는 것이 바로 다중 인덱스입니다.

다중 인덱스는 여러 개의 컬럼을 기준으로 데이터를 계층적으로 구조화하는 방법입니다. 마치 대형 마트에서 "식품 코너 > 음료 섹션 > 탄산음료"처럼 여러 단계로 분류하는 것과 같습니다.

이를 통해 복잡한 데이터도 체계적으로 분석할 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 지역별 카테고리별 판매 데이터
sales = pd.DataFrame({
    'region': ['서울', '서울', '부산', '부산', '서울', '부산'],
    'category': ['전자', '의류', '전자', '의류', '전자', '식품'],
    'sales': [500, 300, 400, 250, 600, 150]
})

# 다중 기준으로 그룹화
multi_group = sales.groupby(['region', 'category'])['sales'].sum()
print(multi_group)

# 특정 레벨의 데이터 접근
print(multi_group.loc['서울'])  # 서울 지역 데이터만

# 다중 인덱스 해제
flat_df = multi_group.reset_index()
print(flat_df)

# unstack으로 피벗 형태 변환
pivoted = multi_group.unstack(fill_value=0)
print(pivoted)

김개발 씨는 이제 groupby가 손에 익었습니다. 그런데 오늘 마케팅 팀장이 새로운 요청을 했습니다.

"지역별로, 그리고 각 지역 안에서 카테고리별로 매출을 정리해주세요. 서울의 전자제품 매출, 서울의 의류 매출, 부산의 전자제품 매출...

이런 식으로요." 김개발 씨는 잠시 고민했습니다. groupby를 두 번 써야 하나?

아니면 다른 방법이 있나? 박시니어 씨가 힌트를 주었습니다.

"groupby에 리스트를 넘기면 다중 인덱스가 만들어져요." 다중 인덱스란 정확히 무엇일까요? 쉽게 비유하자면, 다중 인덱스는 마치 서류 캐비닛과 같습니다.

최상위 서랍에는 "서울", "부산"이라는 라벨이 붙어 있고, 각 서랍을 열면 그 안에 "전자", "의류", "식품"이라는 폴더가 있습니다. 원하는 서류를 찾으려면 먼저 서랍을 선택하고, 그 다음 폴더를 선택합니다.

다중 인덱스도 이렇게 계층적으로 데이터를 정리합니다. 다중 인덱스가 없다면 어떻게 해야 할까요?

"서울_전자", "서울_의류"처럼 두 컬럼을 문자열로 합쳐서 새로운 컬럼을 만들어야 합니다. 하지만 이렇게 하면 "서울 지역의 모든 데이터"를 추출하기가 어려워집니다.

문자열 파싱을 해야 하니까요. 다중 인덱스를 사용하면 이런 문제가 깔끔하게 해결됩니다.

위의 코드를 살펴보겠습니다. groupby(['region', 'category'])처럼 리스트로 여러 컬럼을 전달하면, Pandas는 자동으로 다중 인덱스 구조를 만들어줍니다.

결과물의 인덱스가 (서울, 전자), (서울, 의류)처럼 튜플 형태로 표시되는 것을 볼 수 있습니다. 특정 레벨의 데이터에 접근하는 것도 간단합니다.

multi_group.loc['서울']이라고 하면 서울 지역의 모든 카테고리별 데이터가 추출됩니다. 마치 캐비닛에서 서울 서랍만 꺼내는 것과 같습니다.

실무에서 자주 사용하는 기능 중 하나가 unstack입니다. 이 메서드는 다중 인덱스의 한 레벨을 컬럼으로 이동시켜 피벗 테이블처럼 만들어줍니다.

행에는 지역, 열에는 카테고리가 배치되어 한눈에 비교하기 좋은 형태가 됩니다. 반대로 다중 인덱스를 완전히 해제하고 싶다면 **reset_index()**를 사용합니다.

인덱스였던 region과 category가 일반 컬럼으로 돌아오면서 평평한 DataFrame이 됩니다. 주의할 점이 있습니다.

다중 인덱스 상태에서 데이터를 수정하거나 새로운 컬럼을 추가하려면 번거로울 수 있습니다. 분석 단계에서는 다중 인덱스가 편리하지만, 데이터를 가공하거나 저장할 때는 reset_index로 평평하게 만드는 것이 좋습니다.

김개발 씨는 다중 인덱스로 정리한 데이터를 unstack으로 변환하여 깔끔한 피벗 테이블을 만들었습니다. 마케팅 팀장이 "이거 딱 내가 원하던 형태야!"라며 엄지를 치켜세웠습니다.

실전 팁

💡 - xs 메서드를 사용하면 특정 레벨의 값을 기준으로 데이터를 추출할 수 있습니다

  • swaplevel로 인덱스 레벨의 순서를 바꿀 수 있습니다

3. pivot table 생성

김개발 씨는 엑셀의 피벗 테이블을 자주 사용했습니다. 행과 열을 자유롭게 배치하고, 값을 집계하는 강력한 기능이었죠.

"Pandas에도 이런 게 있으면 좋을 텐데..." 있습니다. 바로 pivot_table입니다.

groupby와 unstack을 한 번에 처리하는 강력한 도구입니다.

pivot_table은 데이터를 행과 열 기준으로 재구성하면서 집계 연산을 수행하는 기능입니다. 엑셀의 피벗 테이블과 동일한 개념으로, 복잡한 데이터를 보기 좋은 표 형태로 요약할 수 있습니다.

groupby보다 직관적인 문법으로 같은 결과를 얻을 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd
import numpy as np

# 월별 지역별 판매 데이터
sales = pd.DataFrame({
    'month': ['1월', '1월', '1월', '2월', '2월', '2월'],
    'region': ['서울', '부산', '서울', '부산', '서울', '부산'],
    'category': ['전자', '전자', '의류', '의류', '전자', '의류'],
    'sales': [100, 80, 50, 40, 120, 60],
    'quantity': [10, 8, 25, 20, 12, 30]
})

# 기본 피벗 테이블: 지역별, 월별 매출 합계
pivot1 = pd.pivot_table(sales, values='sales', index='region',
                        columns='month', aggfunc='sum')
print(pivot1)

# 다중 집계 함수 적용
pivot2 = pd.pivot_table(sales, values='sales', index='region',
                        columns='month', aggfunc=['sum', 'mean'])
print(pivot2)

# 행 합계와 열 합계 추가
pivot3 = pd.pivot_table(sales, values='sales', index='region',
                        columns='month', aggfunc='sum', margins=True)
print(pivot3)

김개발 씨는 예전 회사에서 엑셀 피벗 테이블을 정말 많이 썼습니다. 드래그 앤 드롭으로 행과 열을 배치하면 순식간에 요약 테이블이 만들어졌죠.

"Python에서는 이게 안 되나?"라고 생각했는데, Pandas의 pivot_table이 그 역할을 해준다는 것을 알게 되었습니다. pivot_table이란 정확히 무엇일까요?

쉽게 비유하자면, pivot_table은 마치 레고 블록을 재조립하는 것과 같습니다. 같은 레고 조각들을 가지고 있어도, 어떻게 배치하느냐에 따라 집도 되고 자동차도 됩니다.

pivot_table도 마찬가지입니다. 같은 데이터를 가지고 행에 무엇을 놓고, 열에 무엇을 놓느냐에 따라 완전히 다른 관점의 분석이 가능합니다.

사실 pivot_table은 groupby와 unstack을 합친 것과 비슷합니다. 하지만 문법이 훨씬 직관적입니다.

위의 코드에서 핵심 파라미터를 살펴보겠습니다. values는 집계할 값이 담긴 컬럼입니다.

index는 행 방향의 기준이 됩니다. columns는 열 방향의 기준입니다.

aggfunc는 집계 함수로, 기본값은 mean입니다. 특히 유용한 기능이 margins 옵션입니다.

margins=True를 설정하면 행 합계와 열 합계가 자동으로 추가됩니다. 엑셀에서 피벗 테이블 만들 때 "총합계 표시"를 체크하는 것과 같습니다.

실무에서 pivot_table은 정말 자주 사용됩니다. 예를 들어 "월별, 상품 카테고리별 매출 현황표를 만들어주세요"라는 요청이 있다면, pivot_table 한 줄로 해결됩니다.

결과물을 그대로 엑셀로 내보내면 보고서가 완성됩니다. aggfunc에 리스트를 전달하면 여러 집계 함수를 동시에 적용할 수 있습니다.

aggfunc=['sum', 'mean', 'count']처럼 작성하면 합계, 평균, 개수가 모두 포함된 종합 테이블이 만들어집니다. 주의할 점이 있습니다.

pivot_table에서 특정 조합에 해당하는 데이터가 없으면 NaN이 표시됩니다. 이때 fill_value=0 옵션을 추가하면 결측값을 0으로 채울 수 있습니다.

또 하나 알아두면 좋은 점은 pivotpivot_table의 차이입니다. pivot은 단순히 데이터를 재배치만 하고 집계는 하지 않습니다.

반면 pivot_table은 집계 기능이 포함되어 있어서 같은 조합에 여러 값이 있어도 처리할 수 있습니다. 김개발 씨는 pivot_table로 만든 보고서를 상사에게 보여주었습니다.

"오, 엑셀 피벗이랑 똑같네! Python으로도 이렇게 할 수 있구나." 상사의 감탄에 김개발 씨는 어깨가 으쓱해졌습니다.

실전 팁

💡 - aggfunc에 np.sum 대신 'sum' 문자열을 사용해도 됩니다

  • 여러 컬럼을 index나 columns에 리스트로 전달하면 다중 레벨 피벗이 가능합니다

4. merge로 데이터 결합

어느 날 김개발 씨에게 두 개의 데이터 파일이 전달되었습니다. 하나는 고객 정보, 다른 하나는 주문 내역입니다.

"고객별 주문 현황을 분석해주세요"라는 요청을 받았는데, 두 파일을 어떻게 연결해야 할지 고민이었습니다. SQL의 JOIN처럼 Pandas에도 merge가 있다는 것을 알게 된 순간이었습니다.

merge는 두 개의 DataFrame을 공통 컬럼(키)을 기준으로 결합하는 기능입니다. SQL의 JOIN과 동일한 개념으로, inner, left, right, outer 네 가지 방식을 지원합니다.

관계형 데이터베이스의 테이블처럼 나누어진 데이터를 하나로 통합할 때 필수적인 도구입니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 고객 정보
customers = pd.DataFrame({
    'customer_id': [1, 2, 3, 4],
    'name': ['김철수', '이영희', '박민수', '최지은'],
    'city': ['서울', '부산', '서울', '대전']
})

# 주문 내역
orders = pd.DataFrame({
    'order_id': [101, 102, 103, 104, 105],
    'customer_id': [1, 2, 1, 3, 5],
    'product': ['노트북', '마우스', '키보드', '모니터', '태블릿'],
    'amount': [1200000, 25000, 80000, 350000, 500000]
})

# inner join: 양쪽에 모두 있는 데이터만
inner = pd.merge(customers, orders, on='customer_id', how='inner')
print(inner)

# left join: 왼쪽 기준, 오른쪽에 없으면 NaN
left = pd.merge(customers, orders, on='customer_id', how='left')
print(left)

# outer join: 양쪽 모두 포함, 없으면 NaN
outer = pd.merge(customers, orders, on='customer_id', how='outer')
print(outer)

김개발 씨는 데이터 분석 업무를 하면서 여러 개의 데이터 파일을 다루게 되었습니다. 고객 정보는 customers.csv에, 주문 내역은 orders.csv에 따로 저장되어 있었습니다.

"고객 이름과 함께 주문 내역을 보고 싶은데..." 박시니어 씨가 조언했습니다. "SQL에서 JOIN 써봤죠?

Pandas에서는 merge가 그 역할을 해요." merge란 정확히 무엇일까요? 쉽게 비유하자면, merge는 마치 학교에서 출석부와 성적표를 합치는 것과 같습니다.

출석부에는 학생 이름과 출석 현황이 있고, 성적표에는 학생 이름과 점수가 있습니다. 학생 이름을 기준으로 두 문서를 합치면, 한 문서에서 출석과 성적을 모두 볼 수 있게 됩니다.

merge에는 네 가지 방식이 있습니다. 이것이 핵심입니다.

inner join은 양쪽 데이터에 모두 존재하는 키만 결과에 포함됩니다. 위 예제에서 customer_id가 5인 주문은 고객 정보에 없으므로 제외됩니다.

customer_id가 4인 고객은 주문이 없으므로 제외됩니다. left join은 왼쪽 DataFrame을 기준으로 합니다.

고객 정보에 있는 모든 고객이 결과에 포함되고, 주문이 없는 고객은 주문 관련 컬럼이 NaN으로 채워집니다. right join은 left join의 반대입니다.

오른쪽 DataFrame을 기준으로 하여, 모든 주문이 결과에 포함됩니다. outer join은 양쪽 데이터를 모두 포함합니다.

어느 한쪽에만 있는 데이터도 결과에 나타나며, 매칭되지 않는 부분은 NaN으로 표시됩니다. 실무에서 가장 자주 사용하는 것은 left join입니다.

예를 들어 "모든 고객의 주문 현황을 보고 싶다"면 left join을 사용합니다. 주문이 없는 고객도 포함되어야 하니까요.

반면 "주문한 고객만 보고 싶다"면 inner join이 적합합니다. 키 컬럼의 이름이 다를 때도 있습니다.

한쪽은 customer_id, 다른 쪽은 cust_id라면 어떻게 할까요? left_onright_on 파라미터를 사용합니다.

pd.merge(df1, df2, left_on='customer_id', right_on='cust_id')처럼 작성하면 됩니다. 주의할 점이 있습니다.

merge 후에 예상보다 행이 많아지는 경우가 있습니다. 이는 키 컬럼에 중복 값이 있을 때 발생합니다.

한 고객이 여러 번 주문했다면, 그 고객 정보가 주문 수만큼 반복됩니다. 이것은 버그가 아니라 정상적인 동작입니다.

김개발 씨는 merge로 고객 정보와 주문 내역을 결합한 뒤, 고객별 총 주문 금액을 계산했습니다. "김철수 고객님이 VIP시네요!" 데이터가 하나로 합쳐지니 분석이 훨씬 수월해졌습니다.

실전 팁

💡 - indicator=True 옵션을 추가하면 각 행이 어느 DataFrame에서 왔는지 표시됩니다

  • validate='one_to_many' 옵션으로 예상치 못한 다대다 관계를 방지할 수 있습니다

5. concat으로 데이터 연결

이번에는 다른 상황이 펼쳐졌습니다. 1분기 매출 데이터, 2분기 매출 데이터, 3분기 매출 데이터...

똑같은 형식의 파일이 분기별로 나뉘어 있었습니다. "이걸 하나로 합치려면 어떻게 해야 하지?" merge는 키를 기준으로 옆으로 붙이는 것이고, concat은 위아래로 쌓는 것입니다.

concat은 여러 개의 DataFrame을 위아래(행 방향) 또는 좌우(열 방향)로 연결하는 기능입니다. merge가 관계형 결합이라면, concat은 단순 물리적 결합입니다.

같은 구조의 데이터를 하나로 모을 때 사용합니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 분기별 매출 데이터
q1 = pd.DataFrame({
    'product': ['A', 'B', 'C'],
    'sales': [100, 200, 150],
    'quarter': ['Q1', 'Q1', 'Q1']
})

q2 = pd.DataFrame({
    'product': ['A', 'B', 'D'],
    'sales': [120, 180, 90],
    'quarter': ['Q2', 'Q2', 'Q2']
})

# 위아래로 연결 (행 방향)
yearly = pd.concat([q1, q2], ignore_index=True)
print(yearly)

# 좌우로 연결 (열 방향)
side_by_side = pd.concat([q1, q2], axis=1)
print(side_by_side)

# 여러 파일 한 번에 합치기
quarters = [q1, q2]  # 실제로는 파일에서 읽어온 DataFrame 리스트
all_data = pd.concat(quarters, ignore_index=True)
print(all_data)

# keys로 원본 구분하기
labeled = pd.concat([q1, q2], keys=['1분기', '2분기'])
print(labeled)

김개발 씨는 연간 매출 분석을 해야 했습니다. 그런데 데이터가 sales_q1.csv, sales_q2.csv, sales_q3.csv, sales_q4.csv로 나뉘어 있었습니다.

파일 형식은 모두 동일했습니다. "이걸 어떻게 하나로 합치지?" 박시니어 씨가 말했습니다.

"merge는 열을 기준으로 옆으로 붙이는 거고, concat은 그냥 위아래로 쌓는 거예요. 같은 형식의 데이터를 모을 때는 concat이 딱이에요." concat이란 정확히 무엇일까요?

쉽게 비유하자면, concat은 마치 종이를 스테이플러로 찍는 것과 같습니다. 위아래로 찍으면 페이지가 늘어나고, 좌우로 찍으면 폭이 넓어집니다.

merge가 퍼즐 맞추기라면, concat은 단순히 블록을 쌓는 것입니다. 위의 코드에서 핵심을 살펴보겠습니다.

pd.concat([q1, q2])는 두 DataFrame을 위아래로 연결합니다. 기본값인 axis=0이 행 방향 연결을 의미합니다.

결과는 6개 행이 됩니다. 주의할 점은 인덱스입니다.

그냥 연결하면 각 DataFrame의 원래 인덱스가 유지되어 0, 1, 2, 0, 1, 2가 됩니다. ignore_index=True 옵션을 추가하면 인덱스가 0, 1, 2, 3, 4, 5로 새로 매겨집니다.

대부분의 경우 이 옵션을 사용하는 것이 좋습니다. axis=1을 설정하면 좌우로 연결됩니다.

열 방향 연결이라고 합니다. 같은 행에 다른 정보를 나란히 놓고 싶을 때 사용합니다.

하지만 이 경우는 merge를 사용하는 것이 더 일반적입니다. 실무에서 아주 유용한 패턴이 있습니다.

여러 CSV 파일을 한 번에 합치는 것입니다. glob 모듈로 파일 목록을 가져오고, 각 파일을 DataFrame으로 읽은 뒤, concat으로 합칩니다.

pd.concat([pd.read_csv(f) for f in file_list])처럼 한 줄로 처리할 수 있습니다. keys 파라미터도 알아두면 좋습니다.

pd.concat([q1, q2], keys=['1분기', '2분기'])처럼 작성하면, 결과에 다중 인덱스가 생기면서 각 행이 어느 원본에서 왔는지 구분할 수 있습니다. 주의할 점이 있습니다.

concat은 컬럼 이름을 기준으로 정렬합니다. 두 DataFrame의 컬럼이 다르면 어떻게 될까요?

기본적으로 모든 컬럼이 포함되고, 없는 값은 NaN으로 채워집니다. join='inner' 옵션을 주면 공통 컬럼만 남깁니다.

김개발 씨는 4개 분기 파일을 concat으로 합쳐 연간 데이터를 만들었습니다. groupby와 함께 사용하니 분기별 추이 분석도 손쉽게 할 수 있었습니다.

"데이터가 나뉘어 있어도 걱정 없네요!"

실전 팁

💡 - sort=False 옵션을 주면 컬럼 순서가 원본 그대로 유지됩니다

  • verify_integrity=True로 인덱스 중복을 검사할 수 있습니다

6. 실전 데이터 분석 예제

이제 김개발 씨는 지금까지 배운 모든 기술을 종합해볼 시간입니다. 실제 업무에서는 groupby, merge, concat, pivot_table이 따로 쓰이는 것이 아니라 함께 어우러져 사용됩니다.

온라인 쇼핑몰의 매출 데이터를 분석하면서 이 모든 것을 실전에 적용해 보겠습니다.

실전 데이터 분석에서는 여러 기법을 조합하여 사용합니다. 데이터 결합, 그룹화, 피벗 테이블 생성을 순차적으로 적용하여 의미 있는 인사이트를 도출합니다.

이 과정을 통해 "월별 카테고리별 매출 현황", "고객 등급별 구매 패턴" 같은 비즈니스 질문에 답할 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 고객 데이터
customers = pd.DataFrame({
    'customer_id': [1, 2, 3, 4, 5],
    'name': ['김철수', '이영희', '박민수', '최지은', '정하늘'],
    'grade': ['VIP', '일반', 'VIP', '일반', '일반']
})

# 주문 데이터
orders = pd.DataFrame({
    'order_id': range(1, 11),
    'customer_id': [1, 2, 1, 3, 2, 4, 1, 5, 3, 2],
    'category': ['전자', '의류', '전자', '식품', '의류', '전자', '식품', '의류', '전자', '식품'],
    'amount': [500, 100, 300, 50, 150, 200, 80, 120, 400, 60],
    'month': ['1월', '1월', '2월', '1월', '2월', '2월', '2월', '1월', '2월', '2월']
})

# Step 1: 고객 정보와 주문 데이터 결합
merged = pd.merge(orders, customers, on='customer_id')
print("=== 결합된 데이터 ===")
print(merged.head())

# Step 2: 고객 등급별 총 매출 분석
grade_sales = merged.groupby('grade')['amount'].agg(['sum', 'mean', 'count'])
print("\n=== 등급별 매출 분석 ===")
print(grade_sales)

# Step 3: 월별 카테고리별 매출 피벗 테이블
pivot = pd.pivot_table(merged, values='amount', index='category',
                       columns='month', aggfunc='sum', margins=True)
print("\n=== 월별 카테고리별 매출 ===")
print(pivot)

# Step 4: VIP 고객의 월별 구매 추이
vip_orders = merged[merged['grade'] == 'VIP']
vip_monthly = vip_orders.groupby('month')['amount'].sum()
print("\n=== VIP 월별 구매 ===")
print(vip_monthly)

김개발 씨는 드디어 첫 번째 대형 프로젝트를 맡았습니다. 온라인 쇼핑몰의 월간 매출 분석 보고서를 작성하는 일이었습니다.

고객 데이터, 주문 데이터, 상품 데이터가 각각 다른 테이블에 저장되어 있었습니다. "자, 이제 진짜 실전이다." 김개발 씨는 지금까지 배운 것들을 떠올렸습니다.

첫 번째 단계는 데이터 결합입니다. 주문 데이터에는 customer_id만 있고 고객 이름이나 등급 정보는 없습니다.

이 정보는 고객 테이블에 있습니다. merge로 두 데이터를 결합하면 주문 내역과 고객 정보를 함께 볼 수 있게 됩니다.

SQL의 JOIN과 같은 개념입니다. 두 번째 단계는 그룹별 집계입니다.

"VIP 고객과 일반 고객의 구매 패턴이 어떻게 다른가요?" 이런 질문에 답하려면 groupby가 필요합니다. 고객 등급을 기준으로 그룹화한 뒤, 총 구매액, 평균 구매액, 주문 횟수를 계산합니다.

agg 함수로 여러 집계를 한 번에 수행할 수 있습니다. 세 번째 단계는 피벗 테이블 생성입니다.

"월별로, 카테고리별로 매출이 어떻게 되나요?" 이 질문은 pivot_table이 딱입니다. 행에는 카테고리, 열에는 월을 배치하면 한눈에 비교할 수 있는 표가 완성됩니다.

margins=True를 추가하면 합계까지 자동으로 계산됩니다. 네 번째 단계는 조건부 필터링과 분석입니다.

"VIP 고객만 따로 분석하고 싶어요." 이럴 때는 Boolean 인덱싱으로 VIP 고객만 필터링한 뒤, 다시 groupby를 적용합니다. Pandas의 강력함은 이런 작업들을 자유롭게 조합할 수 있다는 것입니다.

실무에서 이런 분석은 일상입니다. 마케팅 팀은 "어떤 고객 세그먼트가 가장 수익성이 높은지" 알고 싶어합니다.

영업 팀은 "어떤 카테고리가 성장하고 있는지" 궁금합니다. 경영진은 "월별 추이가 어떻게 되는지" 보고 싶어합니다.

Pandas를 잘 활용하면 이 모든 질문에 빠르게 답할 수 있습니다. 주의할 점도 있습니다.

데이터 분석에서 가장 중요한 것은 "질문을 명확히 하는 것"입니다. "매출 분석해줘"라는 막연한 요청보다 "VIP 고객의 월별 카테고리별 구매 패턴"처럼 구체적인 질문이 있어야 적절한 분석 방법을 선택할 수 있습니다.

김개발 씨는 보고서를 완성했습니다. pivot_table로 만든 깔끔한 표와 groupby로 계산한 핵심 지표들이 담긴 보고서였습니다.

상사가 말했습니다. "와, 이렇게 빨리 분석을 끝냈어?

Python 진짜 강력하구나." 김개발 씨는 뿌듯하게 대답했습니다. "Pandas의 힘이에요!"

실전 팁

💡 - 분석 전에 항상 데이터의 shape와 dtypes를 확인하세요

  • 결과를 to_excel이나 to_csv로 내보내 보고서로 활용할 수 있습니다
  • 복잡한 분석은 단계별로 나누어 중간 결과를 확인하며 진행하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Pandas#groupby#pivot_table#merge#concat#Python,Pandas

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.