본문 바로가기
파이썬/파이썬 스터디

파이썬 pandas(판다스) groupby - 시간에 따라 묶기

by davi_kr 2024. 8. 4.
반응형

결과물

년월, 결제수단(payment)에 따라 총 금액을 볼 수 있고 해당 년월에 특정 자치구에서 나온 값들도 같이 볼 수 있습니다.

데이터 둘러보기

groupby를 어떻게 활용할 수 있는지, 자세히 다뤄보기 위해 데이터를 먼저 둘러봅니다.

이용할 데이터는 택시 관련 정보입니다.

import pandas as pd
import seaborn as sns
import numpy as np
df = sns.load_dataset('taxis')
df.info()

 

df.head(5)

 

위 데이터는 상차, 하차 시간, 승객 수, 거리, 운임비, 팁, 톨비, 총 비용, 색상, 결제수단, 상차 지역, 하차 지역, 상차 자치구, 하차 자치구 정보로 구성되어 있습니다.

 

df.isnull().sum()

결측치는 수량이 얼마나 있는지 확인해봅니다.

 

df['payment'].unique()

결측치가 있는 열은 유니크 값이 어떻게 구성되어 있는지도 확인해봅니다.

 

오늘은 groupby 공부하려는 거라.. 그냥 결측치가 있는 행들은 다 제외시키겠습니다.

 

# df에서 빈 값이 있는 행들은 모두 제외함
df1 = df.dropna().copy()
# 빈 값이 있는 행이 있을지, 전체적으로 합산해서 확인
df1.isnull().sum().sum()

 

groupby 작동 원리

groupby는 말 그대로 묶어주는 기능을 합니다. 

예를 들어, payment에 따라 발생한 total의 합이 궁금하다면?

아래와 같이 작성하면 됩니다.

df1.groupby('payment')[['total']].sum()

 

쉽게 생각하면 groupby 함수는 먼저 payment열의 값들을 기준으로 분리합니다.

위에서 cash, credit card, nan이었으나 nan은 전부 날렸기 때문에 기준은 cash와 credit card가 됩니다.

분리한 상태에서 sum()을 적용합니다.

그리고 다시 칩니다.

 

이 과정을 split → apply → combine으로 이해하면 됩니다.

따라서 groupby까지만 사용한 경우엔 split 까지만 해둔 상태라고 보실 수 있겠습니다.

그때는 아래처럼 결과값도 그냥 groupby object라고만 노출됩니다.

df1.groupby('payment')

 

apply할 값에는 sum 외에도 다양한 수치를 계산하는 함수들을 사용할 수 있으며, 직접 만든 함수도 쓸 수 있습니다.

함수 이름 설명
sum 합 계산
mean, median, mod 평균, 중위값, 최빈값 계산
max, min 최대, 최소값 계산
count, nunique, size NaN 제외한 값, 유니크 값, NaN 포함한 값 세기
std, var 표준편차, 분산 계산

 

 

시간에 따라 그룹핑하기

시간에 따라 그룹핑을 해보기 위해 먼저 시간 열을 추가하겠습니다.

df1['year'] = df1['pickup'].dt.year
# 상반기, 하반기도 추가
def determine_half_year(date):
    year = date.year
    month = date.month
    if month <= 6:
        return f"{year}H1"
    else:
        return f"{year}H2"

df1['half'] = df1['pickup'].apply(determine_half_year)
df1['quarter'] = df1['pickup'].dt.to_period('Q')
df1['year_month'] = df1['pickup'].dt.to_period('M')
df1['date'] = df1['pickup'].dt.to_period('D')

df1.head(5)

 

기존에 했던 그룹핑에 년월 기준을 추가해보겠습니다.

df1.groupby(['year_month','payment'])['total'].sum()

데이터가 아쉽네요^^;;  같은 해 2월 3월 뿐이었네요...

 

특정 열의 값들을 열로 바꾸기

구하다보면 같은 열에 있는 데이터들의 수량을 각각의 열로 변환해서 보고 싶을 때가 있습니다.

여기선 unstack과 pivot_table을 사용해봤습니다.

 

먼저 년월 기준으로 값을 추출하기 위해 위에서 했던 것과 동일한 결과 값에 index만 리셋했습니다.

grouped_df1 = df1.groupby(['year_month','payment']).agg({
    'total':'sum'
}).reset_index()

 

pickup_borough의 값들을 기준으로 새로 열을 만들어봤습니다. 

grouped_df_pickup_borough = df1.groupby(['year_month','payment','pickup_borough']
                                        ).agg({'total':'sum'}).unstack(fill_value=0)

 

원래는 이 상태 그대로 merge 해보려고 했는데, Not allowed to merge between different levels. (1 levels on the left, 2 on the right) (1 levels on the left, 2 on the right) 오류가 났습니다.

 

 

문제를 해결하고자 pivot_table 기능을 사용해봤습니다.

grouped_df_pickup_borough = df1.pivot_table(index=['year_month', 'payment']
                                            , columns='pickup_borough'
                                            , values='total'
                                            , aggfunc='sum'
                                            , fill_value=0).reset_index()

 

result = grouped_df1.merge(grouped_df_pickup_borough
                           , how='inner'
                           , on=['year_month','payment'])

결과물이 잘 나왔습니다. 해당 년월에 사용한 현금, 신용카드 기준으로 총 금액이 얼마인지 특정 자치구에서는 얼마가 나왔는지를 한눈에 볼 수 있게 됐습니다.

반응형

댓글