[Python pandas] groupby() 로 그룹별 집계하기 (data aggregation by groups)
Python 분석과 프로그래밍/Python 데이터 전처리 2018. 8. 26. 18:20이번 포스팅에서는 Python pandas의 groupby() 연산자를 사용하여 집단, 그룹별로 데이터를 집계, 요약하는 방법을 소개하겠습니다.
전체 데이터를 그룹 별로 나누고 (split), 각 그룹별로 집계함수를 적용(apply) 한후, 그룹별 집계 결과를 하나로 합치는(combine) 단계를 거치게 됩니다. (Split => Apply function => Combine)
[ GroupBy aggregation mechanics ]
groupby() 는 다양한 변수를 가진 데이터셋을 분석하는데 있어 그룹별로 데이터를 집계하는 분석은 일상적으로 이루어지는 만큼 사용빈도가 매우 높고 알아두면 유용합니다.
실습에 사용할 예제는 바다 해산물인 전복(abalone)에 대한 공개 데이터셋을 사용하겠습니다.
[ UCI Machine Learning Repository ]
|
먼저, 바로 위에 링크해놓은 abalone.txt를 다운받은 후에, abalone.txt 데이터셋을 pandas의 read_csv() 로 불러와서 DataFrame을 만들어보겠습니다.
# Importing common libraries import pandas as pd from pandas import DataFrame from pandas import Series import numpy as np
# Reading abalone data set abalone = pd.read_csv("/Users/ihongdon/Documents/Python/abalone.txt", sep=",", names = ['sex', 'length', 'diameter', 'height', 'whole_weight', 'shucked_weight', 'viscera_weight', 'shell_weight', 'rings'], header = None) |
abalone 라는 이름의 pandas DataFrame을 만들었으니, 데이터가 어떻게 생겼는지 탐색해보겠습니다. 다행히 결측치는 없으며, 4,177개의 관측치를 가지고 있네요. 전복의 성별(sex) 변수가 범주형 변수입니다.
# View of top 5 observations abalone.head() sex length diameter height whole_weight shucked_weight viscera_weight shell_weight rings 0 M 0.455 0.365 0.095 0.5140 0.2245 0.1010 0.150 15 1 M 0.350 0.265 0.090 0.2255 0.0995 0.0485 0.070 7 2 F 0.530 0.420 0.135 0.6770 0.2565 0.1415 0.210 9 3 M 0.440 0.365 0.125 0.5160 0.2155 0.1140 0.155 10 4 I 0.330 0.255 0.080 0.2050 0.0895 0.0395 0.055 7 # Check the missing value np.sum(pd.isnull(abalone)) sex 0 length 0 diameter 0 height 0 whole_weight 0 shucked_weight 0 viscera_weight 0 shell_weight 0 rings 0 dtype: int64
# Descriptive statics abalone.describe()
|
자, 데이터 준비가 되었으니 이제부터 '전복 성별(sex)' 그룹('F', 'M', 'I')별로 전복의 전체 무게('whole_weight') 변수에 대해서 GroupBy 집계를 해보겠습니다.
집단별 크기는 grouped.size(), 집단별 합계는 grouped.sum(), 집단별 평균은 grouped.mean() 을 사용합니다.
grouped = abalone['whole_weight'].groupby(abalone['sex']) grouped <pandas.core.groupby.SeriesGroupBy object at 0x112668c10> grouped.size() sex F 1307 I 1342 M 1528 Name: whole_weight, dtype: int64 grouped.sum() sex F 1367.8175 I 578.8885 M 1514.9500 Name: whole_weight, dtype: float64 grouped.mean() sex F 1.046532 I 0.431363 M 0.991459 Name: whole_weight, dtype: float64 |
위의 예에서는 'whole_weight' 라는 하나의 연속형 변수에 대해서만 '성별(sex)' 집계를 하였습니다만, 집계를 하는 key를 제외한 데이터프레임 안의 전체 연속형 변수에 대해서 한꺼번에 집계를 할 수도 있습니다.
abalone.groupby(abalone['sex']).mean()
|
DataFrame.groupby('key_var').func() 형식으로도 사용가능하며, 위의 abalone.groupby(abalone['sex']).mean()은 아래처럼 abalone.groupby('sex').mean() 처럼 써도 똑같은 결과를 얻을 수 있습니다.
abalone.groupby('sex').mean()
|
이제부터는 '성별(sex)' 이외에 '길이(length)'를 가지고 범주형 변수를 하나 더 만들어서, 2개의 범주형 변수 key 값을 가지고 그룹별 집계를 해보겠습니다.
np.where() 함수를 사용하여 length 의 중앙값보다 크면 'length_long'으로, 중앙값보다 작으면 'length_short'의 이름으로하는 계급으로하는 새로운 범주형 변수를 만들어보겠습니다.
abalone['length_cat'] = np.where(abalone.length > np.median(abalone.length), 'length_long', # True 'length_short') # False abalone[['length', 'length_cat']][:10] length length_cat 0 0.455 length_short 1 0.350 length_short 2 0.530 length_short 3 0.440 length_short 4 0.330 length_short 5 0.425 length_short 6 0.530 length_short 7 0.545 length_short 8 0.475 length_short 9 0.550 length_long |
그럼, 이제 성별 그룹(sex)과 길이 범주(length_cat) 그룹별로 GroupBy 를 사용하여 평균을 구해보겠습니다.
mean_by_sex_length = abalone['whole_weight'].groupby([abalone['sex'], abalone['length_cat']]).mean()
mean_by_sex_length sex length_cat F length_long 1.261330 length_short 0.589702 I length_long 0.923215 length_short 0.351234 M length_long 1.255182 length_short 0.538157 Name: whole_weight, dtype: float64 |
위의 집계 결과가 SQL로 집계했을 때의 형태로 결과가 제시가 되었는데요, unstack() 함수를 사용하면 집계 결과를 가로, 세로 축으로 좀더 보기에 좋게 표현을 할 수 있습니다.
mean_by_sex_length.unstack()
|
abalone['whole_weight'].groupby([abalone['sex'], abalone['length_cat']]).mean() 를 좀더 간결하게 아래처럼 쓸 수도 있습니다. 대상 데이터프레임을 제일 앞에 써주고, groupby()에 집계의 기준이 되는 key 변수들을 써주고, 제일 뒤에 집계하려는 연속형 변수이름을 써주었습니다.
abalone.groupby(['sex', 'length_cat'])['whole_weight'].mean()
sex length_cat
F length_long 1.261330
length_short 0.589702
I length_long 0.923215
length_short 0.351234
M length_long 1.255182
length_short 0.538157
Name: whole_weight, dtype: float64 |
많은 도움이 되었기를 바랍니다.
'Python 분석과 프로그래밍 > Python 데이터 전처리' 카테고리의 다른 글
[Python pandas] 범주형 변수의 항목을 기준 정보를 사용하여 매핑해 변환하기: dict.get() (0) | 2018.08.31 |
---|---|
[Python pandas] GroupBy로 그룹별로 반복 작업하기 (Iteration over groups) (0) | 2018.08.26 |
[Python pandas] 다수개의 범주형자료로 가변수 만들기 (dummy variable) (2) | 2018.08.21 |
[Python NumPy] 선형대수 함수 (Linear Algebra) (0) | 2018.08.15 |
[Python] numpy 배열을 여러개의 하위 배열로 분할하기 (split an array into sub-arrays) (0) | 2018.05.22 |