시계열 데이터

Author

Gabriel Yang

시계열 데이터는 일정 시간간격을 측정된 정보한 데이터입니다. 시계열 데이터는 시간의 흐름에 따라서 테이터가 갖는 특징을 확인하기 위해서 생성되며 금융 정보나 생체 정보등의 특징을 저장하는 경우가 많습니다.

Pandas는 시계열 데이터를 관리하기 위한 많은 기능을 제공합니다. 데이터의 추세, 주기성 등을 파악할 수 있고 필요한 경우 예측 모델링을 할 수 있습니다. 그리고 원하는 형태의 시간을 표시할 수 있도록 DatetimeIndex, Timestamp, Teimdelta등 다양한 함수를 지원하고 있습니다.

시간 데이터형

시계열 데이터를 이해하기 위해서 데이터를 구성하는 날짜를 어떻게 지정하는 지 이해해야 합니다. 파이썬은 날짜와 시간을 나타내는 datetime클래스를 제공합니다. 그리고 Pandas는 datetime객체를 Timestamp 객체로 변화시켜 사용합니다.

from datetime import datetime
new_year = datetime(2023, 1, 1, 0, 0)
new_year
datetime.datetime(2023, 1, 1, 0, 0)

datetime객체를 이용하여 2023년 1월 1일 0시 0분을 나타내는 객체를 생성하였습니다. 이제 Timestamp를 이용하여 특정 시점을 표현합니다.

import pandas as pd
time_start = pd.Timestamp('2002-5-5 13:00')
time_start
Timestamp('2002-05-05 13:00:00')

이제 Pandas의 시계열 데이터의 특정시점을 지정하기 위해서 Timestamp 객체를 생성할 수 있습니다. 하지만 시간 정보를 전달 받는 대부분의 라이브러리는 내부적으로 Timestamp객체로 만들어 데이터를 처리하기 때문에 날짜 및 시간을 표시하는 문자열을 전달 받습니다.

만약 이와 같이 구성하지 않고 생각해보면 매번 Timestamp나 datetime 클래스로 시간 정보를 변경해서 전달 해야 했다면 매우 불편했을 것 같습니다.

시계열 데이터는 데이터의 인덱스로 시간 정보를 사용하는 경우가 대부분입니다. Pandas에서는 Timestamp 데이터로 정의된 인덱스인 DatetimeIndex객체를 사용합니다. 시계열 데이터로 데이터 프레임을 생성하고 이 데이터 프레임 index가 어떤 데이터 형인지 알아봅니다.

dates = pd.Series([10, 20], [pd.Timestamp('2023-1-1'), pd.Timestamp('2023-1-2')])
print(type(dates.index))
display(dates)
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
2023-01-01    10
2023-01-02    20
dtype: int64

위의 코드에서 dates라는 이름으로 pandas series데이터를 생성했습니다. 데이터와 함께 index로 Timestamp정보가 전달됩니다. dates series 데이터에 전달된 Timestamp는 인덱스로 사용되면서 데이터형은 DatetimeIndex로 설정되었습니다.

df = pd.DataFrame({'data': [10, 20]},
                    index = pd.to_datetime(['2023-1-1', '2023-1-2']))
print(type(df.index))
display(df)
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
data
2023-01-01 10
2023-01-02 20

위의 코드는 df 데이터 프레임 생성 시 index정보를 to_datetime()함수를 이용하여 Timestamp로 변환하고 이를 index로 전달했습니다. 데이터 프레임의 index는 이전 예제와 같이 DatetimeIndex로 표시됩니다.

Tip

하지만 매번 Timestamp객체를 만들어 전달하는 것을 코드의 가독성을 낮추는 문제가 있습니다. to_dateteime함수는 Pandas는 Timestamp로 전달될 수 있는 문자열을 Timestamp로 변환할 수 있기 때문에 좀 더 효율적으로 DatetimeIndex를 생성할 수 있습니다.

시간 간격 표현방법

Timedelta

Timedelta 클래스는 시간간격을 표시하기 위해 사용됩니다. 두 날짜 사이의 차이를 계산하거나 간격을 계산하기 위해서 사용됩니다. Timedelta를 사용하기 위해서는 datatime 패키지에서 Timedelta를 import해야 합니다.

import pandas as pd
from datetime import datetime, timedelta
now = datetime.now()
before_7days = now - timedelta(days=7)
display(before_7days)
datetime.datetime(2024, 6, 22, 23, 7, 14, 174614)

예를 들어 시계열 데이터의 현재시점에서 7일전 데이터와의 차이를 확인하기 위해서는 현재 시점에서 원하는 날짜 차이를 빼야 합니다. timedelta를 사용하여 현재 시간에서 7일전을 계산한 결과가 출력되었습니다.

DateOffset

DateOffset은 정기적인 증가 또는 감소를 표현하기 위한 시간적 크기를 표현합니다. 일정 시점에서 자신이 원하는 시간 간격만큼 더하거나 빼는 수학적 연산을 DateOffset을 이용하여 수행합니다.

date = pd.Timestamp('2023-01-01')
offset_3days = pd.DateOffset(days = 3)
offset_3hours = pd.DateOffset(hours = 3)
display(date + offset_3days)
display(date + offset_3hours)
Timestamp('2023-01-04 00:00:00')
Timestamp('2023-01-01 03:00:00')

2023년 1월 1일을 나타내는 date에 3일과 3시간 간격의 DateOffset 객체를 더해 지정한 간격의 날짜 정보를 얻을 수 있습니다.

시간 반복 시계열 생성방법

Range

Range class는 일정 시간 간격으로 시계열 데이터를 만들어야하는 경우 사용됩니다. 년도, 분기, 월 등 다양한 시간간격을 나타낼 수 있으며 이를 이용하여 일정한 간격의 시계열 데이터를 처리하는 경우에 사용할 수 있습니다.

예를 들어 특정한 시작날짜와 종료날짜 사이의 기간을 주단위로 시간간격으로 정보를 확인해야하는 경우 사용될 수 있습니다.

import pandas as pd
import numpy as np

dates = pd.date_range('2023-1-1', '2023-5-1', freq = 'W')
df = pd.DataFrame({'date' : dates,
                   'value' : range(len(dates))})
display(dates)
display(df.head())
DatetimeIndex(['2023-01-01', '2023-01-08', '2023-01-15', '2023-01-22',
               '2023-01-29', '2023-02-05', '2023-02-12', '2023-02-19',
               '2023-02-26', '2023-03-05', '2023-03-12', '2023-03-19',
               '2023-03-26', '2023-04-02', '2023-04-09', '2023-04-16',
               '2023-04-23', '2023-04-30'],
              dtype='datetime64[ns]', freq='W-SUN')
date value
0 2023-01-01 0
1 2023-01-08 1
2 2023-01-15 2
3 2023-01-22 3
4 2023-01-29 4

datesdate_range()함수에 전달된 시작시점과 종료시점 사이를 freq로 전달된 간격만큼 떨어진 시간 정보를 생성했습니다. freq로 전달될 수 있는 주요 offset정보는 아래와 같습니다. 자세한 내용은 Pandas API 문서에서 확인 합니다.

Alias Description
B business day frequency
BM business month end frequency
MS month start frequency
Q quarter end frequency
W-MON weekly frequency (Mondays)

W-MON은 고정 오프셋으로 특정 날짜를 기준으로하는 빈도가 필요할 때 사용합니다. 위의 예제의 기간 중 매주 월요일을 간격으로 날짜를 생성하는 예제를 확인합니다.

import pandas as pd
import numpy as np

dates = pd.date_range('2023-1-1', '2023-5-1', freq = 'W-MON')
df = pd.DataFrame({'date' : dates,
                   'value' : range(len(dates))})
display(df.head())
date value
0 2023-01-02 0
1 2023-01-09 1
2 2023-01-16 2
3 2023-01-23 3
4 2023-01-30 4

생성된 데이터 프레임의 처음 날짜는 2023년 1월 1일이 아니고 해당 기간 중 첫 번째 월요일인 2023년 1월 2일로 날짜가 생성되었습니다.

Period

일정 시점에서 한달 간격으로 수행하는 작업이 있는 경우 Period를 사용할 수 있습니다. Period는 Timestamp와 DateOffset으로 생성한는 시간 데이터를 더 효율적으로 관리할 수 있도록 합니다.

periods = pd.Period('2023-1-1', freq='M')
display(periods)
display(periods+1)
Period('2023-01', 'M')
Period('2023-02', 'M')

시계열 데이터 만들기

다양한 시계열 데이터를 만들면서 Pandas에서 제공하는 시계열 데이터 생성 기능을 배워봅니다.

특정 빈도의 시계열 생성

Pandas에서 제공하는 to_datetime()'과date_range()` 함수를 이용해서 시계열 데이터를 만들어 봅니다.

index = pd.to_datetime(['2023-1-1', '2023-2-28', '2023-3-31', '2023-4-30'])
data = range(len(index))
df = pd.DataFrame({'data': data},
                    index = index)
print(type(df.index))
display(df)
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
data
2023-01-01 0
2023-02-28 1
2023-03-31 2
2023-04-30 3
Figure 1: 데이터프레임 생성, to_datetime()

위의 예제에서는 to_datetime()함수로 일정 시간 정보를 데이터 프레임의 index로 전달하여 데이터 프레임을 생성합니다. 데이터 프레임의 index는 DateTimeIndex로 표시되었습니다.

index = pd.date_range('2023-1-1', '2023-5-1', freq = 'M')
data = range(len(index))
df = pd.DataFrame({'data' : data},
                   index = index)
display(df)
data
2023-01-31 0
2023-02-28 1
2023-03-31 2
2023-04-30 3
Figure 2: 데이터프레임 생성, date_range()

Section 3.2 에서 사용한 date_range()함수를 이용하면 Figure 1 와 같이 to_datatime()함수 이용한 시간 정보가 동일한 간격이라면 Figure 2 처럼 date_range()함수를 이용해 다시 간략하게 표현할 수 있습니다.