그룹별 집계(group by)
는 데이터로부터 동일한 객체를 가진 데이터만 따로 뽑아 기술 통계 데이터를 추출하는 것입니다.
예를 들어 A반 수학 점수의 원본 데이터를 가지고 해당 데이터에서 같은 성별을 가진 학생들의 평균 점수를 구하거나 50점 이상을 받은 학생의 수를 구하는 등의 과정 입니다.
group by
명령어는 분할
→ 적용
→ 결합
과정을 거칩니다.
위 단계를 거치면 어떤 키 값을 기준으로 통합된 통계 데이터를 얻을 수 있습니다.
예시 코드는 아래와 같습니다.
해당 데이터는 레이싱 팀이 매년 대회에 참가해서 얻은 랭크와 점수입니다.
이를 활용하여 데이터 프레임을 만들고 groupby
를 활용하여 팀별 합산 점수를 구합니다.
import pandas as pd
import numpy as np
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.groupby("묶음의 기준이 되는 열")["적용받는 열"].적용받는연산()
df.groupby("Team")["Points"].sum()
💡 주의사항
groupby의 결과물은 항상 시리즈 객체 입니다.
한 개 이상의 열을 기준으로 그룹별 집계를 실행하는 방법을 말합니다.
이전 예시에서 사용한 데이터를 활용해서 여러 열을 key 값으로, points를 추출하고 sum 연산을 적용해보겠습니다.
multi_groupby = df.groupby(["Team", "Year"])["Points"].sum()
multi_groupby
💡 한개 이상의 열로 그룹별 집계를 수행하면 여러 열이 모두 인덱스로 반환됨
인덱스 추출
multi_groupby["Devils":"Kings"]
unstack
함수는 기존 인덱스를 기준으로 묶인 곳에서 두번째 인덱스에 해당하는 것을 열로 변환해서 엑셀의 피봇테이블 같은 형태로 변환 합니다.
아래 예시코드에서 두번째 인덱스였던 year가 열로 변환된 것을 볼 수 있습니다.
multi_groupby.unstack()
swaplevel
함수를 사용하면 인덱스 간의 레벨을 변경할 수 있습니다.
multi_groupby.swaplevel()
sort_index
함수를 사용하면 첫번째 인덱스를 기준으로 데이터를 재정렬 합니다.
multi_groupby.swaplevel().sort_index()
그룹화된 상태라는 말의 의미는 group by의 단계인 분할 → 적용 → 결합
중에서 분할
까지만 이루어진 상태를 의미하며,
get_group
함수를 사용하여 해당 키 값을 기준으로 분할된 데이터프레임 객체를 확인 할 수 있습니다.
grouped = df.groupby("Team")
grouped.get_group("Riders")
요약된 통계정보를 추출하는 집계를 구현하기 위해서는 agg
함수를 사용합니다.
grouped.agg(min)
grouped.agg(np.mean)
변환은 집계와는 달리 키 값별로 요약된 정보가 아닌 개별 데이터 변환을 지원합니다.
또한, 적용 시점에서는 그룹화된 상태의 값으로 적용됩니다.
grouped.transform(max)
score = lambda x: (x - x.mean()) / x.std()
grouped.transform(score)
특정 조건으로 데이터를 검색할 때 사용하는 함수 이며, 주로 filter
함수를 사용합니다.
df.groupby('Team').filter(lambda x: len(x) >= 4)
병합(merge)는 두개의 데이터를 특정한 기준을 가지고 하나로 통합하는 작업을 의미합니다.
SQL에서는 join
이라는 표현을 주로 사용 합니다.
import pandas as pd # pandas 모듈 호출
raw_data = {
'subject_id': ['1', '2', '3', '4', '5', '7', '8', '9', '10', '11'],
'test_score': [51, 15, 15, 61, 16, 14, 15, 1, 61, 16]}
df_left = pd.DataFrame(raw_data, columns = ['subject_id', 'test_score'])
raw_data = {
'subject_id': ['4', '5', '6', '7', '8'],
'first_name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
'last_name': ['Bonder', 'Black', 'Balwner', 'Brice', 'Btisan']}
df_right = pd.DataFrame(raw_data, columns = ['subject_id', 'first_name', 'last_name'])
pd.merge(left=df_left, right=df_right, how="inner", on='subject_id')
# pd.merge(df_left, df_right, on='subject_id', how='left')
subject_id
를 기준으로 내부 조인을 수행
연결(concatenate)
은 병합과는 달리 두 테이블을 그대로 붙이는 방법입니다.
데이터의 스키마가 동일할 때, 그대로 연결하며 주로 concat
함수를 사용합니다.
import os
print(os.getcwd()) # 현재 작업 디렉토리(현재 코드가 실행되는 폴더) 출력
print(os.listdir()) # 그 디렉토리에 있는 파일들과 폴더 목록 보기
import os
folder = '/content'
filenames = [
os.path.join(folder, filename)
for filename in os.listdir(folder)
if 'sales' in filename and filename.endswith('.xlsx')
]
print(filenames)
#['/content/sales-jan.xlsx', '/content/sales-mar.xlsx', '/content/sales-feb.xlsx']
df_list = [pd.read_excel(filename, engine="openpyxl") for filename in filenames]
for df in df_list:
print(type(df), len(df))
# <class 'pandas.core.frame.DataFrame'> 134
# <class 'pandas.core.frame.DataFrame'> 142
# <class 'pandas.core.frame.DataFrame'> 108
df = pd.concat(df_list, axis=0)
print(len(df)) # 384
df.reset_index(drop=True)