MLOps 부트캠프 by 한경+토스뱅크/Python

DataFrame - 날짜와 시간 데이터 다루기

나니니 2024. 8. 4. 22:41

데이터를 불러올 때 형식 지정하기

pd.to_datetime()

: Timestamp로 된 시리즈

parse_dates()

  • 목적: 데이터프레임의 특정 열을 날짜형으로 변환하여, 날짜와 시간을 보다 쉽게 조작하고 분석할 수 있게 해준다.
  • 사용법: parse_dates는 pd.read_csv() 또는 pd.read_excel() 같은 데이터 읽기 함수의 인자로 사용된다. 
# parse_dates 파라미터에 '날짜' 데이터로 불러올 컬럼명을 입력함
order_df = pd.read_csv('data/order.csv', parse_dates=['order_time', 'shipping_time'])

pandas datetime의 기본 형식은 '연도-월-일' 이다. 

이를 parse_dates=[]에 넘겨주면 pandas가 알아서 값을 인식해 '연도-월-일'로 불러와진다. 

만약, '일/월/연도' 형태로 불러오고자 한다면 dayfirst라는 파라미터를 True로 설정하면 된다. (*기본값은 False로 월/일/연도 순임)

order_df = pd.read_csv('data/order3.csv', parse_dates=['order_time', 'shipping_time'], dayfirst=True)

연도(2자리)/월/일 형식이라면 to_datetime()에 yearfirst라는 파라미터 값을 True로 설정하면 된다. 

NaT(Not a Time) 

  • 목적: 날짜와 시간 데이터를 다룰 때 결측값을 표현하기 위해 사용된다다. 예를 들어, 데이터셋에 날짜 정보가 없는 경우 NaT로 표시된다.
  • 형식: NaT는 datetime64 타입의 데이터프레임에서 사용된다.

df[].dt.date

# order_time의 날짜값만 추출
order_df['order_time'].dt.date 
# 	dt: 시리즈에 있는 데이터 타임 정보에 접근할 수 있게 해줌(*.str과 유사)

# order_time의 연도값만 추출
order_df['order_time'].dt.year

# order_time의 일자값만 추출
order_df['order_time'].dt.day

# order_time의 요일값 추출
order_df['order_time'].dt.dayofweek
# 	0 ~ 6: 월 ~ 일요일


데이터 타입을 변경할 때 형식 지정하기

연도(2자리)/월/일 형식의 데이터

연도 값이 4자리가 아니라 2자리로 되어 있다. 여기서 추가로 설정을 해 주지 않으면 pandas가 자동으로 월/일/연도 순서로 날짜 값을 인식할 수도 있기 때문에, 이런 경우에는 아래 코드와 같이 to_datetime()에서 yearfirst라는 파라미터 값을 True로 설정하면 된다.

order_df['order_time'] = pd.to_datetime(order_df['order_time'], yearfirst=True)
order_df['shipping_time'] = pd.to_datetime(order_df['shipping_time'], yearfirst=True)

order_df.head()

참고로 dayfirst와 yearfirst가 모두 True인 경우에는 yearfirst에 더 우선순위를 둔다. 즉, 연도/일/월 순서로 값을 불러와진다. 

특수한 형식의 데이터

데이터 형식에 맞게 날짜와 시간을 표현하는 문자열을 만들어서 format이라는 파라미터에 넘겨줘야 한다. 이 파라미터에 날짜와 시간을 표현할 수 있는 코드인, '%Y년 %m월 %d일 %H시 %M분 %S초'이라는 값을 넘겨준다.

%Y, %m, %d 같은 건 시간과 관련된 정보가 들어갈 위치를 코드로 표현한 것으로, %Y는 연도(4자리), %m은 월(2자리), %d는 일(2자리), %H는 시간(24시간 기준), %M은 분, %S는 초를 의미한다. 

order_df['order_time'] = pd.to_datetime(order_df['order_time'],
                                                                              format='%Y년 %m월 %d일 %H시 %M분 %S초')
order_df['shipping_time'] = pd.to_datetime(order_df['shipping_time'],
                                                                                 format='%Y년 %m월 %d일 %H시 %M분 %S초')
order_df.head()

datetime을 원하는 형태로 바꿔서 표현하기

order_df['order_time'] = order_df['order_time'].dt.strftime('%d %b %Y, %I:%M %p')
order_df['shipping_time'] = order_df['shipping_time'].dt.strftime('%d %b %Y, %I:%M %p')

order_df.head()

 

datetime 값을 원하는 형태의 문자열로 바꿔서 표현하는 것도 가능하다. 예를 들어 2017-10-31 16:37:00이라는 값을 31 October 2017, 04:37PM 이런 식으로 표현해볼 수 있다. 

strftime() 함수는 날짜와 시간을 원하는 형식으로 표현하는 역할을 한다. 주의할 점은 datetime과 strftime() 사이에 dt를 써서 이 함수가 날짜와 시간 정보에 접근할 수 있도록 해 줘야 한다. 그리고 이 함수 안에 문자열로 원하는 형식을 넣으면 되고, 이때 날짜와 시간과 관련된 코드 값을 활용하면 된다. 위에서 2015년 10월 31일 20시 17분 00초 형태의 데이터를 datetime으로 바꿀 때와 비슷하다.

또 위 코드의 %d %B %Y, %I:%M %p 에선 %d는 일자, %B는 영어로 된 월 이름, %Y는 연도(4자리), %I는 시간(12시간 기준), %M은 분, 마지막으로 %p는 오전/오후(AM/PM)를 나타낸다. 물론 연도, 월, 일 같이 자주 쓰는 코드 값들은 외워 두면 좋겠지만 사실 그럴 필요는 없고 그때그때 필요한 부분을 찾아서 사용하면 된다. 예시에서 사용한 것 말고도 더 다양한 코드는 여기를 참고해볼 수 있다. 

시간대 설정하기

 서울이 오후 3시일 때 뉴욕은 오전 2시인 것처럼, 시간대 정보라는 것은 국가나 지역을 고려한 시간 정보를 의미한다. 

order_df = pd.read_csv('data/order1.csv', parse_dates=['order_time', 'shipping_time'])
order_df.head()

시간대 정보를 추가하려면 tz_localize()이라는 함수를 사용하여 원하는 시간대를 설정하면 된다. 예를 들어, order_time 컬럼에 서울의 시간대를 적용하고 싶을 때에는, 아래와 같이 Asia/Seoul이라는 값을 넣으면 된다. 이때에도 마찬가지로 컬럼과 함수 사이에 dt를 넣어줘야 오류가 나지 않는다.

order_df['order_time'].dt.tz_localize('Asia/Seoul')
0    2015-01-20 21:52:00+09:00
1    2015-02-07 22:53:00+09:00
2    2015-02-08 13:15:00+09:00
3    2015-02-24 03:25:00+09:00
4    2015-03-09 03:56:00+09:00
                ...           
95   2017-09-13 21:23:00+09:00
96   2017-10-11 14:20:00+09:00
97   2017-10-19 15:23:00+09:00
98   2018-01-01 04:04:00+09:00
99   2018-01-18 15:47:00+09:00
Name: order_time, Length: 100, dtype: datetime64[ns, Asia/Seoul]

출력 결과를 보, 시간 뒤에 +09:00이라는 값이 추가되고 아래 dtype 부분에도 Asia/Seoul이 추가되어 있는 걸 확인할 수 있다. 여기서 +09:00은 UTC(Coordinated Universal Time)이라는 국제 표준시를 사용해서 서울의 시간대를 표현하는 방법이다. 간단히 설명하자면, UTC는 영국의 그리니치 천문대를 기준점(UTC+0)으로 삼아 각 지역의 상대적인 시간대를 표현하는 방식이다. 예를 들어, UTC+3는 UTC+0보다 3시간 빠르다는 걸 의미하고, UTC-5는 UTC+0보다 5시간 느리다는 걸 의미한다. 지금 나와있는 +09:00은 UCT+9라고 보면 되고, 즉 Asia/Seoul 시간대는 UTC+0에 비해 9시간 더 빠른 시간대라고 할 수 있다.

그러면 이제 order_time과 shipping_time의 시간대를 모두 Asia/Seoul로 설정해보자.

order_df['order_time'] = order_df['order_time'].dt.tz_localize('Asia/Seoul')
order_df['shipping_time'] = order_df['shipping_time'].dt.tz_localize('Asia/Seoul')

 

그런데 이렇게 이미 설정해 둔 시간대를 다른 시간대로 바꾸려면 tz_convert()라는 함수를 쓰면 된다. 예를 들어, 뉴욕의 시간대로 바꾸려면 America/New_York이라는 값을 넘겨주면 된다.

order_df['order_time'].dt.tz_convert('America/New_York')
0    2015-01-20 07:52:00-05:00
1    2015-02-07 08:53:00-05:00
2    2015-02-07 23:15:00-05:00
3    2015-02-23 13:25:00-05:00
4    2015-03-08 14:56:00-04:00
                ...           
95   2017-09-13 08:23:00-04:00
96   2017-10-11 01:20:00-04:00
97   2017-10-19 02:23:00-04:00
98   2017-12-31 14:04:00-05:00
99   2018-01-18 01:47:00-05:00
Name: order_time, Length: 100, dtype: datetime64[ns, America/New_York]

이때 주의할 점은 아직 시간대가 설정되어 있지 않은 상태의 datetime에 바로 tz_convert()를 쓰면 오류가 난다. tz_convert()는 반드시 시간대가 설정되어 있는 데이터에만 사용 가능하기 때문이다. 반대로, 이미 시간대가 설정되어 있는 데이터에 tz_localize()를 써도 오류가 난다.

간단히 정리하면, 아직 시간대 정보가 없는 데이터에는 tz_localize()를, 이미 시간대가 설정되어 있는 데이터의 시간대를 바꿀 때에는 tz_convert()를 사용하면 됩니다.
지금은 서울과 뉴욕의 시간대 정보를 사용했는데, 아래 코드를 실행하면, 두 함수에 사용 가능한 모든 시간대 값들이 나오게 할 수 있다. 

import pytz

for tz in pytz.all_timezones:
    print(tz)