지난 포스팅에서는 '날짜-시간 index'를 가지는 pandas Series, DataFrame에서 '날짜-시간 index'를 기준으로 시계열 데이터를 indexing, slicing, selection 하는 방법(https://rfriend.tistory.com/499)을 소개하였습니다. 



이번 포스팅에서는 Python pandas 의 Series, DataFrame에서 


(1) 시계열 데이터 index 중복 여부를 확인 (check duplicated time series indices)

(2) 시계열 데이터 중복 index 시 첫번째 행만 가져오기 (keep the first row from duplicated time series indices)

(3) 시계열 데이터 index 별 group by 집계 (group by aggregation using time series indices)


하는 방법을 소개하겠습니다. 





예제로 사용할 간단할 시계열 데이터 pandas Series를 만들어보겠습니다. 


이번 포스팅의 주제가 '중복된 시계열 데이터 인덱스 (Duplicated DatatimeIndex)' 이므로 append() 메소드를 사용하여 '2019-12-01', '2019-12-02' 일의 인덱스를 추가함으로써 중복 인덱스를 만들어보았습니다. 


그리고, 시계열 데이터는 시간 순서대로 정렬된 상태로 저장된 데이터이므로 sort_values() 메소드로 내림차순 정렬(sort in ascending order)을 해주었습니다. 



import pandas as pd


# generate dates from 2019-12-01 to 2019-12-10

date_idx = pd.date_range('2019-12-01', periods=10)

date_idx

[Out]:

DatetimeIndex(['2019-12-01', '2019-12-02', '2019-12-03', '2019-12-04', '2019-12-05', '2019-12-06', '2019-12-07', '2019-12-08', '2019-12-09', '2019-12-10'], dtype='datetime64[ns]', freq='D')


# append duplicated dates index

date_idx = date_idx.append(pd.DatetimeIndex(['2019-12-01', '2019-12-02']))

date_idx

[Out]:
DatetimeIndex(['2019-12-01', '2019-12-02', '2019-12-03', '2019-12-04',
               '2019-12-05', '2019-12-06', '2019-12-07', '2019-12-08',
               '2019-12-09', '2019-12-10', '2019-12-01', '2019-12-02'],
              dtype='datetime64[ns]', freq=None)



# Time Series with duplicated dates index

series_ts = pd.Series(range(len(date_idx))

                      , index=date_idx.sort_values())


series_ts

[Out]:
2019-12-01     0
2019-12-01     1
2019-12-02     2
2019-12-02     3
2019-12-03     4
2019-12-04     5
2019-12-05     6
2019-12-06     7
2019-12-07     8
2019-12-08     9
2019-12-09    10
2019-12-10    11
dtype: int64


 



  (1) 시계열 데이터 index 중복 여부를 확인 (check duplicated DatetimeIndex indices)


날짜-시간 index 의 중복 여부를 확인하는 방법에는 여러가지가 있는데요, 그중에서 가장 간단한 방법은 유일한 값 여부(is unique?)를 확인할 수 있는 is_unique 메소드를 사용하는 것입니다. '유일한 값'으로만 되어있으면 True, '중복 값'이 포함되어 있으면 False를 반환합니다. 



# duplication check

series_ts.index.is_unique

[Out]: False

 



index 중복 여부를 확인하는 다른 방법으로는 index에 대해 nunique() 메소드를 사용해서 유일한 값의 index 개수를 세어보고, len(series_ts)로 Series의 전체 행의 개수를 세어보아서 이 둘의 값이 같은지를 확인해보는 것입니다. 만약 중복 index가 있다면 이 둘의 개수가 다르겠지요. 



# duplication check

series_ts.index.nunique() == len(series_ts)

[Out]: False

 




행 단위까지 내려가서 확인을 해보고 싶으면 groupby(level=0) 으로 첫번째인 날짜-시간 index 기준으로 Group By 개수 집계를 해봐서 날짜-시간 index별 행 개수가 '1' 초과인 행을 살펴보면 됩니다. 


< 날짜-시간 index별 행의 개수 집계 >


# count group by time series index

series_ts.groupby(level=0).count() # or size()

[Out]:
2019-12-01    2
2019-12-02    2
2019-12-03    1
2019-12-04    1
2019-12-05    1
2019-12-06    1
2019-12-07    1
2019-12-08    1
2019-12-09    1
2019-12-10    1
dtype: int64


< 날짜-시간 index별 행의 개수가 1 보다 큰 경우, 즉 중복 index 인 모든 행 선택 >


# selecting duplicated index rows

series_ts[series_ts.groupby(level=0).count() > 1]

[Out]:

2019-12-01 0 2019-12-01 1 2019-12-02 2 2019-12-02 3 dtype: int64

 





  (2) 시계열 데이터 중복 index 시 첫번째 행만 가져오기 

       (keep the first row from duplicated time series indices)


날짜-시간 index 중복인 경우 첫번째 행을 가져오려면 groupby(level=0).first(), 마지막 행을 가져오려면 groupby(level=0).last() 메소드를 사용합니다. 



# selecting FIRST row in case duplicated index

series_ts.groupby(level=0).first()

[Out]:
2019-12-01     0
2019-12-02     2
2019-12-03     4
2019-12-04     5
2019-12-05     6
2019-12-06     7
2019-12-07     8
2019-12-08     9
2019-12-09    10
2019-12-10    11
dtype: int64

 


# selecting LAST row in case duplicated index

series_ts.groupby(level=0).last()

[Out]:
2019-12-01     1
2019-12-02     3
2019-12-03     4
2019-12-04     5
2019-12-05     6
2019-12-06     7
2019-12-07     8
2019-12-08     9
2019-12-09    10
2019-12-10    11
dtype: int64






  (3) 시계열 데이터 index 별 group by 집계 

      (group by aggregation using time series indices)


groupby(level=0) 으로 날짜-시간 index 기준으로 GroupBy operation을 수행할 수 있으므로, groupby().agg() 로 집계하고자 하는 함수를 agg() 괄호 안에 넣어서 집계할 수 있습니다. 아래 예제에서는 날짜-시간 index별로 행의 개수(size), 합계(sum), 평균(mean), 최소값(min), 최대값(max) 를 구해보았습니다. (중복 index 시 groupby.agg() 함수 적용하여 집계/요약함)


참고로, groupby().agg() 로 여러개의 집계함수를 적용한 경우 DataFrame을 반환합니다. (vs. 한개의 집계함수만 groupby(level=0).size() 처럼 사용한 경우 Series 반환)



# aggregating size, sum, mean, min, max by group by time series index

series_ts.groupby(level=0).agg(['size', 'sum', 'mean', 'min', 'max'])

[Out]:

sizesummeanminmax
2019-12-01210.501
2019-12-02252.523
2019-12-03144.044
2019-12-04155.055
2019-12-05166.066
2019-12-06177.077
2019-12-07188.088
2019-12-08199.099
2019-12-0911010.01010
2019-12-1011111.01111

 



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)



728x90
반응형
Posted by Rfriend
,