데이터 분석/ADP 자격증 공부

[ADP 실기] Pandas to_datetime 관련 함수 정리

나르시스트 2026. 4. 6. 22:19

*날짜 데이터로 변환

df[‘date’].astype(‘datetime64[ns]’) # 날짜 데이터로 변환
df[‘date’] = pd.to_datetime(df[‘date’])

 

df[‘date_str’].dt.time.astype(str) # 문자열로 변환
df2.strftime(‘%y년 %m-%d %H:%M’) # 날짜 형태 변환
df2.replace(year=2022, minute=2) # 년도, 분 변경

 

d3 = dt.datetime.combine(date_only, time_only)

 

df['날짜'] = df['(년-월-일:시)'].str.split(':').str[0]
df['시'] = df['(년-월-일:시)'].str.split(':').str[1].astype(int)

df['날짜'] = pd.to_datetime(df['날짜'], format='%Y-%m-%d') + pd.to_timedelta(df['시'].where(df['시'] < 24, 0), unit='h')
df.loc[df['시'] == 24, '날짜'] += pd.Timedelta(days=1)
df.head()

 

*월-일 가져오기

df['대여일자'].dt.strftime('%m-%d') == '06-07'
mask = (df['대여일자'].dt.strftime('%m-%d') >= '06-07') & (df['대여일자'].dt.strftime('%m-%d') <= '07-10')
filtered_df = df[mask]

 

*매년 5월의 open가격의 평균값을 데이터 프레임으로

target = df.groupby(df['Date'].dt.strftime('%Y-%m')).mean()
answer = target[target['Date'].dt.month == 5]['Open']

*오늘 날짜, 현재 시간 가져오기

import pandas as pd

current_time = pd.Timestamp.now()
today_date = pd.Timestamp.now().normalize()  # 날짜만
current_time_only = pd.Timestamp.now().time()  # 시간만

current_time_utc = pd.Timestamp.now(tz='UTC')  # UTC 시간
current_time_utc = pd.to_datetime('now', utc=True)

utc_time = local_time.tz_localize('Asia/Seoul').tz_convert('UTC')  # 서울 → UTC
utc_time = local_time.tz_localize(None).tz_convert('UTC')  # 로컬 → UTC

*기본 계산

import pandas as pd

df = pd.DataFrame({'date': ['2023-01-01', '2024-05-15', '2024-12-31']})
df['date'] = pd.to_datetime(df['date'])

df = pd.DataFrame({'date': ['01/02/2023', '15-May-2024', '2024/12/31', 'invalid']})
df['date'] = pd.to_datetime(df['date'], format='%d-%b-%Y', errors='coerce')  # format="%Y-%m-%d" or format = "%d/%m/%Y %H:%M"

df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day

df['nsd'] = df['date'].dt.minute + df['date'].dt.hour * 60 # 분으로 변환

df_2024 = df[df['date'].dt.year == 2024]

#help(df['date'].dt)
df['weekday'] = df['date'].dt.weekday
df['date'].dt.day_of_week  # Monday=0, Sunday=6
(df['date'].dt.day_of_week + 1) % 7  # Sunday=0으로
df['weekday'] = df['date'].dt.day_name()

# 7일 더하기
df['date_after_7_months'] = df['date'] + pd.DateOffset(months=7)
expected_diff = pd.Timedelta(hours=1)

timestamps = [1609459200, 1625097600, 1672531200]
df['date_from_timestamp'] = pd.to_datetime(timestamps, unit='s')
print(df)

# 날짜 인덱스 생성
dates = pd.date_range("2024-01-01", periods=10, freq="D")  # A(년), M(월), D(일), T(분), S(초), Q(분기), W(주)
df = pd.DataFrame({"value": range(10)}, index=dates)
print(df)

# 특정 연도의 데이터 필터링
df_2024 = df['2024']
print(df_2024)

 

*(year + 100) 계산 날짜로 다시 datetime 생성

df.loc[df['Yr_Mo_Dy'].dt.year >= 2061, 'Yr_Mo_Dy'] -= pd.DateOffset(years=100)
def fix_century(x):
    
    year = x.year - 100 if x.year >= 2061 else x.year  #apply에서는 단일 값(Timestamp)이라 dt 안 씀
    return pd.Timestamp(year, x.month, x.day)

df['Yr_Mo_Dy'] = df['Yr_Mo_Dy'].apply(fix_century)
df.head(4)

*연도, 월별 평균 값 계산

df.groupby(df['Yr_Mo_Dy'].dt.year).mean()
df.groupby(df['Yr_Mo_Dy'].dt.to_period('M')).mean()

*시계열 데이터 결측치 처리

모든 결측치는 컬럼기준 직전의 값으로 대체하고 첫 번째 행에 결측치가 있을 경우 뒤에 있는 값으로 대체

df.fillna(method='ffill').fillna(method='bfill')

 

*(24시 → 0시) 변경하고, 날짜 1일 더하기

import pandas as pd

def handle_24_hour_format(date_str):

    if isinstance(date_str, str):
        date_part, hour_part = date_str.split(':')

        if hour_part == '24':
            date = pd.to_datetime(date_part)
            return date + pd.DateOffset(days=1)  # pd.to_datetime(date_ + " " + '00:00:00') + pd.Timedelta(days=1)
        else:
            return pd.to_datetime(date_str, format='%Y-%m-%d:%H')
    
    return date_str

df['(년-월-일:시)'] = df['(년-월-일:시)'].apply(handle_24_hour_format)
df.head(20)

 

*시간이 연속적으로 존재하며 결측치가 없는지 확인

check = len(df['(년-월-일:시)'].diff().unique())  # 2일 경우 결측치 없음
import pandas as pd

df = df.sort_values(by='timestamp')

df['time_diff'] = df['timestamp'].diff()

expected_diff = pd.Timedelta(hours=1)
if (df['time_diff'].dropna() != expected_diff).any():
    print("시간이 연속적이지 않음")
else:
    print("시간이 연속적임")

# 결측치 확인
if df['timestamp'].isnull().any():
    print("결측치가 있음")
else:
    print("결측치가 없음")

*누락된 시간 찾기

df = df.set_index('날짜컬럼').asfreq('1H')  # 1시간 간격으로 딱 맞춤 (누락 시간은 NaN)
missing = df[df.isnull().any(axis=1)].index
import pandas as pd

data = {'timestamp': ['2023-10-01 00:00', '2023-10-01 02:00', '2023-10-01 03:00', '2023-10-01 05:00'], 'value': [10, 20, 30, 50]}
df = pd.DataFrame(data)

df['timestamp'] = pd.to_datetime(df['timestamp'])

full_time_range = pd.date_range(start=df['timestamp'].min(), end=df['timestamp'].max(), freq='H')

missing_times = full_time_range.difference(df['timestamp'])

print("누락된 시간:")
print(missing_times)

 

*누락된 시간을 찾고, 데이터를 앞/뒤 평균으로 대체

import pandas as pd

data = {'timestamp': ['2023-10-01 00:00', '2023-10-01 02:00', '2023-10-01 03:00', '2023-10-01 05:00'], 'value': [10, 20, 30, 50]}
df = pd.DataFrame(data)

df['timestamp'] = pd.to_datetime(df['timestamp'])

# 전체 시간 범위 생성 (1시간 간격으로 연속된 시간)
full_time_range = pd.date_range(start=df['timestamp'].min(), end=df['timestamp'].max(), freq='H')

# reindex를 사용하여 누락된 시간을 추가
df = df.set_index('timestamp').reindex(full_time_range)

# 결측값을 바로 전후 값의 평균으로 채우기 (선형 보간)
df['value'] = df['value'].interpolate(method='linear')

# 인덱스를 다시 'timestamp'로 설정
df = df.rename_axis('timestamp').reset_index()

 

*오전 10시와 오후 10시(22시)의 PM10의 평균값

df.groupby(df['(년-월-일:시)'].dt.hour).mean().iloc[[10,22],[0]]

 

*데이터를 주단위로 뽑아서 최소,최대 평균, 표준표차 (p.402)

df.groupby(df['날짜'].dt.to_period('W'))[df.select_dtypes(include='number').columns].agg(['min', 'max', 'mean', 'std'])
df.resample('W').agg(['min','max','mean','std'])

*특정 날짜 이후 데이터 출력

# Channel 데이터중 2021-10-03일 이후 각 채널의 처음 기록 됐던 구독자 수(subcnt)를 출력
filtered_channel = channel[channel['ct'] > '2021-10-03']
first_subcnt_per_channel = filtered_channel.groupby('channelname').first()['subcnt']

 

*videoname별 가장 최신 테이터 가져오기

video.sort_values('ct').groupby('videoname').tail(1)

 

*videoname별 시작 날짜

episode_data.groupby('videoname')['ct'].min().reset_index()

 

*각 에피소드별 viewcnt의 증가량

q19 = video[(video['ct'] >= '2021-11-01 00:00:00') & (video['ct'] <= '2021-11-01 15:00:00')]

q19_2 = q19.groupby('videoname')['viewcnt'].agg(['min','max']).reset_index()
q19_2['result'] = q19_2['max'] - q19_2['min']
q19 ['viewcnt_diff'] = q19 .groupby('videoname')['viewcnt'].diff()

# NaN 값 제거 (첫 번째 행)
viewcnt_diff_data = q19 .dropna(subset=['viewcnt_diff'])

 

*수집간격이 5분 이하, 20분이상인 데이터 구간( 해당 시점 전,후) 의 시각

gongbeom_ep1_data['time_diff'] = gongbeom_ep1_data['ct'].diff().dt.total_seconds() / 60  # 분 단위로 차이를 계산

# 수집간격이 5분 이하 또는 20분 이상인 데이터 필터링
irregular_intervals = gongbeom_ep1_data[(gongbeom_ep1_data['time_diff'] <= 5) | (gongbeom_ep1_data['time_diff'] >= 20)]

# 해당 시점 전, 후의 시각 출력
irregular_times = irregular_intervals[['ct', 'time_diff']]

 

*특정 시간에 해당하는 날짜 가져와서 해당 날짜의 특정 시간 데이터 가져오기

ep_upload_dates = video.groupby('videoname')['ct'].min().dt.date
print(ep_upload_dates)

results = []
for ep_name, upload_date in ep_upload_dates.items():
    results.append(video[(video['videoname'] == ep_name) & (video['ct'].dt.date == upload_date) & (video['ct'].dt.hour == 21) & (video['ct'].dt.minute == 00)])  
    
# 여러 개의 DataFrame을 하나로 합쳐서 인덱스를 정리한 새로운 DataFrame
result_df = pd.concat(results).reset_index(drop=True)
print(result_df)

result = result_df[['viewcnt', 'ct', 'videoname']].sort_values(by='viewcnt', ascending=False).reset_index(drop=True)
print(result)

*datetime 라이브러리

from datetime import datetime
datetime.today()
datetime.today().year
datetime.strptime('%Y-%m-%d %H:%M:%S')

datetime2 = datetime + timedelta(days=100)  # weeks, hours, minutes, seconds 등

from datetime import timedelta
from dateutil.relativedelta import relativedelta

df['date_plus_7'] = df['date'] + timedelta(days=7)
df['date_plus_2months'] = df['date'] + relativedelta(months=2)

*데이터프레임 합치기