한컴AI 2기

[스나이퍼팩토리] 한컴AI 2기 - Python 데이터 집계와 그룹 연산

싱커 2025. 9. 19. 17:33

Pandas의 groupby 기능을 학습하며 데이터 집계와 그룹 연산의 원리를 정리해 보았다. 데이터를 특정 기준으로 묶어 통계를 내는 작업은 데이터 분석의 핵심인데, groupby는 이 과정을 매우 효율적으로 만들어주는 강력한 도구이다.


GroupBy의 핵심 원리: 분할-적용-결합 (Split-Apply-Combine)

groupby의 모든 연산은 '분할-적용-결합'이라는 세 단계의 흐름을 따른다.

 

  • 1. 분할 (Split): 데이터를 특정 기준(예: 특정 열의 값)에 따라 여러 그룹으로 나눈다.
  • 2. 적용 (Apply): 각 그룹에 특정 함수(예: 평균, 합계)를 적용하여 연산을 수행한다.
  • 3. 결합 (Combine): 각 그룹별 연산 결과를 다시 하나의 데이터 구조로 합친다.

groupby의 주요 활용법과 코드 예제

groupby로 생성된 그룹 객체는 그 자체로 결과물이 아니며, 뒤에 어떤 함수를 적용하느냐에 따라 다양한 분석이 가능하다.

먼저, 실습을 위한 간단한 예제 데이터 프레임을 만든다.

import pandas as pd

df = pd.DataFrame({
    'Team': ['Sales A', 'Sales B', 'Sales A', 'Sales B', 'Sales A'],
    'Product': ['A', 'B', 'B', 'A', 'A'],
    'Sales': [200, 150, 300, 250, 180]
})

 

1. 집계 (Aggregation)

그룹별로 데이터를 요약하여 통계치를 내는 가장 기본적인 기능이다. 각 팀의 총매출을 구하는 예제는 다음과 같다.

# 'Team'을 기준으로 그룹화하고 각 팀의 'Sales' 합계 구하기
team_sales = df.groupby('Team')['Sales'].sum()
print(team_sales)
더보기

[출력 결과]

Team
Sales A    680
Sales B    400
Name: Sales, dtype: int64

.agg() 메서드를 사용하면 여러 통계 함수를 한 번에 적용할 수도 있다.

# 팀별로 Sales의 합계와 평균을 동시에 계산
team_stats = df.groupby('Team')['Sales'].agg(['sum', 'mean'])
print(team_stats)

3건과 2건에 대한 총합과 평균


2. 변환 (Transformation)

그룹별 통계치를 계산하여, 원본 데이터의 각 행에 다시 반영하는 기능이다. 예를 들어, 각 판매 실적이 해당 팀의 평균 대비 얼마나 차이가 나는지 계산할 수 있다.

# 각 Sales 데이터가 팀 평균(Sales A: 226.6, Sales B: 200) 대비 얼마나 차이 나는지 계산
df['Deviance'] = df['Sales'] - df.groupby('Team')['Sales'].transform('mean')
print(df)

.transform()은 원본 데이터와 동일한 모양(shape)을 유지하면서 그룹 연산 결과를 반영해주기 때문에, 그룹 내 상대적 수치를 분석할 때 매우 유용하다.

Sales에서 평균을 빼 계산한 평균 대비 실적


3. 필터링 (Filtering)

그룹 단위로 특정 조건을 만족하는 데이터만 남기는 기능이다. 예를 들어, 판매 건수가 3건 이상인 팀의 데이터만 조회하고 싶을 때 사용할 수 있다.

# 판매 건수가 3건 이상인 팀('Sales A' 팀)의 데이터만 필터링
filtered_df = df.groupby('Team').filter(lambda x: len(x) >= 3)
print(filtered_df)

 

판매 건수가 3건 이상인 팀만의 데이터


groupby의 심화 활용: 특정 상황을 해결하는 응용 예제

groupby는 기본적인 집계, 변환, 필터링을 넘어 더 복잡하고 구체적인 데이터 처리 요구사항을 해결하는 데에도 탁월하다.

그룹별 무작위 샘플링 (Group-wise Random Sampling)

전체 데이터에서 무작위 N개를 뽑는 것이 아니라, "각 그룹별로 N개씩" 뽑고 싶을 때가 있다. 예를 들어, 각 팀에서 무작위로 2명씩의 선수를 뽑아 대표팀을 구성하는 상황을 가정할 수 있다. 이때 groupby와 .apply()를 함께 사용하면 간단하게 해결된다.

import pandas as pd
import numpy as np

# 데이터 생성: 각 팀(A,B)에 10명의 선수가 있다고 가정
players = pd.DataFrame({
    'team': ['team_A'] * 10 + ['team_B'] * 10,
    'skill': np.arange(20) + np.random.randn(20)
})

# 각 그룹에서 2개의 샘플을 뽑는 함수
def random_sample(group):
    return group.sample(2)

# 팀별로 그룹화한 뒤, 각 그룹에 random_sample 함수를 적용
sampled_players = players.groupby('team').apply(random_sample)
print(sampled_players)

각 팀별로 2명씩 선발하는 예제

groupby('team')으로 team_A와 team_B 그룹으로 나눈 뒤, 각 그룹 데이터에 .sample(2)를 적용해 2개씩의 행을 추출하고, 마지막에 그 결과를 하나로 합쳐주는 원리다. 이처럼 복잡해 보이는 요구사항도 apply와 조합하여 해결할 수 있다.


그룹별 상관관계 및 회귀 분석 (Group-wise Correlation & Regression)

groupby의 가장 강력한 점 중 하나는 각 그룹을 하나의 미니 데이터프레임으로 보고, 그룹별로 별도의 통계 분석 모델을 적용할 수 있다는 점이다. 예를 들어, 여러 부서의 연도별 투자액과 성과 데이터가 있을 때, 'A부서의 투자-성과 관계'와 'B부서의 투자-성과 관계'가 어떻게 다른지 각각 분석하고 싶을 수 있다.

 

apply를 사용하면 각 그룹별로 두 변수 간의 상관계수를 쉽게 계산할 수 있다.

# 데이터 생성: 두 부서(A,B)의 연도별 투자액과 성과
df_perf = pd.DataFrame({
    'dept': ['A', 'A', 'A', 'B', 'B', 'B'],
    'year': [2022, 2023, 2024] * 2,
    'investment': [10, 15, 12, 20, 22, 25],
    'performance': [100, 160, 140, 210, 240, 280]
})

# 각 그룹(부서)별로 투자액과 성과의 상관계수를 계산하는 함수
def calculate_corr(group):
    return group['investment'].corr(group['performance'])

# 부서별로 그룹화한 뒤, 상관계수 계산 함수를 적용
corr_by_dept = df_perf.groupby('dept').apply(calculate_corr)
print(corr_by_dept)

부서별 투자액-성과 상관계수

이와 같은 원리를 확장하면, statsmodels와 같은 통계 라이브러리를 이용해 각 그룹별로 가중 평균을 구하거나 선형 회귀 분석을 수행하는 등 훨씬 정교한 분석도 가능하다. 단순히 전체 데이터를 한 번에 분석하는 것을 넘어, 데이터의 부분집합별 특성을 깊이 있게 파고들 수 있게 해주는 핵심적인 기능이다.


 

본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 2기 (B-log) 리뷰로 작성 되었습니다.