본문 바로가기

카테고리 없음

pandas groupby 파이썬 데이터 그룹핑 예제

반응형
본 포스트는 외국 사이트의 내용을 한국어로 재정리한 글입니다.

이번 포스트에서 다룰 내용은 아래와 같습니다.

  • pandas의 groupby를 진짜 세계데이터에서 사용하는 법

  • 단계별로 split-apply-combine 하는법

  • 다시 split-apply-combine 을 decompose 하는법

  • pandas groupby를 이용해서 속해있는 데이터에따라 다른 카데고리에 위치시키는 방법

들어가기에 앞서서

# 소수 셋째자리 밑으로는 과학적 표기법으로 표시 설정
pd.set_option("display.precision", 3)

# 데이터를 표시해주는 프레임 라인 안보이게 설정
pd.set_option("display.expand_frame_repr", False)

# row의 표시를 25줄로 설정
pd.set_option("display.max_rows", 25)

다음과 같이 pandas의 데이터 표시 설정을 해줍니다.

링크에서 현실세계에 쓰이는 data set을 다운 받습니다.

 

예제 1: U.S 의회 dataset

미국 의회 리스트 데이터를 이용할 것입니다. 먼저 CSV파일을 read_csv() 함수로 데이터를 read합니다.

import pandas as pd

dtypes = {
    "first_name": "category",
    "gender": "category",
    "type": "category",
    "state": "category",
    "party": "category",
}
df = pd.read_csv(
    "groupby-data/legislators-historical.csv",
    dtype=dtypes,
    usecols=list(dtypes) + ["birthday", "last_name"],
    parse_dates=["birthday"]
)

이 dataset에는 성과 이름, 생일, 성별, 타입(rep='하원', sen='상원'),U.S 주, 당 등의 데이터가 있으며 df.tail()을 이용해서

마지막 데이터의 정보를 볼 수 있습니다.

 

여기서 이 DataFarme은 메모리 효율을 높이기 위해 categorical dtypes을 사용합니다.

dtypes를 통해 대부분의 데이터 타입이 category인걸 알 수가 있는데 이는 메모리량을 줄여주는 역할을 합니다.

 

 

이제 groupby가 무엇인지 알아볼까요

자, 만약 SQL에서 위의 data set을 이용해서 각 주마다 의회의 멤버 리스트를 뽑는다면 아래와 같은 SELECT statement를 사용하는걸 볼 수 있습니다.

 

이제 파이썬에서 비슷하게 실행하는 방법입니다.

>>> n_by_state = df.groupby("state")["last_name"].count()
>>> n_by_state.head(10)

groupby()의 인자값에 그룹핑할 column 이름을 넣고 ["last_name"] 을 이용해 특정 column만 불러오게 합니다.

.groupby()에는 첫번째 이자값에 하나의 column 뿐만아니라 다음과 같은 여러타입을 지정 할 수 있습니다.

  • 여러 column 의 리스트
  • Series 나 dict
  • Numpy array 나 Pandas 의 Index, iterable 가능한 array

그 다음으로 두개의 column을 이용해 그룹핑한 예제입니다. 

>>> df.groupby(["state", "gender"])["last_name"].count()

 

 

예제 2: 공기 질 dataset

이 data set은 한시간별로 이태리에서 공기를 측정한 것으로, 측정 안되는 빠지는 값은 -200으로 CSV파일을 불러올 때 명시를 하였습니다. 또한 read_csv() 함수에서 두개의 column을 하나의 timestamp 으로 만들어 인덱스로 사용하였습니다.

import pandas as pd

df = pd.read_csv(
    "groupby-data/airqual.csv",
    parse_dates=[["Date", "Time"]],
    na_values=[-200],
    usecols=["Date", "Time", "CO(GT)", "T", "RH", "AH"]
).rename(
    columns={
        "CO(GT)": "co",
        "Date_Time": "tstamp",
        "T": "temp_c",
        "RH": "rel_hum",
        "AH": "abs_hum",
    }
).set_index("tstamp")

이 코드는 Datetime Index와 4개의 float column의 DataFrame을 만듭니다.

여기서 co 는 한시간동안의 평균 일산화탄소, 이고 temp_c는 섭씨 온도, rel_hum(relative_humidity)는 상대습도, abs_hum(absolute humidity)는 절대습도 를 나타냅니다. 측정은 2004 march에서 2005 april 까지 되어있습니다.

 

 

Array를 이용해서 그룹핑하기

이전에 .groupby()는 여러타입의 인자값을 넣을 수 있다고 알려드린적 있습니다.

  • 여러 column 의 리스트

  • Series 나 dict

  • Numpy array 나 Pandas 의 Index, iterable 가능한 array

만약 일주일별로 하루씩 그룹을 한다고 했을 때 마지막 3번째 옵션을 이용하면 가능합니다. 먼저 판다스의 index중 .day_name()을 이용해서 어떻게 하는지 알아보겠습니다.

 

>>> day_names = df.index.day_name()
>>> type(day_names)
<class 'pandas.core.indexes.base.Index'>
>>> day_names[:10]
Index(['Wednesday', 'Wednesday', 'Wednesday', 'Wednesday', 'Wednesday',
       'Wednesday', 'Thursday', 'Thursday', 'Thursday', 'Thursday'],
      dtype='object', name='tstamp')

여기서 day_names 는 array입니다. 1차원의 시쿼스형 입니다.

>>> df.groupby(day_names)["co"].mean()

 

여기서 만약 하루가 아닌 한시간별로 알고 싶다면 어떻게 해야할까요? 결과는 7 * 24 = 168 개의 정보가 나올 것입니다.이렇게 하기 위해서는 판다스의 인덱스 오브젝트(Int64Index)를 사용하면 됩니다.

>>> hr = df.index.hour
>>> df.groupby([day_names, hr])["co"].mean().rename_axis(["dow", "hr"])
dow        hr
Friday     0     1.936
           1     1.609
           2     1.172
           3     0.887
           4     0.823
                 ...
Wednesday  19    4.147
           20    3.845
           21    2.898
           22    2.102
           23    1.938
Name: co, Length: 168, dtype: float64

 

반응형