ilovechoonsik
[STARTERS 4기 TIL] Python 시계열 #2 (230308) 본문

📖 오늘 내가 배운 것
1. DateTime
2. 시계열 데이터 Resampling
3. 판다스 시간 이동
4. Rolling and Expanded
5. 시계열 데이터 시각화
6. 연습 문제
1. DateTime
파이썬에서 사용되는 시계열 데이터 타입 종류는 다음과 같다
1.1 Python Datetime
from datetime import datetime
my_year = 2017
my_month = 1
my_day = 2
my_hour = 13
my_minute = 30
my_second = 15
my_date = datetime(my_year,my_month,my_day)
# January 2nd, 2017
my_date
# datetime.datetime(2017, 1, 2, 0, 0)
my_date_time = datetime(my_year,my_month,my_day,my_hour,my_minute,my_second)
# January 2nd, 2017 at 13:30:15
my_date_time
# datetime.datetime(2017, 1, 2, 13, 30, 15)
my_date.day
# 2
my_date_time.hour
# 13
1.2 Numpy Datetime
Numpy Datetime64 Python의 Datetime과 다르게 좀 더 세부적인 작업을 수행할 수 있다.
정밀도 설정, 쉽게 리스트 생성 등
(1) Numpy Datetime Arrays
Numpy에서 Datetime 배열을 생성하는 방법은 아래와 같다
# 3개의 날짜 배열 생성
np.array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64')
# array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[D]')
# [h]
np.array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[h]')
# array(['2016-03-15T00', '2017-05-24T00', '2018-08-09T00'], dtype='datetime64[h]')
# [Y]
np.array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[Y]')
# array(['2016', '2017', '2018'], dtype='datetime64[Y]')
📌 파라미터
dtype='dateime64'
dtype='dateime64[h]'
dtype='dateime64[D]'
dtype='dateime64[Y]'
-> datetime[h,D,Y 등]으로 정밀도 정의
(2) Numpy Date Ranges
넘파이의 장점인 범위를 통한 빠른 배열 생성을 시계열에 적용할 수 있다.
np.arange('2018-06-01', '2018-06-23', 7, dtype='datetime64[D]')
# array(['2018-06-01', '2018-06-08', '2018-06-15', '2018-06-22'], dtype='datetime64[D]')
np.arange('1968', '1976', dtype='datetime64[Y]')
# array(['1968', '1969', '1970', '1971', '1972', '1973', '1974', '1975'],dtype='datetime64[Y]')
📌 파라미터
dtype= : (1)과 동일하게 datetime[h,D,Y 등]으로 정밀도 정의
int : 중간에 정수 하나 보이는데 설정한 Date간의 간격이라 생각하면 된다! (dtype에서 정의한 정밀도 기준)
1.3 Pandas Datetime array
Pandas에서 작헙할 때, 날짜/시간 인덱스로 시계열을 처리하는 경우가 있는데!
Pandas 에는 이러한 시계열 작업을 위한 기능/방법이 존재한다.
(1) Datetime array index 생성
datetime index 생성의 가장 기본적인 방법 = pd.date_range
# THE WEEK OF JULY 8TH, 2018
idx = pd.date_range('7/8/2018', periods=7, freq='D')
idx
'''
DatetimeIndex(['2018-07-08', '2018-07-09', '2018-07-10', '2018-07-11',
'2018-07-12', '2018-07-13', '2018-07-14'],
dtype='datetime64[ns]', freq='D')
'''
실행해보면 DatetimeIndex가 보이는데, Pandas는 datetime 처리에 특화된 인덱스를 사용!
일반적인 datetime이 아니라 datetime64 객체가 존재 -> 둘의 차이? 표현 자리 수가 많아짐=굉장히 세부적으로 표현 가능
📌 파라미터
periods = 기준 날자로 부터 몇 개의 날짜를 원하는지
freq = 단위 설정! periods는 요 freq를 기준으로 개수를 자른다.
(2) Datetime 형식 지정
나라마다 Date를 표현하는 형식이 다른데 이런 건 어떻게 지정할 수 있을까!
ex) 년월의 표기 순서
아래와 같이 format 파라미터를 통해 설정
pd.to_datetime(['2/1/2018', '3/1/2018'])
# DatetimeIndex(['2018-02-01', '2018-03-01'], dtype='datetime64[ns]', freq=None)
pd.to_datetime(['2/1/2018', '3/1/2018'], format='%d/%m/%Y')
# DatetimeIndex(['2018-01-02', '2018-01-03'], dtype='datetime64[ns]', freq=None)
(3) Datetime index로 데이터프레임 생성 및 요약 확인
📌 Datetime index로 df 생성
# Create some random data
data = np.random.randn(3,2)
cols = ['A','B']
print(data)
'''
[[ 0.39860451 -0.21190089]
[-2.02537182 -1.34274471]
[ 1.23894686 -1.03323783]]
'''
idx = pd.date_range('2020-01-01',periods=3, freq='D')
idx
# DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(data,index=idx,columns=cols)
📌 요약 확인
# 현재 인덱스 반환
df.index
# DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq='D')
# 인덱스 마지막 값
df.index.max()
# Timestamp('2020-01-03 00:00:00', freq='D')
# 마지막 값 인덱스 상 위치
df.index.argmax()
# 2
# 인덱스 최근 값
df.index.min()
# Timestamp('2020-01-01 00:00:00', freq='D')
# 인덱스 최근 값 index
df.index.argmin()
# 0
2. 시계열 데이터 Resampling
📌 Sampling?
우리는 세상의 데이터들을 관측할 때 모든 데이터를 전부 살펴보기에는 힘듦!
따라서 일부만을 잘 뽑아내서 모집단 전체의 경향성을 살펴보고 싶음(모집단 전체에 대한 추정)
이 때 사용하는 것이 표본추출이고 이를 샘플링이라 함
그러나 아무리 잘 뽑아내도 완벽히 모집단 그 자체와 같을 수는 없고 놓치는 부분이 생겨 노이즈가 존재할 수 밖에 없음 이를 보정하기 위해 또 리샘플링이라는 기법을 사용!
📌 Resampling?
일부의 표본추출만으로는 모집단의 분포 형태를 정확히 알 수 없음
보유한 샘플들에서 다시 부분집합을 뽑아 통계량의 변동성을 확인하는 방법, 이를 리샘플링이라 함
대표적인 예시 : k-fold 교차검증, bootstrapping 기법이 있음
1.1 데이터 임포트
(1) Index를 DatetimeIndex로 읽어오기
df = pd.read_csv('../Data/starbucks.csv', index_col='Date', parse_dates=True)
- 데이터를 읽어오며 동시에 Index 지정, Index 타입을 시계열로 지정
- 파라미터 : parse_dates=True
1.2 resample()
(1) resample() 이란?
- Datetime Index를 원하는 주기로 나누어주는 함수! (요 작업이 resampling)
- 일, 월, 연도, 분기 등으로 집계 가능하다 (groupby와 유사)
(2) 파라미터
- 일, 월, 연 등등의 집계 기간을 파라미터로 줄 수 있음. 요기 참고
1.3 Plotting
몇 가지 예시를 통해 살펴보자!
사용 데이터 : 2015 ~ 2018 종가 및 거래량
📌 A : Year and Frequency
df['Close'].resample('A').mean().plot.bar(title='Yearly Mean Closing Price for Starbucks');
📌 M : month and Frequency
title = 'Monthly Max Closing Price for Starbucks'
df['Close'].resample('M').max().plot.bar(figsize=(16,6), title=title,color='#1f77b4');
3. Pandas 시간 이동
3.1 shift()
행을 앞 뒤로 이동 시키는 함수 (index는 고정)
📌 예시
제일 앞단에서 뒷단으로 1칸 shift (- 주면 반대로 shift)
df.head()
df.shift(1).head()
df.shift(1).tail()
- periods, freq 파리미터 이용하면 기간 설정 가능
periods : 주기
freq : 주기의 기준이 되는 시계열 (일, 연, 월 등)
# Shift everything forward one month
df.shift(periods=1, freq='M').head()
1달 기준으로 전부 shift
4. Rolling and Expanding
4.1 Rolling
(1) Rolling이란?
: 현재 열에 대하여 일정 크기의 창(window)를 이용하여 그 window안의 값을 추가 메서드를 통해 계산하는 메서드
~.rolling(window=~).집계함수()
(2) 사용법
📌 기본 종가 변화 시각화
📌 Rolling 이용한 30일 이동 평균선
df['Close: 30 Day Mean'] = df['Close'].rolling(window=30).mean()
df[['Close','Close: 30 Day Mean']].plot(figsize=(12,5)).autoscale(axis='x',tight=True);
-> 지정한 window에 따라 집계 함수를 적용할 수 있다
-> 주로 이동 평균선 그릴 때 사용
4.2 Expanding
(1) Expanding 이란?
: 행이나 열의 값에 대해 누적으로 연산을 수행하는 메서드 = (누적 집계)
~.expanding( ).집계함수( )
(2) 사용법
df['Close'].expanding(min_periods=30).mean().plot(figsize=(12,5));
제일 첫 행 부터 평균을 쌓아 올려 집계한 것! 데이터가 많아 질수록 라인은 수평을 이룬다
5. 시각화
5.1 Plot Formatting
시계열 데이터를 시각화하다 보면 x,y축을 디테일하게 설정해줘야 하는 상황이 발생한다!
어떤 방법들이 존재하는지 알아보자
(1) x,y축 figure에 맞추기
그래프 객체 설정 후 ax.autoscale() 사용을 통해 x,y축 을 figure에 딱 맞게 표현해줄 수 있다!
파리미터
적용할 축 지정 지정 : axis x, y, both
딱 맞출지 결정 : tight=True
title='Starbucks Closing Stock Prices'
ylabel='Closing Price (USD)'
xlabel='Closing Date'
ax = df['Close'].plot(figsize=(12,6),title=title)
ax.autoscale(axis='x',tight=True)
ax.set(xlabel=xlabel, ylabel=ylabel);
(2) 시계열 인덱스 범위 슬라이싱 2가지 방법
📌 df 레벨에서 설정 : plot 그리기 전 기간 설정
df['해당 열']['시작 기간':'끝 기간']
# Dates are separated by a colon:
df['Close']['2017-01-01':'2017-03-01'].plot(figsize=(12,4)).autoscale(axis='x',tight=True);
📌 plot 레벨에서 설정 : xlim을 통해 범위 지정
plot(xlim=['시작 기간','끝 기간'])
# Dates are separated by a comma:
df['Close'].plot(figsize=(12,4),xlim=['2017-01-01','2017-03-01']);
📌 y축 범위 지정 : plot(ylim=[~~, 시작 값, 끝 값])
(3) x 축 간격 설정
📌 x축 ticks가 겹칠 때 설정하는 방법 : .set_major_locator()
- ax.xaxis.set_major_locatior()
- 파라미터로 dates.weekdayylocator(byweekday=0)
- byweekday=1주일, 0=월요일! 7주일 간격, 기준은 월요일로 xticks 설정
# CREATE OUR AXIS OBJECT
ax = df['Close'].plot(xlim=['2017-01-01','2017-03-01'],ylim=[51,57])
# REMOVE PANDAS DEFAULT "Date" LABEL
ax.set(xlabel='')
# SET THE TICK LOCATOR AND FORMATTER FOR THE MAJOR AXIS
ax.xaxis.set_major_locator(dates.WeekdayLocator(byweekday=0))
xticks 다양한 파라미터는 요기 참고!
(4) Date Formatting
위치 설정 후 Date format 정해주지 않았다! 월을 축약된 월 이름으로 바꿔보자
ax = df['Close'].plot(xlim=['2017-01-01','2017-03-01'],ylim=[51,57],title='2017 Starbucks Closing Stock Prices')
ax.set(xlabel='')
ax.xaxis.set_major_locator(dates.WeekdayLocator(byweekday=0))
ax.xaxis.set_major_formatter(dates.DateFormatter("%a-%B-%d"))
Date format 형식은 요기 참고
(5) 주 축, 보조 축
- major라는 주 ticks에 보조 minor ticks 얹는 것! 세부 수준으로 분리
ax.xaxis.set_minor_lcator(세부 설정)
ax.xaxis.set_minor_formator(세부 설정)
ax = df['Close'].plot(xlim=['2017-01-01','2017-03-01'],ylim=[51,57],rot=0,title='2017 Starbucks Closing Stock Prices')
ax.set(xlabel='')
ax.xaxis.set_major_locator(dates.WeekdayLocator(byweekday=0))
ax.xaxis.set_major_formatter(dates.DateFormatter('%d'))
ax.xaxis.set_minor_locator(dates.MonthLocator())
ax.xaxis.set_minor_formatter(dates.DateFormatter('\n\n%b'))
확인해보면 ticks 가 겹치는 거 볼 수 있다! -> 요건 \n 으로설정
(6) 격자 추가
ax.yaxis.grid(True)
ax.xaxis.grid(True)
6. 연습문제
(1) DatetimeIndex를 월 이름으로 만드려면?
df['Month']=df.index.strftime('%B')
strftime 사용
(2) 2005년 이후 값이 가장 적었던 달은?
df.loc['2005-01-01':].idxmin()
.idxmin() 사용! : 축에 대한 최소값의 첫 번째 발생 인덱스 반환
(3) 연도별 변화량 확인하기
# 연도별 평균 집계 resampling
yearly_data = df.resample('Y').mean()
# +1 shift
yearly_data_shift = yearly_data.shift(1)
# 차이 구하기 위한 계산식
change = yearly_data - yearly_data_shift
# 최종적으로 값(변화량)이 가장 큰 행은? idxmax로 구하기
change['UMTMVS'].idxmax()
# Timestamp('2011-12-31 00:00:00', freq='A-DEC')
(4) 피크 찍은 연도 이후에 해당 값 초과하는 경우만 확인하기
#2008년 기준이기 때문에 데이터 추출
df2008 = df.loc['2008-01-01':'2009-01-01']
#2008년 max 찍은 날, 값 확인
df2008.idxmax() #2008-06-01
df2008.max() #510081.0
#다시 peak찍은 날 이후 데이터 추출
df_post_peak = df.loc['2008-06-01':]
#값이 510081 넘는 경우 제외하고 전부 NULL, dropna()로 날리기
df_post_peak[df_post_peak>=510081].dropna()
💪🏻 좋았던 점, 앞으로 개선해야 할 점 (추가로 배워야 할 점)
📌 개인적으로 매우 중요하다고 생각하는 시계열 데이터에 대해 학습했다!
이 기회에 확실히 굳히고 가야겠다🐿️
📌 앞으로 또 어떤 내용을 배울까~ 기대된다🐻
#유데미, #유데미코리아, #유데미부트캠프, #취업부트캠프, #부트캠프후기, #스타터스부트캠프, #데이터시각화 #데이터분석 #태블로
'STARTERS 4기 🚉 > TIL 👶🏻' 카테고리의 다른 글
[STARTERS 4기 TIL] 프로젝트 기반 태블로 실전 트레이닝 #1 (230313) (0) | 2023.03.13 |
---|---|
[STARTERS 4기 TIL] 중간 평가 대비 Python, SQL 복습 (230309,10) (0) | 2023.03.10 |
[STARTERS 4기 TIL] Python 시계열 #1 (230307) (0) | 2023.03.08 |
[STARTERS 4기 TIL] Tableau 고급 #2 (230306) (0) | 2023.03.06 |
[STARTERS 4기 TIL] Tableau 고급 #1 (230303) (0) | 2023.03.06 |