안녕하세요. PSYda입니다.
이번 포스팅에서는 DataFrame의 집계(그루핑) 함수에 대해 알아보겠습니다.
집계함수란 데이터를 몇몇의 집단으로 나누어 집단간 평균, 합계 등의 연산을 수행하는 함수를 얘기합니다.
예를 들어 고등학교 학생 전체 성적 데이터가 있을 경우 반별로 영어성적에 대한 평균을 내거나, 과목별로 학생들의 성적에 대한 평균을 내는 것과 같습니다.
예와 같이 집계함수를 적용하기 위해서는 3가지 값이 필요하며, 그 값은 그룹할 기준(반별 또는 과목별), 연산을 수행할 값(영어성적), 연산 함수(평균) 입니다.
이번 포스팅에서 소개할 내용을 요약하면 아래와 같습니다.
- groupby 함수을 사용한 DataFrame 집계
- pivot_table 함수를 사용한 DataFrame 집계
실습에 사용한 데이터는 fifa19에 등장하는 축구선수들의 능력치 데이터입니다.
데이터는 아래에서 다운로드 받을 수 있습니다.
9. DataFrame의 집계함수
DataFrame을 집계할 수 있는 두 개의 함수
- groupby
- pivot_table
9.1 groupby 함수
groupby 함수를 사용한 집계 연산은 두 단계로 이루어짐
- DataFrame을 그룹별로 나누는 단계
- 나누어진 그룹에서 집계 함수(sum, mean, max 등)를 수행하는 단계
Library import
import pandas as pd
from pandas import Series , DataFrame
import numpy as np
player = pd.read_csv('data/Ch10_1_fifaStats2.csv')
player.head()
Name | Age | Nationality | Club | Preferred Foot | Crossing | Dribbling | LongPassing | ShotPower | |
---|---|---|---|---|---|---|---|---|---|
0 | L. Messi | 31 | Argentina | FC Barcelona | Left | 84.0 | 97.0 | 87.0 | 85.0 |
1 | Cristiano Ronaldo | 33 | Portugal | Juventus | Right | 84.0 | 88.0 | 77.0 | 95.0 |
2 | Neymar Jr | 26 | Brazil | Paris Saint-Germain | Right | 79.0 | 96.0 | 78.0 | 80.0 |
3 | De Gea | 27 | Spain | Manchester United | Right | 17.0 | 18.0 | 51.0 | 31.0 |
4 | K. De Bruyne | 27 | Belgium | Manchester City | Right | 93.0 | 86.0 | 91.0 | 91.0 |
9.1.1 그룹핑 한줄로 수행하기
팀별로 선수의 능력치에 대한 평균값 확인(최상위 5개 팀 조회)
spByTeam = player.groupby('Club').mean()
spByTeam.sort_values(by = 'LongPassing', ascending = False).head()
Age | Crossing | Dribbling | LongPassing | ShotPower | |
---|---|---|---|---|---|
Club | |||||
Chelsea | 25.212121 | 59.484848 | 65.666667 | 65.787879 | 64.060606 |
FC Barcelona | 23.848485 | 59.818182 | 66.121212 | 65.727273 | 64.303030 |
Manchester United | 24.757576 | 62.242424 | 66.878788 | 65.727273 | 66.151515 |
Manchester City | 23.909091 | 59.696970 | 66.151515 | 65.727273 | 65.606061 |
Paris Saint-Germain | 24.566667 | 63.133333 | 68.833333 | 65.500000 | 64.500000 |
특정 하나의 컬럼만 조회하기(Series로 결과 출력됨)
팀별로 Shotpower의 평균을 계산하여 평균값이 제일 높은 5개 팀 조회
spByTeam2 = player.groupby('Club')['ShotPower'].mean()
spByTeam2.sort_values(ascending = False).head()
Club
Juventus 68.000000
Ajax 67.400000
Olympiacos CFP 67.000000
SL Benfica 66.714286
Lazio 66.687500
Name: ShotPower, dtype: float64
특정 두 개 이상의 컬럼 조회(DataFrame으로 결과 출력됨)
팀별로 롱패스와 드리블 능력치 평균값 계산하여 최상위 5개 팀 조회
spByTeam3 = player.groupby('Club')[['LongPassing', 'Dribbling']].mean()
spByTeam3.sort_values(by = 'LongPassing', ascending = False).head()
LongPassing | Dribbling | |
---|---|---|
Club | ||
Chelsea | 65.787879 | 65.666667 |
FC Barcelona | 65.727273 | 66.121212 |
Manchester United | 65.727273 | 66.878788 |
Manchester City | 65.727273 | 66.151515 |
Paris Saint-Germain | 65.500000 | 68.833333 |
두 개 이상의 변수로 그룹핑(Multi Index로 결과 조회됨)
팀 + 나라로 그룹핑하여 롱패스와 드리블 능력치 평균값 최상위 5개 팀+나라 조회
spByTeam4 = player.groupby(['Nationality','Club'])[['LongPassing', 'Dribbling']].mean()
spByTeam4.sort_values(by= 'LongPassing', ascending = False).head()
LongPassing | Dribbling | ||
---|---|---|---|
Nationality | Club | ||
Germany | Real Madrid | 93.0 | 81.0 |
Croatia | FC Barcelona | 90.0 | 84.0 |
Denmark | Tottenham Hotspur | 88.0 | 84.0 |
Croatia | Real Madrid | 88.0 | 90.0 |
Argentina | FC Barcelona | 87.0 | 97.0 |
9.1.2 groupby 원리 파헤치기
9.1.2.1 groupby 함수를 이용하면 Groupby 객체가 생성됨
playerGroup = player.groupby('Club')
playerGroup
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002211EE1F940>
groupby 객체에서 groups 함수를 이용해 그룹별로 나누어진 값을 dict형태(key와 values)로 확인 가능
playerGroup.groups
{' SSV Jahn Regensburg': Int64Index([ 4587, 4840, 5260, 5335, 6184, 6783, 6917, 6954, 7184,
7195, 7633, 7657, 7867, 8337, 8933, 9024, 9212, 10285,
10312, 10686, 11059, 11244, 11861, 12363, 12671, 14161, 14319,
16105, 17786],
dtype='int64'),
'1. FC Heidenheim 1846': Int64Index([ 2053, 4348, 4812, 5093, 5722, 6135, 6208, 6294, 6333,
6545, 6678, 7595, 7723, 8543, 8567, 9040, 9380, 9535,
9890, 12004, 12350, 12356, 12654, 14737, 15318, 15842, 16503,
17538],
dtype='int64'),
'1. FC Kaiserslautern': Int64Index([ 5084, 5445, 6372, 7728, 8550, 9335, 9487, 9554, 9563,
9812, 9886, 10211, 10469, 10554, 11029, 11091, 12485, 14037,
14758, 15230, 15285, 15392, 15951, 16788, 17268, 17524],
dtype='int64'),
......
9.1.2.2 groupby 객체를 이용해 집계함수 사용
- 하나의 집계 함수 적용 : groupby객체.집계함수명()
- 여러개의 집계 함수 적용 : groupby객체.agg([집계함수명1,집계함수명2]) 사용(Multi Column 형태로 출력됨)
groupby 객체의 mean 함수 호출
playerGroup.mean().head()
Age | Crossing | Dribbling | LongPassing | ShotPower | |
---|---|---|---|---|---|
Club | |||||
SSV Jahn Regensburg | 25.655172 | 47.172414 | 52.655172 | 45.689655 | 54.137931 |
1. FC Heidenheim 1846 | 24.000000 | 49.464286 | 54.214286 | 48.964286 | 57.071429 |
1. FC Kaiserslautern | 23.846154 | 48.076923 | 49.769231 | 48.653846 | 56.692308 |
1. FC Köln | 24.321429 | 52.357143 | 57.964286 | 54.714286 | 58.178571 |
1. FC Magdeburg | 24.692308 | 46.500000 | 51.346154 | 47.153846 | 52.269231 |
playerGroup.agg(['mean', 'sum']).head()
Age | Crossing | Dribbling | LongPassing | ShotPower | ||||||
---|---|---|---|---|---|---|---|---|---|---|
mean | sum | mean | sum | mean | sum | mean | sum | mean | sum | |
Club | ||||||||||
SSV Jahn Regensburg | 25.655172 | 744 | 47.172414 | 1368.0 | 52.655172 | 1527.0 | 45.689655 | 1325.0 | 54.137931 | 1570.0 |
1. FC Heidenheim 1846 | 24.000000 | 672 | 49.464286 | 1385.0 | 54.214286 | 1518.0 | 48.964286 | 1371.0 | 57.071429 | 1598.0 |
1. FC Kaiserslautern | 23.846154 | 620 | 48.076923 | 1250.0 | 49.769231 | 1294.0 | 48.653846 | 1265.0 | 56.692308 | 1474.0 |
1. FC Köln | 24.321429 | 681 | 52.357143 | 1466.0 | 57.964286 | 1623.0 | 54.714286 | 1532.0 | 58.178571 | 1629.0 |
1. FC Magdeburg | 24.692308 | 642 | 46.500000 | 1209.0 | 51.346154 | 1335.0 | 47.153846 | 1226.0 | 52.269231 | 1359.0 |
9.2 pivot_table 함수
<span class = "hlblock>player.pivot_table(index, columns, values, aggfunc)
- index : 출력에 사용할 index(그루핑 대상 컬럼)
- columns : 출력에 사용할 columns
- values : 집계함수를 적용할 컬럼명
- aggfunc : 사용할 집계 함수, 여러 개 사용할 경우 [] 안에 집계함수 리스트 작성
EX) 팀별로 드리블 능력치의 평균을 구해 상위 5개팀 출력
player.pivot_table(index = 'Club', values = 'Dribbling', aggfunc = 'mean').sort_values(by = 'Dribbling', ascending = False).head()
Dribbling | |
---|---|
Club | |
Juventus | 69.520000 |
Paris Saint-Germain | 68.833333 |
Napoli | 68.640000 |
Liverpool | 68.212121 |
Borussia Dortmund | 68.151515 |
EX2) 나라 + 팀 별로 롱패스와 슟파워의 평균과 최대값을 계산
player.pivot_table(index = ('Nationality','Club'), values = ('LongPassing','ShotPower'), aggfunc = ('mean','max')).head()
LongPassing | ShotPower | ||||
---|---|---|---|---|---|
max | mean | max | mean | ||
Nationality | Club | ||||
Afghanistan | Notts County | 60.0 | 60.0 | 60.0 | 60.0 |
Philadelphia Union | 59.0 | 59.0 | 61.0 | 61.0 | |
SV Meppen | 42.0 | 42.0 | 39.0 | 39.0 | |
Walsall | 55.0 | 55.0 | 55.0 | 55.0 | |
Albania | AC Ajaccio | 61.0 | 61.0 | 69.0 | 69.0 |
위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.
감사합니다.
'데이터 분석 > Pandas' 카테고리의 다른 글
[Pandas 기초]9.Series와 DataFrame에 함수 적용하기 (0) | 2019.08.29 |
---|---|
[Pandas 기초]8.Pandas DataFrame의 sort, rank함수 (0) | 2019.08.28 |
[Pandas 기초]7.Pandas DataFrame 통계 (0) | 2019.08.27 |
[Pandas 기초]6.Pandas DataFrame 산술 연산 (2) | 2019.08.22 |
[Pandas 기초]5.Pandas 데이터 파일 입출력 (3) | 2019.08.20 |