코딩하는 타코야끼

[Pandas] 7-2강_시계열 데이터 다루기(시계열 데이터셋) 본문

[T.I.L] : Today I Learned/Pandas

[Pandas] 7-2강_시계열 데이터 다루기(시계열 데이터셋)

가스오부시 2023. 4. 30. 02:36
728x90
반응형

1. 시계열 데이터셋

  • 판다스에서 시계열 데이터셋의 가장 기본적인 형태는 Index가 datetime 타입인 Series나 DataFrame 객체이다.
    • DateTimeIndex: datetime 타입의 index 타입

📍 DatatimeIndex indexing 과 slicing

  • Index가 Datetime 타입일 경우(DatetimeIndex) 날짜 시간의 각 요소들(ex: 년도, 월, 시간등등)을 이용해 다양한 조회가 가능하다.
# 부분일치 조회
s['2022']  # 2022년 원소들
s['2022-02'] # 2022년 2월 원소들
>>>
2022-02-01    1.867558
2022-02-02   -0.977278
2022-02-03    0.950088
2022-02-04   -0.151357
dtype: float64
s.index.year.isin([2022,2023])
>>>
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True])
s[(s.index.month == 2) & s.index.year.isin([2022,2023])]
>>>
2022-02-01    1.867558
2022-02-02   -0.977278
2022-02-03    0.950088
2022-02-04   -0.151357
2023-02-01    1.494079
2023-02-02   -0.205158
2023-02-03    0.313068
2023-02-04   -0.854096
dtype: float64
s[s.index.day == 3] # ~ 3일인 인덱스 조회
>>>
2022-01-03    0.978738
2022-02-03    0.950088
2022-03-03    0.144044
2023-01-03    0.443863
2023-02-03    0.313068
2023-03-03    0.864436
dtype: float64

🌓  slicing

  • 부분 매칭(날짜/시간의 특정 요소만으로 매칭)으로 slicing이 가능하다.
s['2022-02-02':'2023-01-03']  #start, stop 포함.
s['2022-02-02':'2023-01-03':3]
>>>
2022-02-02   -0.977278
2022-03-01   -0.103219
2022-03-04    1.454274
2023-01-03    0.443863
dtype: float64
df.loc['2012-01': '2012/02': 5]


📍 DateOffsets ( pd_date.range( ) )

🌓  DateOffset 이용 메소드 ( pd.date_range( ), .first( ) )

  • pd.date_range()
    • 동일한 간격 일시로 구성된(고정빈도)의 DatetimeIndex 생성한다.
    • DatetimeIndex
      • 일시 타입의 Index
    • 주요 매개변수
      • start: str 또는 datetime 형식 - 시작 날짜
      • end: str 또는 datetime 형식 - 종료 날짜
      • period: 생성할 개수
        • start에서 end까지 periods에 지정한 개수에 맞춰 등분한 날짜로 구성된 DatetimeIndex를 반환한다.
        • end 대신 period로
      • freq: str 또는 DateOffsets - 빈도 기준
      • periods와 freq는 둘중 하나만 사용한다. 둘다 생략하면 일별로 생성한다.
    # date_range()
    import pandas as pd
    pd.date_range(start='2022-01', end='2022-02') #default 간격:  날짜기준
    pd.date_range(start='2022-01', end='2022-02', periods=3) # 3등분한 분위의 날짜
    pd.date_range(start='2022-01', periods=3, freq='3ys') # 3ys: 3년
    >>>
    DatetimeIndex(['2022-01-01', '2025-01-01', '2028-01-01'], dtype='datetime64[ns]', freq='3AS-JAN')
    • y: YearEnd
    • ys: YearStart
    • 3ys: 3년
    • m: 1달
    • ms: 밀리초
    • H: 1시간
    • B: 1일
    • Q: 3개월
    • W: 일요일
    • W-요일: 월~일요일
    # 시리즈의 값으로 사용.
    pd.Series(pd.date_range('2020', '2023', freq='W-TUE'))
    >>>
    0     2020-01-07
    1     2020-01-14
    2     2020-01-21
    3     2020-01-28
    4     2020-02-04
             ...    
    151   2022-11-29
    152   2022-12-06
    153   2022-12-13
    154   2022-12-20
    155   2022-12-27
    Length: 156, dtype: datetime64[ns]
    # T 분  (3분 10초))
    s = pd.Series(range(455),index=pd.date_range('2023/01/01', '2023/01/01 23:59:59', freq='3T10S'))
    s
    >>>
    2023-01-01 00:00:00      0
    2023-01-01 00:03:10      1
    2023-01-01 00:06:20      2
    2023-01-01 00:09:30      3
    2023-01-01 00:12:40      4
                          ... 
    2023-01-01 23:45:00    450
    2023-01-01 23:48:10    451
    2023-01-01 23:51:20    452
    2023-01-01 23:54:30    453
    2023-01-01 23:57:40    454
    Freq: 190S, Length: 455, dtype: int64
  • first(offset)
    • offset 빈도의 앞의 N개 행을 조회한다.
# first()
s.first('900S')
s.first('20T')
s.first('3H')
>>>
2023-01-01 00:00:00     0
2023-01-01 00:03:10     1
2023-01-01 00:06:20     2
.
.
.
2023-01-01 02:47:50    53
2023-01-01 02:51:00    54
2023-01-01 02:54:10    55
2023-01-01 02:57:20    56
Freq: 190S, dtype: int64

📍 데이터 shift ( .shift( ) )

  • DatetimeIndex의 index는 그대로 두고 데이터를 앞 또는 뒤로 이동시킨다.
  • DataFrame/Series객체.shift() 이용
    • 매개변수
      • periods=1 : 이동할 기간 (기본값 1)
      • freq: 이동시킬 날짜/시간의 단위. DateOffset 객체/alias, timedelta
s = pd.Series(range(10, 15), index=pd.date_range('2022/01/01', '2022/01/05'))
>>>
2022-01-01    10
2022-01-02    11
2022-01-03    12
2022-01-04    13
2022-01-05    14
Freq: D, dtype: int64
s.shift(2)
>>>
2022-01-01     NaN
2022-01-02     NaN
2022-01-03    10.0
2022-01-04    11.0
2022-01-05    12.0
Freq: D, dtype: float64
s.shift(-2)
>>>
2022-01-01    12.0
2022-01-02    13.0
2022-01-03    14.0
2022-01-04     NaN
2022-01-05     NaN
Freq: D, dtype: float64
s.shift(freq='3MS')
>>>
2022-04-01    10
2022-04-01    11
2022-04-01    12
2022-04-01    13
2022-04-01    14
dtype: int64
# 전날 대비 값이 어떻게 변화했는지?
(s/s.shift(1) - 1)* 100
>>>
2022-01-01          NaN
2022-01-02    10.000000
2022-01-03     9.090909
2022-01-04     8.333333
2022-01-05     7.692308
Freq: D, dtype: float64

📍 resample()을 이용한 집계

  • resample()은 시계열 데이터를 지정한 구간별로 나눠서 집계할 수 있도록 grouping 한다.
  • groupby() 로 묶을 수도 있지만 DatetimeIndex의 경우 resample이 더 편리하다.
    • 매개변수
      • rule: group으로 묶을 기준을 offset으로 지정한다.
      • closed : "left" 또는 "right" - 간격의 시작과 끝중 어느부분을 포함시킬지(닫을지)를 설정. "left"가 기본으로 왼쪽은 포함하고 오른쪽은 포함되지 않는다.
      • on : 기준 컬럼을 지정한다. Index가 아니라 datetime 타입의 열(컬럼)을 기준으로 resample 할 때 사용
s = pd.Series(range(1, 21), index=pd.date_range('2000/01', periods=20, freq='T')) # 분 단위로 20개 값
>>>
2000-01-01 00:00:00     1
2000-01-01 00:01:00     2
2000-01-01 00:02:00     3
..
2000-01-01 00:16:00    17
2000-01-01 00:17:00    18
2000-01-01 00:18:00    19
2000-01-01 00:19:00    20
Freq: T, dtype: int64
# s.resample('10T')  # 10분 기준을 gz나눈다.
# s.resample('10T').mean()   # closed=left(기본) :   [00:00 ~ 10:00), [10:00 ~ 20:00), [20:00 ~ 30) ....
# s.resample('10T', closed='right').mean()   # (50 ~ 00], (00 ~ 10], (10 ~ 20]  # 둘다 시작을 inde로 사용
s.resample('10T', closed='right').sum()
>>>
2021-12-31 23:50:00    10
2022-01-01 00:00:00     0
2022-01-01 00:10:00     0
2022-01-01 00:20:00     0
2022-01-01 00:30:00     0
                       ..
2022-01-04 23:10:00     0
2022-01-04 23:20:00     0
2022-01-04 23:30:00     0
2022-01-04 23:40:00     0
2022-01-04 23:50:00    14
Freq: 10T, Length: 577, dtype: int64
d.resample('5t', on='time')['cnt'].sum()  # on으로 datetime타입 컬럼을 지정.
d.resample('5t', on='time')['cnt'].agg(['mean', 'sum'])

df.groupby(pd.Grouper(freq='Q'))['Close'].mean()
df.groupby([pd.Grouper(freq='Q'), 'Volume'])['Close'].mean()
>>>
Date        Volume  
2012-03-31  4175000     61.790001
            5173100     62.220001
            5480600     61.880001
            5501000     61.900002
            5710800     60.650002
                          ...    
2016-12-31  14321300    71.389999
            16779500    71.099998
            17844800    70.980003
            20110300    69.360001
            23440300    69.190002
Name: Close, Length: 1258, dtype: float64

📍 기간 이동 집계

  • 현재값을 기준으로 N개씩 묶어서 집계를 한다.
    • 예) 이동평균 구하기
  • rolling(window, min_periods=None)
    • window: 범위. 정수
    • min_periods: 집계할 최소 개수. 생략하면 window size로 지정.
    • center: bool - 집계결과를 window의 중간에 둘지 여부. 기본값은 False로 레이블이 창 맨 뒤에 둔다.
    moving_avg = df['Close'].rolling(window=5).mean() # 종가의 5일 이동 평균
    moving_avg2 = df['Close'].rolling(window=20).mean()  # 20일 이동 평균
    # moving_avg.head(60)
    moving_avg2.head(60)
    >>>
    Date
    2012-01-03          NaN
    2012-01-04          NaN
    2012-01-05          NaN
    2012-01-06          NaN
    2012-01-09          NaN
    2012-01-10          NaN
    2012-01-11          NaN
    2012-01-12          NaN
    2012-01-13          NaN
    2012-01-17          NaN
    2012-01-18          NaN
    2012-01-19          NaN
    2012-01-20          NaN
    2012-01-23          NaN
    2012-01-24          NaN
    2012-01-25          NaN
    2012-01-26          NaN
    2012-01-27          NaN
    2012-01-30          NaN
    2012-01-31    60.235500
    2012-02-01    60.328000
    ..
    2012-03-20    59.724000
    2012-03-21    59.822001
    2012-03-22    59.927501
    2012-03-23    60.025500
    2012-03-26    60.162501
    2012-03-27    60.270501
    2012-03-28    60.376000
    Name: Close, dtype: float64
    moving_avg3 = df['Close'].rolling(window=20, min_periods=3).mean() 
    moving_avg3
    >>>
    Date
    2012-01-03          NaN
    2012-01-04          NaN
    2012-01-05    59.820000
    2012-01-06    59.615000
    2012-01-09    59.528000
                    ...    
    2016-12-23    70.825000
    2016-12-27    70.750500
    2016-12-28    70.647499
    2016-12-29    70.588999
    2016-12-30    70.511500
    Name: Close, Length: 1258, dtype: float64

 

반응형