시계열 데이터를 다룰 땐 문자열 형태가 아닌 날짜와 시간 타입으로 변환하는 작업이 필요하다. datetime, numpy, pandas 를 활용하여 날짜와 시간을 변환 또는 생성하는 방법에 대해 알아보고자 한다. 참고로 numpy에서 날짜와 시간은 datetime64 객체로 표현하고 datetime을 사용한 날짜와 시간은 datetime 으로 표현한다. numpy에서의 datetime64는 시간을 10의 -18승(아토초)의 단위까지 표현할 수 있으며 datetime.datetime은 시간을 10의 -6승(마이크로초)의 단위까지 관리한다는 차이점을 가지고 있다(datetime64가 시간을 더 넓은 범위로 관리함).


1. datetime

from datetime import datetime

datetime(2023, 7, 26)
>>> datetime.datetime(2023, 7, 26, 0, 0)

datetime.datetime 으로 날짜와 시간을 표현한다면 위와 같이 year, month, day 값을 꼭 입력해 주어야한다. 만약 세 가지 값(연, 월, 일)을 전달하지 않는다면 TypeError: function missing required argument 'month' (pos 2) 와 같은 타입에러 메시지가 발생한다(이 메시지는 연도만 전달했을 때 확인할 수 있음). 시, 분, 초는 선택사항이고 따로 지정하지 않는다면 0으로 세팅된다.
연, 월, 일 값을 전달할 땐 숫자로 전달해야한다. 만약 str 형태로 전달한다면 다음과 같은 타입에러 메시지를 확인할 수 있다. TypeError: an integer is required (got type str)
출력된 값의 형태를 보면 알 수 있듯이 datetime.datetime 의 형태로 날짜와 시간을 표현하고 있다.


2. numpy

넘파이는 날짜와 시간을 datetime64 형태로 표현한다. 넘파이로 날짜를 생성하는 방법에 대해 알아보자.

(1) 문자열로 날짜로 생성하기

import numpy as np

np.datetime64('2023-07-26')
>>> numpy.datetime64('2023-07-26')

문자열 형태로 datetime64 형태로 변환할 때 주의해야하는 점은 문자열의 형태이다. 만약 ‘2000 01 01’, ‘2000_01_01’, ‘2000/01/01’ 등의 형태로 전달하면 넘파이가 문자열 속의 날짜(연, 월, 일)을 parsing을 잘 하지 못해 ValueError: Error parsing datetime string 라는 에러 메시지를 반환한다. numpy에서 문자열로 날짜를 생성할 땐 문자열 형식에 주의하도록 한다.

(2) 유닉스 시간으로 날짜로 생성하기

import numpy as np

np.datetime64(53, 'Y')
np.datetime64(120, 'M')
np.datetime64(3650, 'D')
>>> numpy.datetime64('2023')
>>> numpy.datetime64('1980-01')
>>> numpy.datetime64('1979-12-30')

유닉스 시간(1970년 1월 1일 00:00:00 UTC)에 상대적인 오프셋으로 정수에서 날짜/시간을 생성하는 것도 가능하다. 위에 작성한 코드(예시)를 보면 53과 Y(연도)를 전달했을 때 2023년이라는 연도 데이터가 나왔다. 이는 유닉스 시간을 기준으로 53년 후의 값을 반환하도록 한 것이다.
다음 예시는 유닉스 시간에서 M(월)을 기준으로 120달 후의 날짜로 반환, D(일)을 기준으로 3650일 후의 날짜로 반환해 본 것이다.

(3) array에 dtype 설정하기

넘파이의 array 함수를 사용할 때 dtype으로 datetime64를 지정하면 str 형태의 날짜 리스트를 datetime64 형태로 배열을 구성할 수 있다.

import numpy as np

np.array(['2000-01-01', '2000-01-02', '2000-01-03'], dtype='datetime64')
>>> array(['2000-01-01', '2000-01-02', '2000-01-03'], dtype='datetime64[D]')

생성된 배열의 dtype을 보면 datetime64[D]의 형태로 데이터가 저장되었음을 확인할 수 있는데 []안의 D는 일자의 정밀도를 가진다는 뜻이다. array를 생성할 때 연, 월, 일로 구성된 데이터를 datetime64[Y]의 데이터타입으로 저장하면 연도까지만 정밀도를 가지게 되어 array에는 연도값만 저장된다.

import numpy as np

np.array(['2000-01-01', '2000-01-02', '2000-01-03'], dtype='datetime64[Y]')
>>> array(['2000', '2000', '2000'], dtype='datetime64[Y]')

array로 날짜 리스트를 datetime64 형태로 저장할 때 주의해야하는 점은 dtype이다. dtype을 따로 지정하지 않으면 문자열 형태로 인식한다는 점을 주의해야한다.

(4) arange로 날짜 범위 생성하기

넘파이의 arange 함수를 사용하면 두 날짜(범위의 시작일과 마지막일) 사이의 값들을 생성할 수 있다. 이때 주의해야할 점은 생성된 날짜엔 마지막일자가 포함되지 않는다는 것이다.

import numpy as np

np.arange('2000-01', '2001-01', dtype='datetime64[M]')
>>> array(['2000-01', '2000-02', '2000-03', '2000-04', '2000-05', '2000-06',
           '2000-07', '2000-08', '2000-09', '2000-10', '2000-11', '2000-12'],
           dtype='datetime64[M]')

위 예시는 2000년 1월부터 2001년 1월 사이를 월 단위로 생성하였다(end date로 지정한 2001년 1월은 범위에 포함되지 않음). 범위를 생성할 때에도 datetime64 뒤의 [] 안에 어떤 값을 넣는지에 따라 날짜 단위를 지정할 수 있다.

(5) 단위코드 정리

코드 의미
Y
M
W
D
h 시간
m
s
ms 밀리초
us 마이크로초
ns 나노초
ps 피코초
fs 펨토초


3. pandas

판다스에서도 날짜 데이터를 다루기 위한 여러 함수들이 정의되어있다. 판다스에서는 날짜와 시간 데이터를 DatetimeIndex 객체로 표현한다.

(1) to_datetime

Pandas의 to_datetime 함수를 사용하면 문자열 형태를 날짜 형태로 변경할 수 있다. 또한 format 인자에 날짜형식(인식 대상)을 지정할 수 있다는 장점이 있다.

import pandas as pd

pd.to_datetime(['2000-01-01', '2000-01-02', '2000-01-03'])
>>> DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03'], dtype='datetime64[ns]', freq=None)

to_datetime 메서드를 활용하면 dataframe을 구성하는 특정 열을 가져와서 그 열에 포함된 데이터를 datetime64 형태로 변환할 수 있다. 판다스에선 datetime64[ns], 즉 나노초 정도의 정밀도를 가진다.

(2) date_range

판다스에서는 numpy의 arange 함수와 동일한 기능을 제공한다. date_range 함수를 사용하면 범위의 시작일, 기간의 개수, 수준(freq)를 지정해 주면 그에 맞는 날짜 범위를 생성해 준다.

import pandas as pd

pd.date_range('2020-01-01', periods=11, freq='M')
>>> DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
                   '2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
                   '2020-09-30', '2020-10-31', '2020-11-30'],
                   dtype='datetime64[ns]', freq='M')

위 예시는 2020년 1월 1일을 기준으로 11개의 날짜를 생성하는데 freq(날짜를 생성하는 수준)를 M(월별 마지막일)로 전달하여 11개의 날짜를 생성하였다. freq 에 전달하는 코드는 ‘Pandas, Offset aliases’ 의 링크를 클릭하면 확인할 수 있다.
따로 freq를 전달하지 않고 시작일, 종료일, 개수(periods)만 전달해도 그에 맞는 범위의 날짜 데이터를 생성할 수 있다. date_range 함수는 numpy에서의 arange 함수와는 다르게 end date를 포함한다(start date, end date, periods 전달 시).

(3) DatetimeIndex

판다스에서는 DatetimeIndex 라는 메서드를 제공하는데 이 메서드에 list나 array를 전달하면 날짜 형태의 데이터로 변환할 수 있다.

import pandas as pd
import numpy as np

arr = np.array(['2000-01-01', '2000-01-02', '2000-01-03'])
pd.DatetimeIndex(arr)
>>> DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03'], dtype='datetime64[ns]', freq=None)


4. Reference


👩🏻‍💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.

댓글남기기