groupby함수는 쉽게 말하면 그룹별 집계로, 엑셀의 피벗테이블과 비슷한 기능이다.
다음의 3단계를 거친다.
- 분할(split): 같은 key값을 가진 데이터들끼리 묶는다. 이때 key값 = 기준 열에서 항목 값
- 적용(apply): 분할로 나누어진 각 데이터 블록마다 다양한 연산 적용하며, 연산 함수를 직접 만들수 있다.
- 결합(combine): 적용된 각 블록들을 합침 --> 어떤 key값을 기준으로 통합된 통계 데이터 추출
.groupby("묶을 기준 열1","묶을 기준 열2",...)["연산하는 열"].연산함수(level= )
이때 레벨별로 별도의 연산 함수 지정가능하다
index는 반환할 수 없다.
결과는 Series객체로 반환되며, DataFrame객체로 변형하려면 reset_index함수를 적용해야한다.
import pandas as pd
ipl_data = {'Team': ['Riders', 'Riders','Devils','Devils','Kings','Kings','Kings','Kings','Riders','Royals','Royals','Riders'],
'Rank': [1,2,2,3,3,4,1,1,2,4,1,2],
'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
'Points': [876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)
df
>
이 데이터에서 'Team'별로 'Point'의 '합계'를 계산한 표를 보려면 다음과 같이 작성하면 된다.
single_groupby = df.groupby('Team')['Point'].sum()
single_groupby
>
type(single_groupby)
>pandas.core.series.Series
이렇게 groupby를 적용한 데이터는 Series객체가 된다.
그리고 묶을 기준열을 2개 이상 지정하면 자동으로 그 열들은 multi index가 된다.
위에서 사용한 single_groupby의 index를 살펴보면
single_groupby.index
>
그리고 기준 열을 2개 지정하면
# multi index
multi_groupby = df.groupby(["Team","Year"])["Points"].sum()
multi_groupby.index
>
위와 같이 multiIndex가 된다.
이렇게 multiIndex를 가지는 데이터에서 아래와 같은 함수들을 적용하여 데이터 형태에 변화를 줄수 있다.
.unstack()
: multiIndex중 두 번째 index를 전치한다.
multi_groupby.unstack()
>
위와 같이 두번째 index인 'Year'를 전치시킨다. 이때 값이 없는 곳은 NaN으로 채워진다.
.swaplevel() & .sort_index()
.swaplevel(): index 간의 우선순위를 변경한다.
.sort_index(): 첫 번째 index를 기준으로 데이터를 오름차순으로 재정렬한다.
m1 = multi_groupby.swaplevel()
m2 = multi_groupby.swaplevel().sort_index()
print(m1,"\n",m2)
>
m1은 기존에 'Team', 'Year'순서였던 index를 'Year', 'Team'으로 단순히 순서만 바꾼것이다. 이때 index에 중복 값들이 다시 나타난다.
m2는 첫 번째 index인 'Year'을 기준으로 오름차순으로 데이터를 재정렬한것이다.
그리고 아까 '레벨별로 별도의 연산함수를 지정'할수 있다고 했는데, 여기서 레벨(level) = index이다.
그리고 level은 0부터 시작하는 숫자인데, 순서는 index의 순서와 같다.
lv0 = multi_groupby.mean(level=0) #평균
lv1 = multi_groupby.std(level=1) #표준편차
print(lv0, "\n", lv1)
>
grouped 상태
마지막으로 grouped상태라는게 있는데, 이는 split만 적용한 상태의 데이터이다.
이때 method로 .get_group("key값") 적용하면 해당 key값을 기준으로 분할된 DataFrame객체를 반환한다.
grouped = df.groupby("Team")
grouped.get_group("Riders")
>
이렇게 'Team'에서 'Riders'값을 갖는 데이터들만 반환한다.
그리고 grouped상태의 DataFrame에 다음과 같은 method들도 적용할수 있는데
- aggregation(집계): 요약된 통계 정보 추출
.agg(연산): groupby의 결과와 비슷하나 모든 열에 연산을 적용하는 점이 다르고, DataFrame객체로 반환된다.
grouped.agg(np.mean)
>
'Team'으로 분할된 데이터에 각 key값마다 평균을 계산한다.
이때 연산을 지정한 열이 없으므로 모든 열에 대한 평균값을 계산한다.
- transformation(변환): 해당 정보 변환
.transform(연산): grouped상태에서 연산 값들을 추출해 넣은 후 combine발생
.transform(사용자 지정 함수): grouped상태의 연산 값들을 추출하여 각각 split된 상태의 값에 적용 시킴
score = lambda x: (x - x.mean()) / x.std()
grouped.transform(score)
>
'Team'으로 분할된 데이터이므로 'Team'열을 제외한 나머지 열들에 연산을 적용한다.
- filter(필터): 특정 정보 필터링, 매개변수로 True/False 구분하는 함수 넣어야함
.filter(lambda x: 표현식) --> 이때 x는 분할 기준 열의 key값들의 집합(group)이다.
grouped.filter(lambda x: x["Year"].max() > 2016
>
grouped는 현재 'Team'으로 분할(split)된 상태다. 이때 각 key값들의 집합에서 'Year'의 최댓값(max())가 2016보다 큰 요소를 반환한다.
원본데이터를 보면
'Riders' group에서 'Year'의 최댓값은 (0, 1, 8,11)번째들 중 11번째이다. 이 값이 2016보다 크므로 반환된다.
다른 key group들도 같은 방식으로 결과가 반환된다.
'pandas' 카테고리의 다른 글
데이터 추출 (0) | 2022.04.01 |
---|---|
DataFrame객체 (0) | 2022.03.30 |
Series객체 (0) | 2022.03.30 |