곡뢀기둝/μ‹œκ³„μ—΄

1. μ‹œκ³„μ—΄ 데이터λ₯Ό μœ„ν•œ datetime, Numpy & Pandas

kaizen_bh 2023. 12. 12. 08:41

 


 

톡계 λ“±μ˜ μˆ˜ν•™μ„ λͺ¨λ₯΄μ§€λ§Œ νšŒμ‚¬μ˜ μ‹œκ³„μ—΄ 데이터λ₯Ό λ‹€λ€„λ³΄κ³ μž μ‹œκ³„μ—΄ 곡뢀λ₯Ό μ‹œμž‘ν•˜κ²Œ λ˜μ—ˆλ‹€

 

(유데미 μ‹œκ³„μ—΄ κ°•μ˜)[https://www.udemy.com/course/250-timeseries-kor-sub-top-100/]

 

유데미의 μ‹œκ³„μ—΄ κ°•μ˜λ₯Ό λ³΄λ©΄μ„œ κ³΅λΆ€ν•œ λ‚΄μš©λ“€ μœ„μ£Όμ— λΆ€μ‘±ν•œ 뢀뢄듀을 κ²€μƒ‰ν•˜κ³  μ΅œμ’… λͺ©ν‘œλŠ” νšŒμ‚¬μ˜ μ‹€μ œ 데이터에 μ μš©ν•œ μ‚¬λ‘€κΉŒμ§€ μ†Œκ°œν•˜λŠ” 것이닀.

 

κ³΅λΆ€ν• μˆ˜λ‘ 톡계 λͺ¨λΈμ„ μ‚¬μš©ν•˜μ—¬ μ‹œκ³„μ—΄ 데이터에 λŒ€ν•΄ 뢄석 및 λͺ¨λΈλ§μ„ ν•˜λŠ” λ‚΄μš©λ“€μ„ λ³΄λ©΄μ„œ λ‚΄κ°€ μˆ˜ν•™μ μΈ 뢀뢄에 λŒ€ν•΄ μ œλŒ€λ‘œ μ΄ν•΄ν•˜μ§€ λͺ»ν–ˆλŠ”λ° μ •λ¦¬ν•΄μ„œ λΈ”λ‘œκ·Έμ— μ˜¬λ¦¬λŠ” 게 λ§žλ‚˜ μ‹Άλ‹€κ°€ λ‚˜ 같은 μˆ˜ν•™μ„ λͺ¨λ₯΄λŠ” μž…λ¬Έμžλ“€μ΄ 이둠보닀 μ½”λ“œμ μΈ 뢀뢄듀을 λ¨Όμ € κ°€μ Έκ°€κ³  μ μš©ν•΄ 보고 이둠 뢀뢄을 μ±„μ›Œλ‚˜κ°€λŠ” μ‹μœΌλ‘œ 글을 ν•œλ²ˆ 정리해보고 μ‹Άμ—ˆλ‹€. κ·Έλž˜μ„œ κΈ€μ˜ μ£Ό λ‚΄μš©μ€ μ‹€μ œ μ½”λ“œ μœ„μ£Όκ°€ 될 것이닀.


 

 

1. μ‹œκ³„μ—΄ 데이터λ₯Ό μœ„ν•œ datetime, Numpy & Pandas

μ‹œκ³„μ—΄ λ°μ΄ν„°μ˜ 경우 데이터셋이 μ§§κ²ŒλŠ” 초, λΆ„λ‹¨μœ„ λΆ€ν„° μ‹œκ°„, 일자, μ£Ό, μ›”, λ…„ μ‹œκ°„μˆœμœΌλ‘œ 일정 κ°„κ²©μœΌλ‘œ 데이터듀이 λ‚˜μ—΄λ˜μ–΄ μžˆλ‹€.

κ·Έλž˜μ„œ μ‹œκ°„μ„ λ‹΄κ³  μžˆλŠ” 칼럼 λ˜λŠ” 인덱슀λ₯Ό 핸듀링할 쀄 μ•Œλ©΄ μ‹œκ³„μ—΄ 데이터λ₯Ό λ‹€λ£¨λŠ”λ° μœ μš©ν•˜λ‹€.

주둜 μ‹œκ°„μ„ λ‹€λ£¨λŠ” λΌμ΄λΈŒλŸ¬λ¦¬λ‘œλŠ” 파이썬의 datetime이 있고 νŒλ‹€μŠ€μ˜ pd.to_datetime μ‚¬μš©ν•˜κΈ°λ„ ν•œλ‹€.

이전에 μ°Έμ—¬ν•œ 데이콘 μ‹œκ³„μ—΄ λŒ€νšŒ μˆ˜μƒμž μ½”λ“œλ¦¬λ·° μŠ€ν„°λ””μ—μ„œ μˆ˜μƒμžνŒ€μ€ μ‹œκ³„μ—΄ 데이터 μ „μ²˜λ¦¬μ— 주둜 νŒλ‹€μŠ€μ˜ pd.to_datetime을 μ‚¬μš©ν•˜μ˜€λ‹€.

전체 λ‚΄μš©μ„ λ‹€λ£¨μ§€λŠ” μ•Šκ³  주둜 μ‚¬μš©ν–ˆλ˜ κΈ°λŠ₯ μœ„μ£Όλ‘œλ§Œ κ°„λ‹¨νžˆ 정리해보렀 ν•œλ‹€.

 

 

1-1. datetime

νŒŒμ΄μ¬μ— λ‚΄μž₯된 λͺ¨λ“ˆ 쀑 ν•˜λ‚˜λ‘œ λ‚ μ§œμ™€ μ‹œκ°„μ„ 닀룬닀. κ°„λ‹¨ν•˜κ²Œ import ν•΄μ„œ μ‚¬μš©κ°€λŠ₯ν•˜λ‹€.

# Import the entire module:
import datetime

 

μ‚¬μš©λ²•μ€ μ–΄λ ΅μ§€ μ•ŠμœΌλ―€λ‘œ κ°„λ‹¨ν•˜κ²Œλ§Œ 정리해 보자면

# datetime 객체 생성 및 μ‹œκ°„ μž…λ ₯
tm = datetime.time(hour=5,minute=25,second=1) / tm = datetime.time(5,25,1)
=> datetime.time(5, 25, 1)

print(tm)
=> 05:25:01

print(tm.minute)
=> 25

print(tm.second)
=> 1

type(tm)
=> datetime.time

---------------------------------------------------
# λ‚ μ§œ 및 μ‹œκ°„ μž…λ ₯. 2019,1,2 뒀에 μ‹œκ°„μ΄ μž…λ ₯λ˜μ§€ μ•ŠμœΌλ©΄ 2019-02-02 00:00:00 이런 ν˜•νƒœλ‘œ 좜λ ₯λœλ‹€
day_time = datetime.datetime(2019, 1, 2, 5, 25, 1)
=> datetime.datetime(2019, 1, 2, 5, 25, 1)

print(day_time)
=> 2019-01-02 05:25:01

print(day_time.day)
=> 2

---------------------------------------------------
x = date.today()
print(x)
=> 2019-01-03

y = datetime.today()
print(y)
=> 2019-01-03 12:15:05.526582


---------------------------------------------------
d = datetime(1969,7,20,20,17)
d.weekday()
=> 6

 

datetime의 객체λ₯Ό μƒμ„±ν•˜κ³  λ‚ μ§œμ™€ μ‹œκ°„μ„ μž…λ ₯ν•˜μ—¬ μ›ν•˜λŠ” λ‚ μ§œμ˜ datetime을 λ§Œλ“€κ³  κ±°κΈ°μ„œ ν•„μš”ν•œ λ‚ μ§œμ™€ μ‹œκ°„, λΆ„, 초 등을 μΆ”μΆœν•΄ μ‚¬μš©ν•  수 μžˆλ‹€. todayλ₯Ό 톡해 ν˜„μž¬ λ‚ μ§œμ™€ μ‹œκ°„κΉŒμ§€ 좜λ ₯ν•  수 μžˆλ‹€.

weekdayλ₯Ό μ‚¬μš©ν•˜λ©΄ μ–΄λŠ λ‚ μ§œλ“  μ •ν™•ν•œ μš”μΌμ„ μ•Œλ €μ£Όλ©° 0~6, μ›”μš”μΌ ~ μΌμš”μΌ 순으둜 ν• λ‹Ήλœλ‹€.

++정말 μ‚¬μ†Œν•˜μ§€λ§Œ μ‹€λ¬΄μ—μ„œ datetime을 μ‚¬μš©ν–ˆλ˜ κ²½μš°λŠ” vm μ„œλ²„μ—μ„œ μ‹€μ‹œκ°„μœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ„ μ²˜λ¦¬ν•  λ•Œ 쀑간에 μ²˜λ¦¬μ†λ„κ°€ 느렀져 병λͺ© λ˜λŠ” μ΄μŠˆκ°€ μžˆμ—ˆλ‹€.

μ΄λ•Œ datetime을 μ΄μš©ν•΄ μ‹€μ‹œκ°„μœΌλ‘œ 둜그λ₯Ό μ°μ–΄λ³΄λ©΄μ„œ μ½”λ“œ 쀑간에 κ²€μˆ˜λ₯Ό μœ„ν•œ for문이 μ‹œκ°„μ„ 많이 μž‘μ•„λ¨Ήμ—ˆμŒμ„ μ°Ύμ•˜λ˜ 적이 μžˆμ—ˆλ‹€. 정말 기본적이고 μ‰¬μš΄ λΌμ΄λΈŒλŸ¬λ¦¬μ΄μ§€λ§Œ μ΄λ ‡κ²Œ μ‚¬μš©λ˜λŠ” κ²½μš°κ°€ μ’…μ’… μžˆκΈ°μ— κΈ°μ΄ˆκ°€ μ€‘μš”ν•˜λ‹€λŠ” κ±Έ λ°°μ› λ‹€.

 

 


1-2. Numpy

 

데이터 λΆ„μ„μ΄λ‚˜ λŒ€λΆ€λΆ„μ˜ 인곡지λŠ₯ κ°•μ˜λ₯Ό 보면 λ„˜νŒŒμ΄, νŒλ‹€μŠ€μ— λŒ€ν•œ κΈ°μ΄ˆλ‚΄μš©λ“€μ„ 닀루기 λ•Œλ¬Έμ— 전체 λ‚΄μš©μ„ λ‹€ 닀루지 μ•Šκ² λ‹€.

λ„˜νŒŒμ΄μ˜ κ°€μž₯ 큰 μž₯점은 λΈŒλ‘œλ“œμΊμŠ€νŒ…, 배열에 λŒ€ν•΄ λ‹€μ–‘ν•œ 연산을 μΌκ΄„μ μœΌλ‘œ μ μš©μ‹œν‚¬ 수 μžˆλ‹€λŠ” 점으둜 μΈλ±μ‹±μ΄λ‚˜ μŠ¬λΌμ΄μ‹± λ“± λΉ„μŠ·ν•΄ λ³΄μ΄λŠ” λ¦¬μŠ€νŠΈμ™€ 큰 차이점이기도 ν•˜λ‹€.

 

import numpy as np
arr = np.arange(0,10)
=> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# BroadCasting
arr + arr
=> array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

arr * arr
=> array([ 0,  1,  4,  9, 16, 25, 36, 49, 64, 81])

arr - arr
=> array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

arr / 2
=> array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])

arr**3
=> array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729], dtype=int32)

 

μ΄λ ‡κ²Œ λ‹¨μˆœ μ—°μ‚° 외에도 np.sqrt(), exp(), sin(), log() λ“±μ˜ λ³΅μž‘ν•œ 연산도 μΌκ΄„μ μœΌλ‘œ μ μš©ν•΄ 쀄 수 μžˆλ‹€.

이 외에도 배열에 λŒ€ν•΄ 총합, sum() / 평균값 mean() / μ΅œλŒ“κ°’ max() / μ΅œμ†Œ-μ΅œλŒ“κ°’μ˜ 인덱슀λ₯Ό μ°ΎλŠ” argmin()κ³Ό argmax(), 쑰건을 톡해 값을 μ°Ύκ³  λ˜λŠ” κ΅μ²΄κΉŒμ§€ ν•  수 μžˆλŠ” np.where()κΉŒμ§€ μœ μš©ν•œ κΈ°λŠ₯듀이 λ§Žλ‹€.

 

특히 λ„˜νŒŒμ΄μ—μ„œ μ€‘μš”ν•˜λ‹€κ³  μƒκ°ν•˜λŠ” κΈ°λŠ₯은 reshape와 쑰건을 ν†΅ν•œ κ°’ 필터링 및 인덱슀 색인이닀.

arr_2d = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
arr_2d, arr_2d.shape
=> 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

=> (3, 4)

arr_2d.reshape(2,6)
=> 
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])
---------------------------

μ—¬λŸ¬ μ°¨μ›μœΌλ‘œ λ˜μ–΄ μžˆλŠ” 데이터λ₯Ό 핸듀링할 λ•Œ reshape와 λ‹€μ–‘ν•œ 연산을 같이 μ΄μš©ν•˜μ—¬ μ›ν•˜λŠ” 값을 μΆ”μΆœ 및 λ³€ν™˜ν•  수 μžˆλ‹€.

 


μœ„μ—μ„œ Numpy의 κΈ°λŠ₯듀에 λŒ€ν•΄ κ°„λ‹¨ν•˜κ²Œλ§Œ μ–ΈκΈ‰ν•˜μ˜€κ³  Numpy둜 Datetime 배열을 닀뀄볼 것이닀.

import numpy as np
date_array = 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]')

---

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]')

---

np.array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[Y]')
=> array(['2016', '2017', '2018'], dtype='datetime64[Y]')

 

λ„˜νŒŒμ΄λ‘œ datetime νƒ€μž… 배열을 생성 μ‹œ datetime64 [h], datetime64 [Y] νƒ€μž…μ„ μ§€μ •ν•˜μ—¬ μ›ν•˜λŠ” μ‹œκ°„λŒ€λ₯Ό μΆ”μΆœν•  수 μžˆλ‹€.

 

리슀트의 range와 λ§ˆμ°¬κ°€μ§€λ‘œ λ„˜νŒŒμ΄μ—μ„œλ„ np.arrange()λ₯Ό 톡해 일정 λ²”μœ„ 내에 μ›ν•˜λŠ” μŠ€ν…λ§ŒνΌμ˜ 배열을 생성할 수 μžˆλŠ”λ° νƒ€μž…μ„ datetime으둜 쀄 경우 μ‹œκ°„ 배열도 생성이 κ°€λŠ₯ν•˜λ‹€! 

# μŠ€ν…μ‚¬μ΄μ¦ˆλŠ” dtypeλ₯Ό 톡해 μ§€μ •. 7, datetiem64[D] => 7일.
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]')

 

μ‹œκ³„μ—΄ 데이터λ₯Ό 닀룬닀면 주둜 νŒλ‹€μŠ€λ₯Ό ν†΅ν•΄μ„œ μ‚¬μš©ν•˜κ² μ§€λ§Œ λ„˜νŒŒμ΄λ‘œλ„ datetime νƒ€μž…μ„ λ‹€λ£° 수 μžˆλ‹€λŠ” 점 기얡해두면 쒋을 것 κ°™λ‹€

 

 


1-3. Pandas

 

(1) Pandas Datetime - Index

μ‹œκ³„μ—΄ 데이터λ₯Ό λ‹€λ£° λ•Œ νŒλ‹€μŠ€λ‘œ λ‹€μ–‘ν•œ 핸듀링을 ν•œλ‹€. λ¨Όμ € 뢄석을 ν•˜κΈ° μ’‹κ²Œ μ΄μƒμΉ˜λ‚˜ κ²°μΈ‘μΉ˜λ“€μ„ μ²˜λ¦¬ν•˜κ³  보기 νŽΈν•œ ν˜•νƒœλ‘œ λ³€ν™˜ν•˜κ±°λ‚˜ 그룹끼리 λ¬Άμ–΄μ„œ 연산을 톡해 μƒˆλ‘œμš΄ ν˜•νƒœμ˜ ν…Œμ΄λΈ”κ³Ό μΈμ‚¬μ΄νŠΈλ₯Ό 뽑아낸닀.

μ΄λ ‡κ²Œ μ—°μ‚°ν•œ ν…Œμ΄λΈ”λ“€μ„ matplotlib, seaborn λ˜λŠ” νŒλ‹€μŠ€μ˜ λ‚΄μž₯ plot을 μ΄μš©ν•΄ μ‹œκ°ν™”λ₯Ό ν•˜μ—¬ 뢄석을 μ§„ν–‰ν•œλ‹€.

νŒλ‹€μŠ€λ₯Ό μ΄μš©ν•œ 데이터 핸듀링 및 μ‹œκ°ν™”κΉŒμ§€ 닀루면 λ‚΄μš©μ΄ λ„ˆλ¬΄ κΈΈμ–΄μ§€κΈ° μ—¬κΈ°μ„œ 닀루지 μ•Šκ³  μ‹œκ°„ νƒ€μž…μ— λŒ€ν•΄ νŒλ‹€μŠ€λ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•˜λŠ”μ§€λ₯Ό μ •λ¦¬ν•˜κ³ μž ν•œλ‹€.

λ„˜νŒŒμ΄μ—μ„œ np.arange에 데이터 νƒ€μž…μ„ datetime64둜 μ€˜μ„œ μ‹œκ°„ 배열을 μƒμ„±ν•œ κ²ƒμ²˜λŸΌ λΉ„μŠ·ν•œ κΈ°λŠ₯을 νŒλ‹€μŠ€μ—μ„œλ„ μ§€μ›ν•œλ‹€.

 

 

import pandas as pd

pd.date_range('2020-01-01', periods=7, freq='D')
=> DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05', '2020-01-06', '2020-01-07'],
              dtype='datetime64[ns]', freq='D')

---

pd.date_range('Jan 01, 2018', periods=7, freq='D') 
# νŒλ‹€μŠ€μ˜ λ‚΄μž₯된 ν˜•νƒœμ˜ λ¬Έμžμ—΄μ΄λΌλ©΄ μ΄λ ‡κ²Œ μž…λ ₯해도 인식함.
=> DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
               '2018-01-05', '2018-01-06', '2018-01-07'],
              dtype='datetime64[ns]', freq='D')

---

# 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')

 

κ½€ λ‹€μ–‘ν•œ ν˜•νƒœλ₯Ό μž…λ ₯으둜 λ°›μ„μˆ˜ μžˆμŒμ„ λ³Ό 수 μžˆλ‹€. νŒλ‹€μŠ€μ—μ„œ μΈμ‹ν•˜λŠ” ν˜•νƒœλΌλ©΄ κΌ­ ν˜•νƒœκ°€ λ™μΌν•˜μ§€ μ•Šμ•„λ„ μ‹œκ°„ 배열을 생성할 수 μžˆλ‹€.

λ„˜νŒŒμ΄λ‘œ μƒμ„±ν•œ νƒ€μž„ 배열을 λ°μ΄ν„°ν”„λ ˆμž„μ˜ 인덱슀둜 μ„€μ •ν•˜λŠ” κΈ°λŠ₯도 μ§€μ›ν•œλ‹€.

 

some_dates = np.array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[D]')
=> array(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[D]')

---

idx = pd.DatetimeIndex(some_dates)
=> DatetimeIndex(['2016-03-15', '2017-05-24', '2018-08-09'], dtype='datetime64[ns]', freq=None)

μ΄λ ‡κ²Œ 인덱슀λ₯Ό 섀정해쀄 μˆ˜λ„ μžˆμ§€λ§Œ μ‹œκ³„μ—΄ 데이터λ₯Ό 뢈러올 λ•Œ 컬럼 쀑 μ‹œκ°„ 컬럼이 μžˆλ‹€λ©΄ μ•„λž˜μ²˜λŸΌ 인덱슀 μ„€μ •κ³Ό parse_dates νŒŒλΌλ―Έν„°λ₯Ό 톡해 인덱슀λ₯Ό datetime νƒ€μœΌλ‘œ μ„€μ •ν•˜μ—¬ 데이터λ₯Ό 뢈러올 수 μžˆλ‹€.

λ°μ΄ν„°λŠ” ν•΄λ‹Ή κ°•μ˜μ—μ„œ μ‚¬μš©ν•œ μŠ€νƒ€λ²…μŠ€μ˜ 주식 κ°’ 데이터λ₯Ό μ΄μš©ν•œλ‹€. Close μ»¬λŸΌμ€ λ§ˆκ°μ‹œ 가격, μ’…κ°€λ₯Ό μ˜λ―Έν•˜κ³  Volume은 ν•΄λ‹Ή λ‚ μ§œμ˜ μ£Όμ‹κ±°λž˜λŸ‰μ„ μ˜λ―Έν•œλ‹€.

 

df = pd.read_csv('./Data/starbucks.csv', index_col='Date', parse_dates=True)

 

Date Close Volume
2015-01-02 38.0061 6906098
2015-01-05 37.2781 11623796
2015-01-06 36.9748 7664340
2015-01-07 37.8848 9732554
2015-01-08
38.4961 13170548

 

μœ„μ˜ λ°©λ²•μœΌλ‘œ 데이터λ₯Ό 뢈러온 후에 인덱슀λ₯Ό 확인해보면

DatetimeIndex(['2015-01-02', '2015-01-05', '2015-01-06', '2015-01-07',
'2015-01-08', '2015-01-09', '2015-01-12', '2015-01-13',
'2015-01-14', '2015-01-15',
...
'2018-12-17', '2018-12-18', '2018-12-19', '2018-12-20',
'2018-12-21', '2018-12-24', '2018-12-26', '2018-12-27',
'2018-12-28', '2018-12-31'],
dtype='datetime64[ns]', name='Date', length=1006, freq=None)

μ΄λ ‡κ²Œ datetime64둜 μΈλ±μŠ€κ°€ λΆˆλŸ¬μ™€μ§€λŠ” 것을 확인할 수 μžˆλ‹€.

 

 


 

(2) Time - Resampling

μ‹œκ³„μ—΄ 뢄석을 함에 μžˆμ–΄μ„œ κΈ°μ΄ˆκ°€ λ˜λŠ” 방법이 Resampling이닀. datetime인덱슀λ₯Ό μΈμ‹ν•˜μ—¬ λ‹€μ–‘ν•œ 룰셋을 μ μš©ν•΄ μ›ν•˜λŠ” λ‚ μ§œμ™€ νŒ¨ν„΄μ„ κ°„λ‹¨ν•˜κ²Œ λ¬Άμ–΄μ„œ μ›ν•˜λŠ” 연산을 ν•  수 μžˆλŠ” 것이 resample의 μž₯점이닀. λ§Œμ•½ μ–΄λŠ 달은 30일 ν˜Ήμ€ 31μΌκΉŒμ§€ 없더라도 νŒλ‹€μŠ€μ—μ„œ ν•΄λ‹Ή μ›”μ˜ λ§ˆμ§€λ§‰ λ‚ μ§œλ₯Ό μΈμ‹ν•˜μ—¬ 계산해쀀닀.

λ°μ΄ν„°λŠ” μœ„μ™€ λ™μΌν•œ μ£Όκ°€ 데이터λ₯Ό μ‚¬μš©ν•œλ‹€.

Date Close Volume
2015-01-02 38.0061 6906098
2015-01-05 37.2781 11623796
2015-01-06 36.9748 7664340
2015-01-07 37.8848 9732554
2015-01-08
38.4961 13170548
df.resample(rule='A').mean()

μ—¬κΈ°μ„œ μ‚¬μš©ν•œ rule='A'λŠ” year and frequency둜 각 μ—°λ§ˆλ‹€ 끝 λ‚ μ§œμ— λŒ€ν•΄ 평균값을 계산해쀀닀. 이 외에도 λ‹€μ–‘ν•œ λ‚ μ§œνŒ¨ν„΄λ“€μ΄ 룰셋에 μžˆμœΌλ―€λ‘œ ν•„μš”ν•œ λ£° 셋을 μ§€μ •ν•˜μ—¬ μ΄μš©ν•˜λ©΄ λœλ‹€.

μœ„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚€λ©΄ λ‹€μŒκ³Ό 같은 κ²°κ³Όλ₯Ό μ–»λŠ”λ‹€.

Date Close Volume
2015-12-31 50.078100 8.649190e+06
2016-12-31 53.891732 9.300633e+06
2017-12-31 55.457310 9.296078e+06
2018-12-31 56.870005 1.122883e+07

 

 


 

(3) Time - Shifting

νŒλ‹€μŠ€μ—λŠ” shiftλΌλŠ” κΈ°λŠ₯이 μ‘΄μž¬ν•œλ‹€. shiftλ₯Ό 톡해 데이터 값듀을 μ•ž ν–‰ λ˜λŠ” λ’· ν–‰μœΌλ‘œ μ΄λ™μ‹œν‚¬ 수 μžˆλ‹€.

ν•˜λ‚˜μ˜ ν–‰ λ˜λŠ” μ—΄μ˜ 데이터λ₯Ό ν•˜λ‚˜μ”© λ°€μ–΄λ‚΄κ±°λ‚˜ λ‹ΉκΈ΄λ‹€κ³  μ΄ν•΄ν•˜λ©΄ λœλ‹€.

df.shift(1).head()
Date Close Volume
2015-01-02 38.0061 6906098
2015-01-05 37.2781 11623796
2015-01-06 36.9748 7664340
2015-01-07 37.8848 9732554
2015-01-08
38.4961 13170548

 

μ—¬κΈ° 기쑴의 λ°μ΄ν„°μ—μ„œ

 

Date Close Volume
2015-01-02 NaN NaN
2015-01-05 38.0061 6906098
2015-01-06 37.2781 11623796
2015-01-07 36.9748 7664340
2015-01-08
37.8848 9732554

μ—΄λ°©ν–₯으둜 행에 μžˆλŠ” 데이터λ₯Ό ν•˜λ‚˜μ”© μ•„λž˜λ‘œ λ°€μ–΄λ‚Έλ‹€.

 

df.shift(periods=1, freq='M').head()

λ‹¨μˆœνžˆ ν•˜λ‚˜μ˜ 행을 λ°€κ³  λ‹ΉκΈ°λŠ” 것 외에도 λ‹€λ₯Έ νŒŒλΌλ―Έν„° 섀정을 톡해 ν•œλ‹¬ λ‹¨μœ„λ‘œ μ΄λ™μ‹œν‚€λŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

  • periods값을 톡해 λͺ‡ 개의 행을 λ°€μ–΄λ‚Ό 것인지 μ„€μ •κ°€λŠ₯
  • axis=”columns”둜 μ„€μ •ν•˜λ©΄ μœ„μ•„λž˜κ°€ μ•„λ‹Œ μ–‘μ˜†μœΌλ‘œ 이동도 κ°€λŠ₯ν•˜λ‹€.
  • 값을 shiftν•  경우 맨 처음-맨 λ§ˆμ§€λ§‰ 값듀이 NaNκ°’μœΌλ‘œ μ±„μ–΄μ§€λŠ”λ° fill_value=0을 톡해 μ›ν•˜λŠ” κ°’μœΌλ‘œ μ±„μšΈ 수 μžˆλ‹€
  • μœ„μ—μ„œ freq=’M’을 쀀것 처럼 freq=’D’ λ“±λ“± 일, μ›”λ³„λ‘œ 이동도 κ°€λŠ₯ν•˜λ‹€

 


(4) Rolling & Expanding

μ•žμ—μ„œ νŒλ‹€μŠ€λ₯Ό 톡해 datetimeνƒ€μž…μ˜ 인덱슀λ₯Ό 닀루고 κ·Έλ£Ήλ³„λ‘œ 연산을 해보고 μ•žλ’€λ‘œ 당겨보며 핸듀링을 ν•΄λ³΄μ•˜λ‹€λ©΄ 이제 일정 κΈ°κ°„λ™μ•ˆ 평균값을 μ°μ–΄λ³΄λ©΄μ„œ μ‹œκ³„μ—΄ λ°μ΄ν„°μ˜ μΆ”μ„Έλ₯Ό λ³΄λŠ” 방법을 μ—°μŠ΅ν•œλ‹€.

λ¨Όμ € νŒλ‹€μŠ€μ˜ rolling에 λŒ€ν•΄ κ°„λ‹¨ν•˜κ²Œ μ„€λͺ…ν•΄λ³΄μžλ©΄ μ‹œκ°„μˆœμœΌλ‘œ λ‚˜μ—΄λœ 데이터듀에 λŒ€ν•΄ 일정 μ£ΌκΈ°λ§ˆλ‹€ 평균값을 κ³„μ‚°ν•˜μ—¬ μƒˆλ‘œμš΄ 데이터λ₯Ό λ§Œλ“€μ–΄λ‚΄λŠ” κΈ°λŠ₯으둜 기간이동 계산 ν˜Ήμ€ 이동평균 ν•¨μˆ˜λΌ ν•œλ‹€.

 

ν•΄λ‹Ή κ·Έλž˜ν”„λŠ” μŠ€νƒ€λ²…μŠ€ μ£Όμ‹μ’…κ°€μ˜ κ·Έλž˜ν”„μ΄λ‹€. 이제 νŒλ‹€μŠ€μ˜ rolling을 μ΄μš©ν•˜μ—¬ 원본 κ·Έλž˜ν”„μ™€ 비ꡐ할 것이닀.

 

Rolling

# 7 day rolling mean
df.rolling(window=7).mean().head(15) # window : ν•œλ²ˆμ— μ–Όλ§ˆλ§ŒνΌμ˜ μ„Ήμ…˜μ„ λ³Όκ²ƒμΈμ§€μ˜ 크기, λͺ‡ 개 행을 λ³Ό 건지.
  • μ‚¬μš©ν•˜λŠ” λ°μ΄ν„°λŠ” μΌλ‹¨μœ„μ΄κ³  window=7은 κ³§ 일주일 λ‹¨μœ„λ₯Ό μ˜λ―Έν•œλ‹€.
Date Close Volume
2015-01-02 NaN NaN
2015-01-05 NaN NaN
2015-01-06 NaN NaN
2015-01-07 NaN NaN
2015-01-08
NaN NaN
2015-01-09 NaN NaN
2015-01-12 37.616786 1.238222e+07
2015-01-13 37.578786 1.297288e+07
2015-01-14 37.614786 1.264020e+07
2015-01-15 37.638114 1.270624e+07
2015-01-16 37.600114 1.260380e+07
2015-01-20 37.515786 1.225634e+07
2015-01-21 37.615786 9.868837e+06
2015-01-22 37.783114 1.185335e+07
2015-01-23 38.273129 1.571999e+07

 

  • 결과값을 보면 처음 μ—¬μ„―κ°œ 값은 λͺ¨λ“œ NaN값이 λ‚˜μ˜€λŠ”λ° κ·Έ μ΄μœ λŠ” 아직 평균을 κ΅¬ν•˜λ €λŠ” 일곱개 값이 μ±„μ›Œμ§€μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
  • 둀링 창을 μ‚¬μš©ν•  경우 n-1 κ°œμˆ˜κ°€ NaNκ°’μœΌλ‘œ λΉ„κ²Œ λœλ‹€.

 

df['Close'].plot(figsize=(12,5)).autoscale(axis='x',tight=True)
df.rolling(window=7).mean()['Close'].plot();

그럼 원본 데이터값과 이동평균 ν•¨μˆ˜κ°’μ„ κ·Έλž˜ν”„λ‘œ κ·Έλ €μ„œ 비ꡐ해보면 μ•„λž˜κ³Ό κ°™λ‹€.

μ—¬κΈ°μ„œ μ£Όλͺ©ν•  점은 window의 값이닀. 즉, 평균값을 계산할 μ£ΌκΈ°λ₯Ό μ–Όλ§ˆλ‚˜ μ£ΌλŠλƒμ— 따라 κ·Έλž˜ν”„μ˜ ν˜•νƒœκ°€ 많이 λ‹¬λΌμ§€κ²Œ λœλ‹€.

 

< window = 7 >

 

< window = 30 >

 

< window = 180 >

  • window값에 λ”°λ₯Έ κ·Έλž˜ν”„λ₯Ό 비ꡐ해봀을 λ•Œ μœˆλ„μš° μ°½ 크기가 클수둝 λ°˜μ˜λ˜λŠ” 값듀이 λ§Žμ•„μ§€λ―€λ‘œ κ·Έλž˜ν”„κ°€ 보닀 더 μ™„λ§Œν•΄μ§€λ©° μΌλ°˜ν™”λ˜λŠ” 것을, μΌλ°˜ν™”λ˜λŠ” μΆ”μ„Έλ₯Ό 보여쀀닀
  • 반면 μœˆλ„μš° μ°½ 크기가 μž‘μ„μˆ˜λ‘ 원본 데이터에 κ°€κΉκ²Œ κ·Έλ €μ§„λ‹€. κ³ μˆ˜μ€€μ˜ μΆ”μ„Έλ₯Ό 보여쀀닀.

 

 


 

expanding

μœ„μ—μ„œ rolling을 μ‚¬μš©ν•  경우 λ°μ΄ν„°μ˜ 맨 μ•žμͺ½λΆ€ν„° μœˆλ„μš° 개수만큼 μ±„μ›Œμ§€μ§€ μ•ŠλŠ” ν–‰κΉŒμ§€ 평균값을 κ³„μ‚°ν•˜μ§€ λͺ»ν•΄ NaNκ°’μœΌλ‘œ μ±„μ›Œμ§€λŠ” 것을 확인할 수 μžˆμ—ˆλ‹€.

expanding을 μ‚¬μš©ν•˜λ©΄ μ΄λ™ν•˜λ©΄μ„œ μœˆλ„μš° μ°½ 개수만큼의 데이터λ₯Ό κ³„μ‚°ν•˜λŠ” 것이 μ•„λ‹Œ μ‹œκ³„μ—΄μ˜ μ‹œμž‘μ λΆ€ν„° 점차 κ³„μ‚°ν•˜λŠ” 창의 크기λ₯Ό λŠ˜λ €κ°€ 맨 λ§ˆμ§€λ§‰ λ°μ΄ν„°μ—μ„œλŠ” λͺ¨λ“  데이터에 λŒ€ν•œ 평균을 κ³„μ‚°ν•œλ‹€. μ΄λ ‡κ²Œ κ³„μ‚°ν•˜λŠ” λ²”μœ„λ₯Ό ν™•μž₯ν•˜κΈ°μ— expanding이라 ν•œλ‹€.

 

df['Close'].expanding(min_periods=30).mean().plot(figsize=(12,5));

κ·Έλž˜ν”„λ₯Ό λ³΄λ©΄μ„œ 더 μ„€λͺ…ν•΄λ³΄μžλ©΄

  • rolling의 경우 window, 창에 μ§€μ •ν•œ 개수만큼 각 μ‹œμ λ§ˆλ‹€ μ΄λ™ν•˜λŠ” 것과 λ‹€λ₯΄λ‹€. 2015-07에 λŒ€ν•œ y값은 맨 처음 κ°’λΆ€ν„° ν•΄λ‹Ή μ‹œμ κΉŒμ§€ λͺ¨λ“  데이터에 λŒ€ν•œ 평균값을 μ˜λ―Έν•œλ‹€
  • λ”°λΌμ„œ μ‹œκ°„μ΄ μ§€λ‚ μˆ˜λ‘ 평균에 λ°˜μ˜λ˜λŠ” 데이터듀이 λ§Žμ•„μ§€λ―€λ‘œ μΌλ°˜ν™”κ°€ λ˜λ©΄μ„œ μ™„λ§Œν•œ κ·Έλž˜ν”„λ₯Ό 그리게 λœλ‹€
  • μ‹œκ°„μ΄ μ§€λ‚˜κ³  맨 λ§ˆμ§€λ§‰ μ‹œμ μΈ 2019-01의 경우, 전체 데이터 ν”„λ ˆμž„μ˜ λͺ¨λ“  ν–‰, ν•˜λ‚˜μ˜ 열에 λŒ€ν•œ 평균 값이 λœλ‹€.

 


 

rolling vs expanding

  • rolling은 μ›€μ§μ΄λŠ” μ°½, μœˆλ„μš°κ°€ μ΄λ™ν•˜λ©΄μ„œ 평균값을 κ΅¬ν•œλ‹€
  • expanding은 κ·Έ 창이 계속 이동과 λ™μ‹œμ— ν™•μž₯ν•˜λ©΄μ„œ 평균값을 κ΅¬ν•œλ‹€. 맨 μ²˜μŒλΆ€ν„° μ‹œμž‘ν•˜μ—¬ λκΉŒμ§€ κ°€κ²Œλ˜λ©΄ κ·Έ μ—΄μ˜ 전체 데이터 ν‰κ· μœΌλ‘œ μˆ˜λ ΄ν•œλ‹€.

 

 

 


참고자료