cs

상세 컨텐츠

본문 제목

[KOR] [Pandas] PeriodIndex vs. DatetimeIndex

2 Main Languages/Python

by shin15530 2022. 1. 2. 04:37

본문

특히나 교통 부문 데이터 분석 과정에서 자료가 시간과 결합하여 시계열 자료로써 분석해야 하는 경우가 많다. 시간대별 교통량이나 연도별 비행기 탑승객 수 등이 그 예시이다.

 

반면, Pandas 패키지에서는 통계프로그램 Rts class를 지원하는 것과는 다르게 pandas.Series가 시간과 관련된 index를 갖는 경우만 시계열 분석 관련 패키지를 활용할 수 있는 방식을 채택하고 있다. 그중 내가 가장 어려움을 겪었던 분기 관련 시계열 자료와 일반적인 시계열 자료에 대해 Pandas 패키지에서 정의하는 방법을 포스팅하고자 한다. 예제는 Pandas 공식 문서에 있는 코드를 일부 수정하여 활용하였다.

 

Overview

기본적으로 Pandas 패키지는 시간과 관련된 개념을 4가지로 나누어 다룬다.

  1. Date times
    - 특정한 날짜와 시간의 개념 (w/ timezone) (datetime.datetime 기반)
  1. Time deltas (An absolute time duration)
    - 타이머와 같이 몇시간 몇 분 몇 초에 대한 개념이며, 위의 Date time 간의 차이를 의미함
  1. Time spans
    - 반기 · 분기처럼 (1) 특정 시점에 의해 구분되며 (2) 주기적으로 반복되는 시간 개념
    - 시점이자 기간으로 해석될 수 있다는 특징을 가짐
  1. Date offsets (A relative time duration)
    - 달력에 의해 계산된 시간의 차이를 의미함
    - 한달 차이와 30일 차이는 각각 Date offsets, Time deltas 개념에 대응됨

우리는 그중 Date timesTime spans의 개념에 대해 아래에서 알아보고자 한다.

 

Timestamps vs. Time spans

보편적으로 자주 쓰이는 날짜 형식의 자료는 모두 Timestamp라고 보아도 무방하다. "yyyy-mm-dd HH:MM:SS" 형식에서 최소한 날짜가 채워져 있다면 아래와 같이 Timestamp 객체로 만들어 연산이 가능하다.

>>> pd.Timestamp("2021-01-02")
Timestamp('2021-01-02 00:00:00')

>>> pd.Timestamp(2021, 1, 2)
Timestamp('2021-01-02 00:00:00')

 

반면, 반기나 분기와 같은 개념은 특정 시점으로 해석하는 경우도 많으나 대부분 동일 기간 내 자료를 집계한 결과로써 활용된다는 점에서 위의 Timestamp와 구별된다. 그런 경우를 위해 만들어진 개념이 Period이다. 앞서 말했듯이, 달력 형식에서 '일'이 빠지는 경우, 해당 달의 날짜를 특정할 수 없기 때문에 Period 객체로 만들 수도 있다.

>>> pd.Period("2021Q1") # inferred
Period('2021Q1', 'Q-DEC')

>>> pd.Period("2021Q1", freq="Q-JAN") # explicit
Period('2021Q1', 'Q-JAN')

 

한편 TimestampPeriod 객체는 각각 DatetimeIndexPeriodIndex로 데이터를 구분짓는 index로써 역할을 수행할 수 있다.

 

DatetimeIndex vs. PeriodIndex

기존 날짜형식의 문자열을 이용하여 DatetimeIndexPeriodIndex를 만드는 경우, .to_datetime()이나 .astype() 형변환을 통해 원하고자 하는 인덱스를 생성할 수 있다.

# timestamp
>>> dti = [
            "2017-01-01T00:00:00",
            "2017-01-01T00:30:00",
            "2017-01-01T00:31:00",
            "2017-01-01T01:00:00",
            "2017-01-01T03:00:00",
            "2017-01-01T03:05:00",
          ]    
>>> pd.to_datetime(dti) # inferred
DatetimeIndex(['2017-01-01 00:00:00', '2017-01-01 00:30:00',
               '2017-01-01 00:31:00', '2017-01-01 01:00:00',
               '2017-01-01 03:00:00', '2017-01-01 03:05:00'],
              dtype='datetime64[ns]', freq=None)

# period
>>> pi = pd.Series(['2000Q1', '2000Q2', '2000Q3', '2000Q4', '2001Q1', '2001Q2'])
>>> pi = pi.astype('period[Q]')
>>> pd.PeriodIndex(pi)
PeriodIndex(['2000Q1', '2000Q2', '2000Q3', '2000Q4', '2001Q1', '2001Q2'], dtype='period[Q-DEC]', freq='Q-DEC')

 

간혹 DatetimeIndexPeriodIndex를 사용하며, 두 인덱스 방식을 번갈아 사용하는 경우엔 .to_timestamp().to_period()를 활용하자.

# period2timestamp
>>> ss.index = ss.index.to_timestamp(freq='Q-DEC') # explicit

# timestamp2period
>>> ss.index = ss.index.to_period() # or
>>> ss.index.astype("period[M]") # .asfreq() and .to_period() at once

 

PeriodIndex에서 freq=None이거나 inferred_freq에 의해 의도치 않은 값을 갖는 경우가 있다. 그러한 경우 아래의 코드로 커스터마이즈 해줄 수 있다.

>>> ss.index.asfreq('Q-DEC')

>>> ss.index = pd.to_datetime([]) # freq=None
>>> add_freq(ss.index, freq='D')

 

Summary

  • Pandas 패키지에서 시계열 데이터를 다루기 위해서는 반드시 시간과 관련된 인덱스를 지정해줘야한다.
  • 그중 많이 쓰이는 DatetimeIndexPeriodIndex에 대해 알아보았다.
  • freq가 지정되지 않았거나 잘못 유추한 경우엔 freq='D'와 같이 지정하는 방식을 이용하자.

References

'2 Main Languages > Python' 카테고리의 다른 글

[KOR] [Pandas] Removing Commas from Values in Pandas  (0) 2022.01.26

관련글 더보기

댓글 영역