[Python pandas] GroupBy 집계 메소드와 함수 (Group by aggregation methods and functions)
Python 분석과 프로그래밍/Python 데이터 전처리 2018. 9. 2. 14:56지난번 포스팅에서는 row나 column 기준으로 GroupBy의 Group을 지정할 수 있는 4가지 방법으로 Dicts, Series, Functions, Index Levels 를 소개하였습니다.
이번 포스팅에서는 Python pandas에서 연속형 변수의 기술통계량 집계를 할 수 있는 GroupBy 집계 메소드와 함수 (GroupBy aggregation methods and functions)에 대해서 소개하겠습니다.
(1) GroupBy 메소드를 이용한 집계 (GroupBy aggregation using methods): (ex) grouped.sum()
(2) 함수를 이용한 GroupBy 집계 (GroupBy aggregation using functions): grouped.agg(function)
[ Python pandas Group By 집계 메소드와 함수 ]
pandas에서 GroupBy 집계를 할 때 (1) pandas에 내장되어 있는 기술 통계량 메소드를 사용하는 방법과, (2) (사용자 정의) 함수를 grouped.agg(function) 형태로 사용하는 방법이 있습니다. GroupBy 메소드는 성능이 최적화되어 있어 성능면에서 함수를 사용하는 것보다 빠르므로, 메소드가 지원하는 집단별 기술통계량 분석 시에는 메소드를 이용하는게 좋겠습니다.
NA 값은 모두 무시되고 non-NA 값들에 대해서만 GroupBy method가 적용됩니다.
기술 통계량들이 어려운게 하나도 없으므로 이번 포스팅은 좀 쉬어가는 코너로 가볍게 소개합니다. 설명에 사용한 간단한 예제 데이터프레임과 'group'변수를 대상으로 GroupBy object를 만들어보겠습니다.
# Importing common libraries import numpy as np import pandas as pd # sample DataFrame df = pd.DataFrame({'group': ['a', 'a', 'a', 'b', 'b', 'b'], 'value_1': np.arange(6), 'value_2': np.random.randn(6)}) df
|
# Making GroupBy object grouped = df.groupby('group') grouped <pandas.core.groupby.DataFrameGroupBy object at 0x11136f550> |
(1) GroupBy 메소드를 이용한 집계 (GroupBy aggregation using methods) |
(1-1) count(), sum()
count(): 그룹 내 non-NA 개수 |
sum(): 그룹 내 non-NA 합 |
||||||||||||||||||||||||
grouped.count()
|
grouped.sum() # DataFrame
|
*cf. grouped.size() 도 grouped.count()와 동일한 결과를 반환함
위의 예에서 보면 'value_1', 'value_2' 변수가 숫자형이므로 pandas가 알아서 잘 찾아서 count()와 sum()을 해주었으며, 반환된 결과는 데이터프레임입니다.
만약 특정 변수에 대해서만 그룹별 요약/집계를 하고 싶다면 해당 변수를 indexing해주면 되며, 한개 변수에 대해서만 GroupBy 집계를 하면 반환되는 결과는 Series가 됩니다. 한개 변수에 대해 GroupBy 집계해서 나온 Series를 데이터프레임으로 만들고 싶으면 pd.DataFrame() 를 사용해서 집계 결과를 데이터프레임으로 변환해주면 됩니다.
grouped.sum()['value_2'] # Series group a -0.012473
b 0.072545 Name: value_2, dtype: float64 pd.DataFrame(grouped.sum()['value_2']) # DataFrame
|
(1-2) 최소값, 최대값: min(), max()
min(): 그룹 내 non-NA 값 중 최소값 |
max(): 그룹 내 non-NA 값 중 최대값 |
||||||||||||||||||||||||
grouped.min()
|
grouped.max()
|
(1-3) 중심 경향: mean(), median()
mean(): 그룹 내 non-NA 값들의 평균값 |
median(): 그룹 내 non-NA 값들의 중앙값 |
||||||||||||||||||||||||
grouped.mean()
|
grouped.median()
|
※ 그룹별로 집계된 결과값의 변수에 접두사(Prefix)를 붙이려면 add_prefix() 를 사용합니다.
예) df.groupby('key_col').mean().add_prefix('mean_')
(1-4) 퍼짐 정도: std(), var(), quantile()
표준편차, 분산 계산에 n-1 자유도를 사용했으므로 샘플표준편차, 샘플분산으로 봐야겠네요.
quantile() 의 괄호 안에 0~1 사이의 값을 넣어주면 분위수를 계산해주며, 최소값과 최대값을 등분하여 그 사이를 interpolation 하여 분위수를 계산하는 방식입니다.
std(): 그룹 내 표준편차 | var(): 그룹 내 분산 |
quantile(): 그룹 내 분위수 |
||||||||||||||||||||||||||||||||||||
grouped.std()
| grouped.var()
|
# interpolation grouped.quantile(0.1)
|
(1-5) first(), last()
first(): 그룹 내 non-NA 값 중 첫번째 값 |
last(): 그룹 내 non-NA 값 중 마지막 값 |
||||||||||||||||||||||||
grouped.first()
|
grouped.last()
|
(1-6) describe()
describe(): 그룹 별 기술통계량 - 옆으로 길게 |
describe().T: 그룹 별 기술통계량 - 세로로 길게 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grouped.describe()['value_1']
|
grouped.describe()['value_1'].T
|
(2) 함수를 이용한 GroupBy 집계: grouped.agg(function) |
필요로 하는 집계함수가 pandas GroupBy methods에 없는 경우 사용자 정의 함수를 정의해서 집계에 사용할 수 있습니다. IQR(Inter-Quartile Range, Q3 - Q1) 를 사용자 정의 함수로 정의하고, 이를 grouped.aggregate() 혹은 grouped.agg() 의 괄호 안에 넣어서 그룹 별로 IQR를 계산해보겠습니다.
def iqr_func(x): q3, q1 = np.percentile(x, [75, 25]) iqr = q3 - q1 return iqr |
grouped.aggregate(function) |
grouped.agg(function) |
||||||||||||||||||||||||
grouped.aggregate(iqr_func)
|
grouped.agg(iqr_func)
|
위에서 사용자 정의함수로 정의해서 그룹별로 집계한 결과가 맞게 나온건지 quantile() 메소드로 그룹별 Q3 와 Q1을 계산해서 확인해보니, 위의 grouped.agg(iqr_func)가 잘 계산한거 맞네요.
grouped.quantile([0.75, 0.25])
|
다음번 포스팅에서는 grouped.agg() 의 좀더 다양한 사용법을 소개하겠습니다.
많은 도움이 되었기를 바랍니다.