판다스에서 날짜/시간 다루기
날짜/시간 기본
하나의 날짜/시간
import pandas as pd
date = pd.to_datetime('2022-08-29')
월
date.month
요일
date.day_of_week
자료형
type(date)
시간 간격
delta = pd.to_timedelta([1, 2, 3], 'D')
date + delta
날짜로 인덱싱
데이터 만들기
index = pd.DatetimeIndex(['2014-07-04', '2014-08-04', '2015-07-04', '2015-08-04'])
data = pd.Series([100, 200, 300, 400], index=index)
일정 기간 데이터
data['2014-07-04':'2015-07-04']
특정 시점의 데이터
data['2015']
알 파벳 주가 데이터
df = pd.read_excel('GOOG.xlsx')
df.head()
Date 컬럼은 날짜, Price 컬럼은 주가(종가)
df.head()는 데이터의 앞부분을 보여줌. df.tail()은 뒷부분을 보여줌.
df.Date = pd.to_datetime(df.Date)
문자열을 날짜 시간 형식으로 변환
df.set_index('Date', inplace=True)
Date 컬럼을 인덱스(행 이름)으로 변환
inplace=True: 원본을 변환, 생략하면 Date가 index로 설정된 새로운 데이터를 만듦
df.loc['2015-01-02':'2015-01-07']
인덱스를 이용해 특정 기간의 데이터를 뽑아냄
정렬 & 시각화
df.sort_index(inplace=True)
인덱스를 순서대로(오름차순) 정렬
df.sort_index(ascending=False)
인덱스를 역순(내림차순) 정렬
df.Price.plot()
시각화
변화량 구하기
df.Price.diff()
차분(differencing): 전일과 차이 구하기
점점 더 폭이 커지는 이유는 주가가 올라서 같은 비율의 변동도 가격 차이가 더 커지기 때문
df.Price.pct_change()
전일과 차이의 비율 구하기
대부분의 경우 일정 비율 내에서 변동하는 것을 볼 수 있음
2020년 초 주가의 변동성이 커진 것을 볼 수 있음
일정 간격으로 데이터 뽑기
df.Price.asfreq('M')
asfreq는 일정한 간격(frequency)으로 데이터를 뽑아냄
.asfreq('M')은 매월 말일 주가
그래프 겹쳐 그리기
.plot을 같은 셀에서 실행하면 그래프가 겹쳐서 그려짐
df.Price.plot(alpha=0.3)
df.Price.asfreq('BA').plot(color='red', style='o-')
빈 데이터 채우기
2016-12-31의 전후 날짜 데이터
df.Price['2016-12-30':'2017-01-03']
2016년 12월 31일~2017년 1월 2일까지 비어있음
해당 날짜의 데이터가 비어있을 경우 이전(forward)의 데이터로 채우기
df.Price.asfreq('A', method='ffill')
해당 날짜의 데이터가 비어있을 경우 이후(back)의 데이터로 채우기
df.Price.asfreq('A', method='bfill')
리샘플 resample
특정 시점 간격으로 데이터를 종합 아래는 가격을 매년 초(AS)를 기준으로 잘라, 연 평균 가격을 계산
df.Price.resample('AS').mean()
이동 평균
rolling = df.Price.rolling(365, center=True)
rolling을 이용해서 매 365일 간격의 데이터를 묶음
이동 평균은 평균을 마지막 날짜에 표시하므로, 그래프를 그리면 뒤로 밀려서 보임.
center=True를 하면 중심에 맞춰 그림
rolling.mean().plot()
각 묶음별로 평균
자전거 대여소 데이터
미국 시애틀 Fremont 브릿지 자전거 대여소 데이터
data = pd.read_csv(
'bicycle.csv',
index_col='Date', # Date 컬럼을 인덱스로 지정
parse_dates=True) # 자동으로 날짜 처리
data.head()
시각화
편의를 위해 컬럼 이름 변경
data.columns = ['Total', 'East', 'West']
시각화
data.plot()
주 단위 합계 시각화
data.resample('W').sum().plot()
이동 평균
일단위 합계의 30일 이동 평균
daily = data.resample('D').sum()
daily.rolling(30, center=True).mean().plot()
가까운 날짜에 더 많은 가중치를 주고, 먼 날짜에 적은 가중치를 주는 방식
roll = daily.rolling(30, center=True, win_type='gaussian')
roll.sum(std=10).plot()
시간대별 평균
시간별(data.index.hour)로 데이터를 모아(groupby) 평균
by_time = data.groupby(data.index.hour).mean()
by_time.plot()
가로 눈금을 3시간 간격으로
import numpy as np
hourly_ticks = 3 * np.arange(8)
by_time.plot(xticks=hourly_ticks, style=[':', '--', '-'])
요일별 평균
by_weekday = data.groupby(data.index.dayofweek).mean()
by_weekday.index = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
by_weekday.plot()
주중과 주말의 비교
주중과 주말, 시간대별로 나누어 평균
import numpy as np
weekend = np.where(data.index.weekday < 5, 'Weekday', 'Weekend')
by_time = data.groupby([weekend, data.index.hour]).mean()
비교 시각화
by_time.loc['Weekday'].plot(xticks=hourly_ticks)
by_time.loc['Weekend'].plot(xticks=hourly_ticks)
하나의 그래프에 합쳐 그리기
하나의 셀에 실행
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, figsize=(14, 5))
by_time.loc['Weekday'].plot(ax=ax[0], title='Weekdays', xticks=hourly_ticks)
by_time.loc['Weekend'].plot(ax=ax[1], title='Weekends', xticks=hourly_ticks)