Programming Language/Python

판다스(Pandas) shift를 활용해서 Sliding Window 만들기

TwinParadox 2020. 2. 7. 18:54
728x90

시계열 데이터를 활용해서 수치를 예측하는 모델을 만들 때 사용하는 다양한 방법 중에 Sliding Window를 활용해 과거 데이터를 feature로 사용하는 방법이 있다. 이 방법은 시계열 데이터를 활용한 예측에서 과거 데이터들을 바탕으로 예측을 수행하므로 과거 데이터들을 포함하는 feature를 만들어줘야 한다.

 

이렇게 feature로 사용할 과거 기간에 대해서 lookBack, lag, delay 등 다양한 명칭으로 부르는데, 통상적으로 lag이라는 명칭을 많이 사용하는 것 같다. 예시 코드에서는 lookBack으로 작성했다.

 

다양한 방법으로 lag을 줘서 Sliding Window를 만들 수 있지만, 손수 Sliding Window와 lag 개념을 넣으려면 거기에 맞게 행을 추가해줘야 하고, 데이터 이동도 시켜줘야 한다. 이걸 수작업으로 만들 수야 있겠지만, pandas를 이용하면 그럴 필요가 없다.

 

pandas의 shift와 반복문 하나면 아주 간단하게 만들어낼 수 있다 .경험 상 pandas.Dataframe.shift를 이용하는 것이 가장 편했던 터라, pandas의 shift()를 활용해서 간단하게 만드는 방법을 정리해봤다.

 

 

 

pandas.DataFrame.shift — pandas 1.0.1 documentation

The scalar value to use for newly introduced missing values. the default depends on the dtype of self. For numeric data, np.nan is used. For datetime, timedelta, or period data, etc. NaT is used. For extension dtypes, self.dtype.na_value is used. Changed i

pandas.pydata.org

 

 

이 글에서 다룬 데이터는 아래와 같은 구조로 이루어져 있다. 단변량으로 예측하는 경우에는 SPI를 가공해 SPI를 예측하고, 다변량으로 예측하는 경우 SPI는 물론 CPI, M2, MMI, CBD 지표까지 다 고려한다. 결론적으로 시계열 데이터를 활용해서 SPI를 예측하는 것이다.

 

 

활용 데이터의 모습

 

 

pandas.DataFrame.shift(period, freq, axis, fill_value)

 

 

shift로 단순히 시간 지연만 만들어내려면, freq나 axis는 따로 건드릴 필요가 없다. 어떤 값을 채워야 한다면 fillna를 사용해도 좋고, 그게 아니라면 shift 과정에서 생긴 새로운 feature에 대한 값을 바로 지정해주는 fill_value를 사용해도 좋다.

 

pandas.shift를 이용해서 위 데이터를 가지고 단변량과 다변량 예측 과정에 사용할 수 있는 데이터로 가공하는데 사용했다. 데이터를 만드는 함수는 아래와 같이 구현해봤다.

 

def makeSlidingWindows(origin_train, origin_test, train, test, lookBack=2, multiVariate=False, gtruthName='SPI'):

    if not multiVariate:
        train_df = pd.DataFrame(train[:,0], index=origin_train.index)
        test_df = pd.DataFrame(test[:,0], index=origin_test.index)
        train_df.columns = origin_train.columns
        test_df.columns = origin_test.columns
        column_list = list(train_df)
        
        for s in range(1, lookBack + 1):
            tmp_train = train_df[column_list].shift(s)
            tmp_test = test_df[column_list].shift(s)

            tmp_train.columns = "shift_" + tmp_train.columns + "_" + str(s)
            tmp_test.columns = "shift_" + tmp_test.columns + "_" + str(s)

            train_df[tmp_train.columns] = train_df[column_list].shift(s)
            test_df[tmp_test.columns] = test_df[column_list].shift(s)

        return train_df, test_df

    else:
        train_df = pd.DataFrame(train, index=origin_train.index)
        test_df = pd.DataFrame(test, index=origin_test.index)
        train_df.columns = origin_train.columns
        test_df.columns = origin_test.columns
        column_list = list(train_df)

        for s in range(1, lookBack + 1):
            tmp_train = train_df[column_list].shift(s)
            tmp_test = test_df[column_list].shift(s)

            tmp_train.columns = "shift_" + tmp_train.columns + "_" + str(s)
            tmp_test.columns = "shift_" + tmp_test.columns + "_" + str(s)

            train_df[tmp_train.columns] = train_df[column_list].shift(s)
            test_df[tmp_test.columns] = test_df[column_list].shift(s)  

 

방식은 간단하다. 1부터 lag까지 전 구간에 대해서 shift를 수행해주고 이 shift한 column의 이름을 지정해주고서 shift한 결과를 원본 dataframe에 column으로 추가해주면 된다.

 

 

shift 결과

 

위 코드를 수행한 결과다. 여기서는 lag(코드에서는 lookBack)을 1만 준 상태로, 데이터셋을 가공이 끝나면 이처럼 첫번째 shift_ 데이터에 nan이 들어가 있고 그 다음부터 데이터가 들어가 있다. 이런 모양새를 보면 알 수 있듯이, 이렇게 lag을 적용하면 적용한 lag의 사이즈만큼 원래 예측하려는 기간보다 예측 기간이 줄어든다. 이 부분을 해결할 방법을 찾아보고 있지만 마땅한 방법이 없다.

 

어쨌든 pandas.Dataframe.shift를 이용해서 SlidingWindow를 만들어낼 수 있다.

728x90
728x90