반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 DataFrame의 집계(그루핑) 함수에 대해 알아보겠습니다.

집계함수란 데이터를 몇몇의 집단으로 나누어 집단간 평균, 합계 등의 연산을 수행하는 함수를 얘기합니다.
예를 들어 고등학교 학생 전체 성적 데이터가 있을 경우 반별영어성적에 대한 평균을 내거나, 과목별로 학생들의 성적에 대한 평균을 내는 것과 같습니다.
예와 같이 집계함수를 적용하기 위해서는 3가지 값이 필요하며, 그 값은 그룹할 기준(반별 또는 과목별), 연산을 수행할 값(영어성적), 연산 함수(평균) 입니다.

이번 포스팅에서 소개할 내용을 요약하면 아래와 같습니다.

  • groupby 함수을 사용한 DataFrame 집계
  • pivot_table 함수를 사용한 DataFrame 집계

실습에 사용한 데이터는 fifa19에 등장하는 축구선수들의 능력치 데이터입니다.
데이터는 아래에서 다운로드 받을 수 있습니다.

Ch10_1_fifaStats2.csv
다운로드

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에서도 확인 할 수 있습니다.

감사합니다.

반응형

+ Recent posts