[Python.TimeSeries] Date와 DateTime 심화 - Rolling and Shift

2021. 2. 24. 05:00Python과 머신러닝/TimeSeries & DateTime

0. 이전 포스트

 

1. Data Input

In [1]:import pandas as pd 
       import os
In [2]:df = pd.read_csv('bike_demand_train.csv',
                        parse_dates=['datetime']) 
       df.set_index('datetime', inplace=True) 
       df
Out[2]:

Out[2]

  • 시계열 데이터를 분석하다 보면 '지난달의 데이터가 이번 달의 데이터에 어떤 영향을 미쳤는지' 확인해야 하는 경우가 대부분이다.
  • 그렇기 때문에 이번 포스트에서는 Rolling과 Shift라는 개념/기능을 통해서 어떻게 데이터를 전 처리할 수 있는지 계획이다.

 

 

2. 월별 평균 구하기

In [3]:monthly_mean = df['count'].resample('M').mean() 
       monthly_mean
Out[3]:datetime
       2011-01-31     54.645012 
       2011-02-28     73.641256
       2011-03-31     86.849776
       2011-04-30     111.026374
       2011-05-31     174.809211
       2011-06-30     196.877193
       2011-07-31     203.614035 
       2011-08-31     182.666667
       2011-09-30     174.622517 
       2011-10-31     174.773626 
       2011-11-30     155.458333 
       2011-12-31     134.173246 
       2012-01-31     124.353201 
       2012-02-29     145.646154 
       2012-03-31     208.276923
       2012-04-30     257.455947
       2012-05-31     264.109649
       2012-06-30     287.186404
       2012-07-31     267.037281 
       2012-08-31     285.570175 
       2012-09-30     292.598684
       2012-10-31     280.508772
       2012-11-30     231.980220
       2012-12-31     217.054825
       Freq: M, Name: count, dtype: float64

 

3. Shift를 이용해서 월별 데이터를 수정하기

In [4]:monthly_mean_shift = monthly_mean.shift(periods=2, fill_value=0)
       monthly_mean_shift

Out[4]:datetime  
       2011-01-31    0.000000 
       2011-02-28    0.000000
       2011-03-31    54.645012
       2011-04-30    73.641256
       2011-05-31    86.849776 
       2011-06-30    111.026374
       2011-07-31    174.809211
       2011-08-31    196.877193
       2011-09-30    203.614035
       2011-10-31    182.666667 
       2011-11-30    174.622517 
       2011-12-31    174.773626 
       2012-01-31    155.458333 
       2012-02-29    134.173246 
       2012-03-31    124.353201 
       2012-04-30    145.646154
       2012-05-31    208.276923
       2012-06-30    257.455947
       2012-07-31    264.109649
       2012-08-31    287.186404
       2012-09-30    267.037281
       2012-10-31    285.570175 
       2012-11-30    292.598684
       2012-12-31    280.508772 
       Freq: M, Name: count, dtype: float64
  • monthly_mean.shift(periods=2, fill_value=0)
    • 2단계에서 resample을 통해 monthly_mean을 구해서, 월별 데이터를 구했다.
    • 이 데이터에 shift를 하는데 2개 단위로 shift를 한다.
    • fill_value=0 : 앞에서 2개를 shift 하면 첫 2개는 값이 없을 테니, 0으로 채운다.
    • 이렇게 하여 기존의 1월 데이터는 3월에, 2월 데이터는 4월에 등등 이어서 채워지게 된다.

 

 

 

 

 

 

 

4. 기존 월평균과 shift 월평균 하나의 그래프로 표현하기

In [5]:df_monthly = pd.DataFrame(monthly_mean, columns=['count']) 
In [6]:df_monthly['2_shift_demand'] = monthly_mean_shift
       df_monthly
In [7]:df_monthly.plot()

Out[6]
Out[7]

  • 이 둘을 하나의 df_monthly라는 dataframe에 넣고 plot 하면 위와 같이 결과가 나온다.
  • 결국 동일한 데이터를 2개월 단위로 미뤄놓고 봄으로써, 2달 전의 데이터가 현재 데이터에 어떤 영향을 미치는지 시각적으로 볼 수도 있고, 추후에는 Machine Learning에 필요한 데이터로 사용할 수 있다.

 

5. Moving Average (이동 평균)을 위한 Data 전처리

In [8]:monthly_mean = df['count'].resample('D').mean().fillna(0) 
       monthly_mean
Out[8]:datetime
       2011-01-01 41.041667
       2011-01-02 34.826087 
       2011-01-03 61.318182
       2011-01-04 67.913043
       2011-01-05 69.565217 
       ... 
       2012-12-15 210.291667
       2012-12-16 157.750000
       2012-12-17 191.041667
       2012-12-18 231.541667 
       2012-12-19 219.458333 
       Freq: D, Name: count, Length: 719, dtype: float64

In [9]:monthly_mean_shift = monthly_mean.rolling(window=30,).mean()

In [10]:df_monthly = pd.DataFrame(monthly_mean, columns=['count']) 
        df_monthly['30_mean_average'] = monthly_mean_shift 
        df_monthly.head(31)
Out[10]:

Out[10]

  • Moving Average (이동 평균) : 시계열 데이터에는 노이즈가 많기 때문에, 구간을 겹쳐서 평균을 구하고,
  • 그 평균들의 추세를 보는 것이 더 정확한 분석이 된다.
  • 위 표로 예를 들어 설명하면, 좌측의 count는 기존에도 봤던 일별 count의 평균이다. 
  • 우측의 30_mean_average는 30일간의 데이터의 평균을 낸 것이다.
  • 그래서 2011-01-30의 30_mean_average는 1월 1일부터 30일까지의 평균을 낸 것이고,
  • 2011-01-31의 average는 1월 2일부터 31일까지의 평균을 낸 것이다.
  • 이렇게 이동 평균을 구하게 되면, 한 데이터의 노이즈가 발생하더라도 추세에 큰 영향을 주지 않아서 분석이 훨씬 용이해지고 정확해진다.

 

6. 그래프로 표현하기

In [11]:df_monthly.plot(figsize=(20,10))
Out[11]:

Out[11]

  • 파란색 선은 일별 평균값이다. 보다시피 중간중간 결측치도 많아서 추세라고 할 것이 없다.
  • 그에 비해 30일 이동평균은 결측치와 노이즈를 감안하여 계산되기 때문에 훨씬 더 분석이 용이하고, 유의미한 통찰을 얻을 수 있도록 돕는다.
반응형