[Python pandas] Downsampling 으로 시계열 데이터 집계 시 좌/우의 포함여부(closed), 라벨 이름(label) 설정하기
Python 분석과 프로그래밍/Python 데이터 전처리 2019. 12. 30. 17:47지난번 포스팅에서는 분기 단위의 기간 날짜 범위 만들기, 그리고 period와 timestamp 간 변환하기 (https://rfriend.tistory.com/506)에 대해서 소개하였습니다.
Python pandas의 resample() 메소드를 사용하면
(a) 더 세부적인 주기(higher frequency)의 시계열 데이터를 더 낮은 주기로 집계/요약을 하는 Downsampling (예: 초(seconds) --> 10초(10 seconds), 일(day) --> 주(week), 일(day) --> 월(month) 등)과,
(b) 더 낮은 주기의 시계열 데이터를 더 세부적인 주기의 데이터로 변환하는 Upsampling (예: 10초 --> 1초, 주 --> 일, 월 --> 주, 년 --> 일 등)을 할 수 있습니다.
이번 포스팅에서는 pandas의 resample() 메소드로 Downsampling 을 할 때 (예: 1초 단위 주기 --> 10초 단위/ 1분 단위/ 1시간 단위 주기로 resampling)
(1) 왼쪽과 오른쪽 중에서 포함 위치 설정 (closed)
(2) 왼쪽과 오른쪽 중에서 라벨 이름 위치 설정 (label)
하는 방법을 소개하겠습니다.
포함 위치와 라벨 이름 설정 시 왼쪽과 오른쪽 중에서 어디를 사용하느냐에 대한 규칙은 없구요, (a) 명확하게 인지하고 있고 (특히, 여러 사람이 동시에 협업하여 작업할 경우), (b) product의 코드 전반에 걸쳐서 일관되게(consistant) 사용하는 것이 필요합니다. (SQL로 DB에서 두 그룹으로 나누어서 시계열 데이터 전처리 작업을 하다가 나중에서야 포함 여부와 라벨 규칙이 서로 다르다는 것을 확인하고, 이를 동일 규칙으로 수정하느라 시간을 소비했던 경험이 있습니다. -_-;;;)
예제로 사용하기 위해 1분 단위 주기의 6개 데이터 포인트를 가지는 간단한 시계열 데이터 pandas Series 를 만들어보겠습니다.
import pandas as pd # generate dates range dates = pd.date_range('2020-12-31', periods=6, freq='min') # or freq='T' dates
# create Series ts_series = pd.Series(range(len(dates)), index=dates) ts_series [Out]: 2020-12-31 00:00:00 0
2020-12-31 00:01:00 1
2020-12-31 00:02:00 2
2020-12-31 00:03:00 3
2020-12-31 00:04:00 4
2020-12-31 00:05:00 5
Freq: T, dtype: int64 |
이제 '1 분 단위 주기'(freq='min')인 시계열 데이터를 '2초 단위 주기'(freq='2min' or freq='2T')로 resample() 메소드를 이용해서 Downsampling을 해보도록 하겠습니다.
이때 포함 위치 (a) closed='left' (by default) 또는 (b) closed='right' 과 라벨 이름 위치 (c) label='left' (by default) 또는 label='right' 의 총 4개 조합별로 나누어서 Downsampling 결과를 비교해보겠습니다. 집계 함수는 sum()을 공통으로 사용하겠습니다.
(1) By default: Downsampling 시 closed='left', label='left' |
Downsampling 할 때 왼쪽과 오른쪽 중에서 한쪽은 포함(inclusive, default: 'left')되고 나머지 한쪽은 포함되지 않습니다. 그리고 Downsampling으로 resampling 된 후의 라벨 이름의 경우 default는 가장 왼쪽(label='left')의 라벨을 사용합니다.
ts_series = pd.Series(range(len(dates)), index=dates) ts_series [Out]: 2020-12-31 00:00:00 0
2020-12-31 00:01:00 1
2020-12-31 00:02:00 2
2020-12-31 00:03:00 3
2020-12-31 00:04:00 4
2020-12-31 00:05:00 5
Freq: T, dtype: int64 # by default, left side of bin interval is closed # by default, left side of bin inverval is labeled ts_series.resample('2min').sum()
# same result with above ts_series.resample('2min', closed='left', label='left').sum() [Out]: 2020-12-31 00:00:00 1
2020-12-31 00:02:00 5
2020-12-31 00:04:00 9
Freq: 2T, dtype: int64 |
(2) Downsampling 시 closed='right', label='left' |
ts_series = pd.Series(range(len(dates)), index=dates) ts_series [Out]: 2020-12-31 00:00:00 0
2020-12-31 00:01:00 1
2020-12-31 00:02:00 2
2020-12-31 00:03:00 3
2020-12-31 00:04:00 4
2020-12-31 00:05:00 5
Freq: T, dtype: int64 # right side of bin interval is closed using closed='right' ts_series.resample('2min', closed='right', label='left').sum()
|
(3) Downsampling 시 closed='left', label='right' |
ts_series = pd.Series(range(len(dates)), index=dates) ts_series [Out]: 2020-12-31 00:00:00 0
2020-12-31 00:01:00 1
2020-12-31 00:02:00 2
2020-12-31 00:03:00 3
2020-12-31 00:04:00 4
2020-12-31 00:05:00 5
Freq: T, dtype: int64 # right side of bin inverval is labeled using label='right' ts_series.resample('2min', closed='left', label='right').sum() [Out]: 2020-12-31 00:02:00 1
2020-12-31 00:04:00 5
2020-12-31 00:06:00 9
Freq: 2T, dtype: int64 |
(4) Downsampling 시 closed='right', label='right' |
아래의 예는 디폴트와 정반대로 시계열 구간의 오른쪽을 포함시키고(closed='right') 라벨 이름도 오른쪽 구간 값(label='right')을 가져다가 Downsampling 한 경우입니다.
ts_series [Out]: 2020-12-31 00:00:00 0
2020-12-31 00:01:00 1
2020-12-31 00:02:00 2
2020-12-31 00:03:00 3
2020-12-31 00:04:00 4
2020-12-31 00:05:00 5
Freq: T, dtype: int64 # right side of bin interval is closed using closed='right' # right side of bin inverval is labeled using label='right' ts_series.resample('2min', closed='right', label='right').sum() 2020-12-31 00:00:00 0
2020-12-31 00:02:00 3
2020-12-31 00:04:00 7
2020-12-31 00:06:00 5 Freq: 2T, dtype: int64 |
(5) 시계열 pandas DataFrame에 대해 Downsaumpling 시 포함(closed), 라벨(label) 위치 설정하기 |
지금까지 위의 (1), (2), (3), (4)는 pandas Series를 대상으로 한 예제였습니다. DatatimeIndex를 index로 가지는 시계열 데이터 pandas DataFrame 도 Series와 동일한 방법으로 Downsampling 하면서 포함, 라벨 위치를 설정합니다.
import pandas as pd # generate dates range dates = pd.date_range('2020-12-31', periods=6, freq='min') dates [Out]: DatetimeIndex(['2020-12-31 00:00:00', '2020-12-31 00:01:00',
'2020-12-31 00:02:00', '2020-12-31 00:03:00',
'2020-12-31 00:04:00', '2020-12-31 00:05:00'],
dtype='datetime64[ns]', freq='T') # create timeseries DataFrame ts_df = pd.DataFrame({'val': range(len(dates))}, index=dates) ts_df [Out]:
# (a) Downsampling using default setting ts_df.resample('2min').sum() [Out]:
# (b) Downsampling using closed='right' ts_df.resample('2min', closed='right').sum() [Out]:
# (c) Downsampling using label='right' ts_df.resample('2min', label='right').sum() [Out]:
# (d) Downsampling using closed='right', label='right' ts_df.resample('2min', closed='right', label='right').sum() [Out]:
|
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요.