[Pandas 기초] 시계열 데이터(timeseries), Timestamp와 Period
업데이트:
1. 시계열 데이터
판다스에서 시계열 자료형은 Timestamp와 Period라는 두가지 타입이 있다.
Timestamp 자료형은
to_datetime()
함수로 생성가능하며 날짜형태의 자료형을 시계열 타입으로 변환해준다.
Period 자료형은 Timestamp(datetime)객체를 다시 기간에 따른 자료형으로 이용하고자 할때 사용한다.
2. 자료형의 시계열 객체 변환 : to_datetime()
, to_period()
먼저 데이터를 하나 불러와보자.
import pandas as pd
df = pd.read_csv("~/stock-data.csv")
df.head()
Date | Close | Start | High | Low | Volume | |
---|---|---|---|---|---|---|
0 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 |
1 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 |
2 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 |
3 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 |
4 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 |
그리고 데이터 요약정보를 확인한다.
df.info()
[Output]
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 6 columns):
Date 20 non-null object
Close 20 non-null int64
Start 20 non-null int64
High 20 non-null int64
Low 20 non-null int64
Volume 20 non-null int64
dtypes: int64(5), object(1)
memory usage: 1.0+ KB
현재 날짜를 나타내는 Date컬럼은 문자형(object)임을 알 수 있다.
to_datetime()
함수를 이용해서 Date컬럼을 시계열 객체(Timestamp)로 변환해보자.
df['new_Date'] = pd.to_datetime(df['Date'])
print(df.head())
print('\n')
print(df.info())
print('\n')
print(type(df['new_Date'][0]))
[Output]
Date Close Start High Low Volume new_Date
0 2018-07-02 10100 10850 10900 10000 137977 2018-07-02
1 2018-06-29 10700 10550 10900 9990 170253 2018-06-29
2 2018-06-28 10400 10900 10950 10150 155769 2018-06-28
3 2018-06-27 10900 10800 11050 10500 133548 2018-06-27
4 2018-06-26 10800 10900 11000 10700 63039 2018-06-26
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 7 columns):
Date 20 non-null object
Close 20 non-null int64
Start 20 non-null int64
High 20 non-null int64
Low 20 non-null int64
Volume 20 non-null int64
new_Date 20 non-null datetime64[ns]
dtypes: datetime64[ns](1), int64(5), object(1)
memory usage: 1.2+ KB
None
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
기존 Date열 지우고 new_Date를 인덱스로 지정해주자.
df.drop('Date', axis = 1, inplace=True)
df.set_index('new_Date', inplace=True)
print(df.head())
print('\n')
print(df.info())
[Output]
Close Start High Low Volume
new_Date
2018-07-02 10100 10850 10900 10000 137977
2018-06-29 10700 10550 10900 9990 170253
2018-06-28 10400 10900 10950 10150 155769
2018-06-27 10900 10800 11050 10500 133548
2018-06-26 10800 10900 11000 10700 63039
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 20 entries, 2018-07-02 to 2018-06-01
Data columns (total 5 columns):
Close 20 non-null int64
Start 20 non-null int64
High 20 non-null int64
Low 20 non-null int64
Volume 20 non-null int64
dtypes: int64(5)
memory usage: 960.0 bytes
None
데이터요약정보(info)를 확인해보면, 인덱스가 DatetimeIndex
임을 알 수 있고 2018년07월02일에서 2018년06월01일 사이에 20개의 날짜가 존재하는 것을 알 수 있다.
이번에는 Timestamp와 Period의 차이를 알아보자.
# Timestamp를 Period로 변환
dates = ['2019-01-01','2020-03-01','2021-06-01']
ts_dates = pd.to_datetime(dates)
print(ts_dates)
print('\n')
# Timestamp를 Period변환
pr_day = ts_dates.to_period(freq='D') #1일의 기간
print(pr_day)
pr_month = ts_dates.to_period(freq='M') #1개월의 기간
print(pr_month)
pr_year = ts_dates.to_period(freq='A') #1년의 기간
print(pr_year)
[Output]
DatetimeIndex(['2019-01-01', '2020-03-01', '2021-06-01'], dtype='datetime64[ns]', freq=None)
PeriodIndex(['2019-01-01', '2020-03-01', '2021-06-01'], dtype='period[D]', freq='D')
PeriodIndex(['2019-01', '2020-03', '2021-06'], dtype='period[M]', freq='M')
PeriodIndex(['2019', '2020', '2021'], dtype='period[A-DEC]', freq='A-DEC')
보는 바와 같이 Period객체는 to_period(freq='기간인수')
를 통해 datetime변수에 대해 어떤 기간에 따른 자료형을 생성하고자 할때 주로 활용된다. 이는 바로 아무 자료형에나 사용할 수 없고 datetime타입에 대해 적용가능하다.
3. 시계열 데이터 만들기 : date_range()
, period_range()
3-1. Timestamp 배열
Timestamp를 배열하는 date_range()
함수는 파이선의 내장함수인 range()함수와 비슷한 개념이다.
다음과 같이 옵션을 설정해주면 원하는 Timestamp(datetime)배열을 얻을 수 있다.
import pandas as pd
ts_ms = pd.date_range(start = '2019-01-01', # 날짜 범위 시작
end = None, # 날짜 범위 끝
periods = 6, # 생성할 Timestamp 개수
freq = 'MS', # 시간 간격(MS : 월의 시작일)
tz = 'Asia/Seoul') # 시간대(timezone)
print(ts_ms)
[Output]
DatetimeIndex(['2019-01-01 00:00:00+09:00', '2019-02-01 00:00:00+09:00',
'2019-03-01 00:00:00+09:00', '2019-04-01 00:00:00+09:00',
'2019-05-01 00:00:00+09:00', '2019-06-01 00:00:00+09:00'],
dtype='datetime64[ns, Asia/Seoul]', freq='MS')
2019년01월01일부터 월의 시작일 간격으로 6개를 생성했다.
이렇게 freq=
옵션을 통해 유연한 배열의 생성이 가능하다.
이번에는 월 간격, 월의 마지막 날 기준(freq='M'
)으로 생성하기 위한 옵션이다.
ts_me = pd.date_range('2019-01-01',
periods = 6,
freq = 'M', #1개월 간격, 월의 마지막날 기준
tz = 'Asia/Seoul')
print(ts_me)
print('\n')
ts_3m = pd.date_range('2019-01-01',
periods = 6,
freq = '3M', # 3개월 간격, 월의 마지막 날 기준
tz = 'Asia/Seoul')
print(ts_3m)
print('\n')
[Output]
DatetimeIndex(['2019-01-31 00:00:00+09:00', '2019-02-28 00:00:00+09:00',
'2019-03-31 00:00:00+09:00', '2019-04-30 00:00:00+09:00',
'2019-05-31 00:00:00+09:00', '2019-06-30 00:00:00+09:00'],
dtype='datetime64[ns, Asia/Seoul]', freq='M')
DatetimeIndex(['2019-01-31 00:00:00+09:00', '2019-04-30 00:00:00+09:00',
'2019-07-31 00:00:00+09:00', '2019-10-31 00:00:00+09:00',
'2020-01-31 00:00:00+09:00', '2020-04-30 00:00:00+09:00'],
dtype='datetime64[ns, Asia/Seoul]', freq='3M')
3-2. Period 배열
마찬가지로 Period 배열을 생성해주는 period_range()
함수를 알아보자.
Timestamp와의 차이는 Period는 기간을 나타내는 자료형 이므로, 배열을 적용할때 freq=
옵션은 기간의 단위를 의미한다는 점이다.
# 1개월 길이
pr_m = pd.period_range(start = '2019-01-01',
end = None,
periods = 3,
freq = 'M')
print(pr_m)
print('\n')
# 1시간 길이
pr_h = pd.period_range(start = '2019-01-01',
end = None,
periods = 3,
freq = 'H')
print(pr_h)
print('\n')
# 2시간 길이
pr_2h = pd.period_range(start = '2019-01-01',
end = None,
periods = 3,
freq = '2H')
print(pr_2h)
[Output]
PeriodIndex(['2019-01', '2019-02', '2019-03'], dtype='period[M]', freq='M')
PeriodIndex(['2019-01-01 00:00', '2019-01-01 01:00', '2019-01-01 02:00'], dtype='period[H]', freq='H')
PeriodIndex(['2019-01-01 00:00', '2019-01-01 02:00', '2019-01-01 04:00'], dtype='period[2H]', freq='2H')
4. 시계열데이터 활용
4-1. 날짜 데이터 분리 : dt.year
, dt.month
, dt.day
다시 처음으로 돌아와 데이터를 불러와서 Date변수를 날짜변수로 변환한 컬럼을 추가한 부분으로 돌아오자.
import pandas as pd
df = pd.read_csv("~/stock-data.csv")
df['new_Date'] = pd.to_datetime(df['Date']) #Date를 날짜변수로 변환
df.head()
Date | Close | Start | High | Low | Volume | new_Date | |
---|---|---|---|---|---|---|---|
0 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 | 2018-07-02 |
1 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 | 2018-06-29 |
2 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 | 2018-06-28 |
3 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 | 2018-06-27 |
4 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 | 2018-06-26 |
datetime타입에 적용하는 dt
속성을 활용해 연(year), 월(month), 일(day)을 날짜에서 분리해보자.
df['Year'] = df['new_Date'].dt.year
df['Month'] = df['new_Date'].dt.month
df['Day'] = df['new_Date'].dt.day
df.head()
Date | Close | Start | High | Low | Volume | new_Date | Year | Month | Day | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 | 2018-07-02 | 2018 | 7 | 2 |
1 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 | 2018-06-29 | 2018 | 6 | 29 |
2 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 | 2018-06-28 | 2018 | 6 | 28 |
3 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 | 2018-06-27 | 2018 | 6 | 27 |
4 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 | 2018-06-26 | 2018 | 6 | 26 |
이번에는 아까 배운 to_period()
함수를 이용해 표기를 변경해보자
df['Date_yr'] = df['new_Date'].dt.to_period(freq = 'A') # 연도까지
df['Date_m'] = df['new_Date'].dt.to_period(freq = 'M') # 연월까지
df.head()
Date | Close | Start | High | Low | Volume | new_Date | Year | Month | Day | Date_yr | Date_m | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 | 2018-07-02 | 2018 | 7 | 2 | 2018 | 2018-07 |
1 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 | 2018-06-29 | 2018 | 6 | 29 | 2018 | 2018-06 |
2 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 | 2018-06-28 | 2018 | 6 | 28 | 2018 | 2018-06 |
3 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 | 2018-06-27 | 2018 | 6 | 27 | 2018 | 2018-06 |
4 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 | 2018-06-26 | 2018 | 6 | 26 | 2018 | 2018-06 |
4-2. 날짜 인덱스 활용
이번에는 시계열 타입을 인덱스로 두고 활용하는 방법에 대해 알아보자.
import pandas as pd
df = pd.read_csv("~/stock-data.csv")
df['new_Date'] = pd.to_datetime(df['Date']) #Date를 날짜변수로 변환
df.set_index('new_Date',inplace=True) #인덱스로 지정
df.head()
Date | Close | Start | High | Low | Volume | |
---|---|---|---|---|---|---|
new_Date | ||||||
2018-07-02 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 |
2018-06-29 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 |
2018-06-28 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 |
2018-06-27 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 |
2018-06-26 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 |
시계열 타입이 인덱스인 경우에는, 꼭 인덱스이름과 같지 않아도 특정 연도, 연도(2018), 연월(2018-07), 연월일(2018-07-02) 등과 같이 인덱싱이 가능하다.
print(df.loc['2018-06']) # 6월에 해당하는 row 인덱싱
print('\n')
print(df['2018-07']) # 7월에 해당하는 row 인덱싱
print('\n')
print(df['2018-06-25' : '2018-06-20']) # 해당기간의 인덱싱
[Output]
Date Close Start High Low Volume
new_Date
2018-06-29 2018-06-29 10700 10550 10900 9990 170253
2018-06-28 2018-06-28 10400 10900 10950 10150 155769
2018-06-27 2018-06-27 10900 10800 11050 10500 133548
2018-06-26 2018-06-26 10800 10900 11000 10700 63039
2018-06-25 2018-06-25 11150 11400 11450 11000 55519
2018-06-22 2018-06-22 11300 11250 11450 10750 134805
2018-06-21 2018-06-21 11200 11350 11750 11200 133002
2018-06-20 2018-06-20 11550 11200 11600 10900 308596
2018-06-19 2018-06-19 11300 11850 11950 11300 180656
2018-06-18 2018-06-18 12000 13400 13400 12000 309787
2018-06-15 2018-06-15 13400 13600 13600 12900 201376
2018-06-14 2018-06-14 13450 13200 13700 13150 347451
2018-06-12 2018-06-12 13200 12200 13300 12050 558148
2018-06-11 2018-06-11 11950 12000 12250 11950 62293
2018-06-08 2018-06-08 11950 11950 12200 11800 59258
2018-06-07 2018-06-07 11950 12200 12300 11900 49088
2018-06-05 2018-06-05 12150 11800 12250 11800 42485
2018-06-04 2018-06-04 11900 11900 12200 11700 25171
2018-06-01 2018-06-01 11900 11800 12100 11750 32062
Date Close Start High Low Volume
new_Date
2018-07-02 2018-07-02 10100 10850 10900 10000 137977
Date Close Start High Low Volume
new_Date
2018-06-25 2018-06-25 11150 11400 11450 11000 55519
2018-06-22 2018-06-22 11300 11250 11450 10750 134805
2018-06-21 2018-06-21 11200 11350 11750 11200 133002
2018-06-20 2018-06-20 11550 11200 11600 10900 308596
4-3. 오늘과의 날짜 차이 열 만들기
오늘 날짜를 2019-07-18이라고 하고 경과일을 구해보자.
today = pd.to_datetime('2019-07-18')
df['time_delta'] = today - df.index
df.head()
Date | Close | Start | High | Low | Volume | time_delta | |
---|---|---|---|---|---|---|---|
new_Date | |||||||
2018-07-02 | 2018-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 | 381 days |
2018-06-29 | 2018-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 | 384 days |
2018-06-28 | 2018-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 | 385 days |
2018-06-27 | 2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 | 386 days |
2018-06-26 | 2018-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 | 387 days |
차이값을 보면 알아서 days가 붙어 표기해주는 것을 알 수 있다.
4-4. 오늘날짜 : datetime
모듈
판다스에 내장된 시계열 자료형들 외에도 datetime이라는 모듈이 존재한다. 이 모듈의 datetime.now()
함수로 오늘 날짜를 초단위까지 구할 수 있는 재밌는 기능이다.
import datetime
now = datetime.datetime.now()
print(now)
print(now.year)
print(now.month)
print(now.day)
print(now.hour)
print(now.minute)
print(now.second)
print('%s-%s-%s' % (now.year, now.month, now.day))
[Output]
2019-08-19 17:58:52.512272
2019
8
19
17
58
52
2019-8-19
Reference
도서 [파이썬 머신러닝 판다스 데이터 분석]을 공부하며 작성하였습니다.
댓글남기기