[Python] 날짜와 시간 다루는 방법 (feat. datetime)
시계열 데이터를 다룰 땐 문자열 형태가 아닌 날짜와 시간 타입으로 변환하는 작업이 필요하다. 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
👩🏻💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.
댓글남기기