[Pandas] .dt accessor
Pandas dt, Pandas .dt, Pandas dt accessor, datetime accessor
정의
Series.dt 는 datetime Series 의 각 구성요소 (년/월/일/시/분/요일 등) 에 벡터로 접근하는 accessor. str 의 datetime 버전.
s.dt.year
s.dt.month
s.dt.day
s.dt.hour
s.dt.weekday
구성요소 분류 시각화
flowchart LR
DT["datetime Series\n.dt accessor"] --> DATE["날짜 계열"]
DT --> TIME["시간 계열"]
DT --> PERIOD["기간/기타"]
DATE --> D1["dt.year / dt.month / dt.day"]
DATE --> D2["dt.dayofweek / dt.day_name()"]
DATE --> D3["dt.quarter / dt.dayofyear"]
DATE --> D4["dt.is_month_end / dt.is_month_start"]
TIME --> T1["dt.hour / dt.minute / dt.second"]
TIME --> T2["dt.floor() / dt.ceil() / dt.round()"]
TIME --> T3["dt.tz_localize() / dt.tz_convert()"]
PERIOD --> P1["dt.to_period() - 월/분기 집계"]
PERIOD --> P2["dt.days / dt.total_seconds() - Timedelta"]
기본 컴포넌트
| 속성 | 의미 |
|---|---|
dt.year, dt.month, dt.day | 년/월/일 |
dt.hour, dt.minute, dt.second | 시/분/초 |
dt.dayofweek / dt.weekday | 요일 (0=월) |
dt.day_name() | 요일 이름 (‘Monday’) |
dt.month_name() | 월 이름 (‘January’) |
dt.quarter | 분기 (1-4) |
dt.dayofyear | 그 해의 몇일째 |
dt.week, dt.isocalendar() | 주차 |
dt.is_month_end, dt.is_month_start | 월말/월초 boolean |
dt.days_in_month | 그 달의 일 수 |
사용
python
import pandas as pd
s = pd.to_datetime(['2024-01-15', '2024-03-30', '2024-12-25'])
s = pd.Series(s)
print('year :', s.dt.year.tolist())
print('month:', s.dt.month.tolist())
print('day :', s.dt.day.tolist())
print('weekday:', s.dt.day_name().tolist())
print('quarter:', s.dt.quarter.tolist()) 결과
year : [2024, 2024, 2024]
month: [1, 3, 12]
day : [15, 30, 25]
weekday: ['Monday', 'Saturday', 'Wednesday']
quarter: [1, 1, 4]포맷 변환
s.dt.strftime('%Y-%m-%d') # 문자열로
s.dt.strftime('%Y년 %m월 %d일 (%A)')
s.dt.normalize() # 시간 0으로 (날짜만)
s.dt.floor('h') # 시간 단위 내림
s.dt.ceil('h') # 올림
s.dt.round('15min') # 반올림
timezone
s.dt.tz # 현재 timezone
s.dt.tz_localize('Asia/Seoul') # naive → aware
s.dt.tz_convert('UTC') # 다른 timezone 으로
s.dt.tz_convert('America/New_York') # 시간대 변환
IMPORTANT
tz_localize 와 tz_convert 는 전혀 다른 연산이다. tz_localize 는 timezone 정보 없는 naive datetime 에 timezone 을 부여, tz_convert 는 이미 timezone 이 있는 aware datetime 을 변환. naive 에 tz_convert 를 부르면 TypeError.
Timedelta 의 dt
td = pd.to_timedelta(['1 days 02:30:00', '2 days 05:00:00'])
td = pd.Series(td)
td.dt.days # [1, 2]
td.dt.seconds # 9000, 18000 (하루 안의 초)
td.dt.total_seconds() # 전체 초
Period accessor
# PeriodIndex 로 변환하면 .dt.start_time, .dt.end_time 등 사용 가능
s_period = s.dt.to_period('M') # monthly Period
s_period.dt.start_time # 각 월의 첫째 날 Timestamp
s_period.dt.end_time # 각 월의 마지막 날 Timestamp
s_period.dt.quarter # 분기 (Period 용)
자주 쓰는 패턴
월별 집계
df['month'] = df['created_at'].dt.to_period('M') # PeriodIndex (2024-01, ...)
monthly = df.groupby('month')['amount'].sum()
요일별 트렌드
df['weekday'] = df['date'].dt.day_name()
df.groupby('weekday')['orders'].mean()
영업일 / 주말
df['is_weekend'] = df['date'].dt.dayofweek >= 5
df['is_weekday'] = df['date'].dt.dayofweek < 5
datetime 차이
df['days_since_signup'] = (pd.Timestamp.today() - df['signup_date']).dt.days
df['age_years'] = (pd.Timestamp.today() - df['birth_date']).dt.days / 365.25
시간대별 분석
python
import pandas as pd
df = pd.DataFrame({
'ts': pd.date_range('2024-01-01', periods=6, freq='4h'),
'val': [10, 20, 5, 30, 15, 25],
})
df['hour_bucket'] = df['ts'].dt.hour // 6 * 6 # 0,6,12,18 구간
print(df.groupby('hour_bucket')['val'].sum()) 결과
hour_bucket
0 30
6 35
12 40
Name: val, dtype: int64날짜 범위 필터
# 특정 월만
mask = (df['date'].dt.year == 2024) & (df['date'].dt.month == 3)
df[mask]
# 특정 요일
df[df['date'].dt.dayofweek == 0] # 월요일만
# 영업 시간 내
df[(df['ts'].dt.hour >= 9) & (df['ts'].dt.hour < 18)]
resample 과 결합
# 일별 집계 (dt accessor + resample)
df.set_index('date').resample('D')['amount'].sum()
# 주별 집계
df.set_index('date').resample('W')['amount'].mean()
자세히는 Pandas resample.
성능 팁
# dt accessor 는 벡터 연산, 루프보다 훨씬 빠름
# ❌ 느림
df['year'] = df['date'].apply(lambda x: x.year)
# ✓ 빠름
df['year'] = df['date'].dt.year
# datetime64 dtype 이면 dt 사용 가능, object 이면 to_datetime 먼저
df['date'] = pd.to_datetime(df['date_str'])
df['year'] = df['date'].dt.year
함정
1. dt 가 안 되는 경우
s = pd.Series(['2024-01-15', '2024-02-20'])
s.dt.year # AttributeError, str 이라서
# 먼저 변환
pd.to_datetime(s).dt.year
2. tz-aware vs naive 비교
naive.tz_localize('UTC') > aware # ✓
naive > aware # TypeError 가능
3. dayofweek 의 시작 (월요일 = 0)
s.dt.dayofweek # 0=Mon ... 6=Sun
s.dt.weekday # 같음
# Python 의 datetime.weekday() 과 동일
ISO 표준 (1=Mon) 은 s.dt.isocalendar().day.
4. dt.week 는 deprecated
s.dt.week # DeprecationWarning (pandas 1.1+)
# 대신 사용
s.dt.isocalendar().week
WARNING
dt.week 와 dt.weekofyear 는 pandas 1.1 에서 deprecated, 2.x 에서 제거됐다. dt.isocalendar().week 를 사용할 것.
관련 위키
이 글의 용어 (5개)
- [Pandas] .str accessorpandas
- 정의 는 Series 의 각 문자열 원소에 벡터화된 문자열 메서드 를 적용하는 accessor. Python 의 거의 모든 메서드를 NaN-aware 로 제공한다. accesso…
- [Pandas] date_range / Timestamppandas
- 정의 - : 정해진 시작/끝/간격으로 datetime 시퀀스 생성 - : pandas 의 단일 datetime 객체 - : 시간 차이 사용 상황 | 상황 | 사용 API | |:…
- [Pandas] groupbypandas
- 정의 는 데이터를 그룹으로 나누고 (split), 각 그룹에 함수를 적용 (apply), 결과를 합쳐 (combine) 새 DataFrame 으로 만드는 split-apply-c…
- [Pandas] resamplepandas
- 정의 는 시계열 데이터를 다른 빈도 (월별, 일별, 시간별 등) 로 재샘플링하면서 집계한다. 의 시계열 버전. DatetimeIndex (또는 으로 datetime 컬럼) 이 필…
- [Pandas] to_datetimepandas
- 정의 는 문자열, 정수, dict, DataFrame 컬럼을 타입으로 변환한다. pandas 시계열 작업의 출발점. 사용 상황 - CSV 로드 후 날짜 컬럼이 (문자열) 로 읽혔…
💬 댓글