본문 바로가기
IT/Data Analysis with python

시계열_2

by Cyber_ 2024. 7. 7.

5. 기간과 기간 연산

며칠, 몇 개월, 몇 분기, 몇 해 같은기간은 pandas.Period 클래스로 표현할 수 있으며 클래스를 생성할 때 문자열이나 정수, 빈도가 필요하다.

p = pd.Period("2011", frea="A-DEC")

1) Period의 빈도 변환

Period와 PeriodIndex 객체는 asfreq 메서드를 사용해 다른 빈도로 변환할 수 있다.

p = pd.Period("2011", frea="A-DEC")
p.asfreq("M", how="start")

Period('2011', 'A-DEC')는 전체 기간을 가리키는 일종의 커서로 생각할 수 있고 이를 월간으로 나눌 수 있다. 회계연도 마감이 12월이 아닌 경우에는 월간 빈도가 달라진다.

p = pd.Period("2011", freq="A-JUN")
p.asfreq("M", how="start")
p.asfreq("M", how="end")

만약 매년 마지막 영업일을 사용하고 싶다면 "B"를 사용해 해당 기간의 종료 지점을 지정할 수 있다.

periods = pd.Period_range("2006", "2009", freq="A-DEC")
ts = pd.Series(np.random.standard_normal(len(periods)), index=periods)
ts.asfreq("M",how="start")
ts.asfreq("B",how="end")

2) 분기 빈도

판다스는 12가지 모든 경우의 수를 지원하며 분기 빈도는 Q-JAN 부터 Q-DEC 까지다.

p = pd.Period("2014Q4", freq="Q-JAN")
p.asfreq("D", how="start")
p4pm = (p.asfreq("B", how="end") - 1).asfreq("T", how="start") + 16 * 60

to_timestamp 메서드는 기본적으로 해당 기간의 시작 Timestamp를 반환한다.

3) 타임스탬프와 기간 서로 변환하기

타입스탬프로 색인된 Series와 DataFrame 객체는 to_period 메서드를 사용해서 Period로 변환 가능하다.

dates = pd.date_range("2000-01-01", periods=3, freq="M"
ts = pd.Series(np.random.standard_normal(3), index=dates)
pts = ts.to_period

여기서 말하는 기간은 겹치지 않는 시간상의 간격을 뜻하므로 주어진 빈도에서 타임스탬프는 하나의 기간에만 속한다. 새로운 PeriodIndex의 빈도는 기본적으로 타임스탬프 값을 통해 추론되지만 지원되는 빈도를 직접 지정할 수도 있다. 결과에 중복되는 기간이 나오더라도 문제가 되지 않는다.
기간을 타임스탬프로 변환하려면 DatetimeIndex를 반환하는 to_timestamp 메서드를 이용한다.

4) 배열로 PeriodIndex 생성하기

고정된 빈도를 갖는 데이터셋은 종종 여러 열에 걸쳐 기간에 대한 정보를 함께 저장하기도 한다. 예를 들어 거지경제학 데이터셋에는 연도와 분기가 서로 다른 열에 존재한다.
PeriodIndex에 빈돗값과 함께 전다랗면 이를 조합해서 DataFrame에서 사용할 수 있는 색인을 만들 수 있다.

6. 리샘플링과 빈도 변환

리샘플링은 시계열의 빈도를 변환하는 과정을 일컫는다. 높은 빈도의 데이터를 낮은 빈도로 집계하는 것을 다운램플링이라고 하며 반대 과정을 업샘플링이라고 부른다. 모든 샘플링이 이 두가지 범주에 속하는 것은아니다. 예를 들어 W-WED를 W-FRI로 변경하는 것은 업샘플링도 다운샘플링도 아니다.
판다스 객체는 resample 메서드를 가지며 빈도 변환과 관련된 모든 작업에서 유용하게 사용된다. resample은 groupby와 비슷한 API를 가지고 있는데 resample을 호출해서 데이터를 그룹 짓고 집계 함수를 적용하는 식이다.

1) 다운샘플링

다운샘플링은 시계열 데이터를 규칙적이고 낮은 빈도로 집계한다. 집계할 데이터는 고정 빈도를 가질 필요가 없으며 잘라낸 시계열 조각의 크기를 원하는 빈도로 정의한다. resample을 사용해서 데이터를 다운샘플링할 때 고려해야 할 사항이 몇 가지 있다.

  • 각 간격의 양 끝 중에서 어느 쪽을 닫아둘지 closed
  • 집계하려는 구간의 레이블을 간격의 시작으로 하지 끝으로 할지
dates = pd.date_range("2000-01-01", periods=12, freq="T")
ts = pd.Series(np.arrange(len(dates)), index=dates)
ts.resample("5min").sum()
ts.resample("5min", closed="right").sum()
ts.resample("5min", closed="right", label="right").sum()

반환된 결과의 색인을 특정 크기만큼 이동시키고 싶다면 to_offset 메서드를 사용한다.

from pandas.tseries.frequencies import to_offset

result = ts.resample("5min", closed="right", label="right").sum()

result.index = result.index + to_offset("-1s")

금융 분야에서 시계열 데이터를 집계하는 아주 흔한 방식은 각 버킷에서 네 가지 값을 계산하는 것이다. 네 가지 값은 시가, 고가, 저가, 종가 이며 이를 OHLC(open, hign,low,close)라고 한다. ohlc 집계 함수를 사용하면 ohlc 값을 한 열에 담은 DataFrame을 얻을 수 있다.

ts = pd.Series(np.random.permutation(np.arrange(len(dates))), index=dates)
ts.resample("5min").ohlc()

2) 업샘플링과 보간

낮은 빈도에서 높은 빈도로 업샘플링할 때는 집계가 필요하지 않다.
asfreq메서드를 이용하여 6일 과 12일을 1일 단위로 업샘플링한다면 7,8,9,10,11일에 결측치가 발생할 것이다. 이 결측치는 ffill()을 통해 채울 수 있다. 특정 7,8,9일의 결측치만 채우도록 지접을 제한할 수 있다.

3) 기간 리샘플링

frame = pd.DataFrame(np.random.standard_normal((24,4)), index = pd.period_range("1-2000", "12_2001", freq = "M"), columns=["Colorado", "Texas", "New York", "Ohio"]

annual_frame=frame.resample("A-DEC").mean()
annual_frame.resample("Q-DEC").ffill()
annual_frame.resample("Q-DEC", convention="end").asfreq()

기간은 시간 범위를 참조하므로 업샘플링과 다운샘플링 규칙이 조금 더 엄격하다.

  • 다운샘플링의 경우 대상 빈도는 반드시 원본 빈도의 하위 기간이어야 한다.
  • 업샘플링의 경우 대상 빈도는 반드시 원본 빈도의 상위 기간이어야 한다.

위 조건을 만족하지 않으면 예외가 발생한다. 이 예외는 주로 분기별, 연간, 주간 빈도에서 발새앟며 예를 들어 Q-MAR로 정의된 기간은 A-MAR, A-JUN, A-SEP, A-DEC로만 이루어진다.

4) 그룹화된 시간 리샘플링

시계열 데이터의 경우 resample 메서드는 의미론적으로 시간 간격에 기반한 그룹 연산이다.

N = 15
times = pd.date_range("2017-05-20 00:00", freq="1min", periods=N)

df2 = pd.DataFrame({"time": times.repeat(3), "key": np.tile(["a", "b", "c"], N), "value": np.arange(N*3.)})

key의 각 값에 대해 동일한 리샘플링을 수행하려면 pandas.Grouper 객체를 사용한다. 그 다음 시간 색인을 설정하고 "key"와 time_key로 그룹화한 다음 집계한다.

time_key=pd.Grouper(freq="5min")
resapmled = (df2.set_index("time")
            .groupby(["key", time_key])
            .sum())

pandas.Grouper를 사용할 때 한 가지 제약 사항은 시간이 Series나 DataFrame의 색인 시간이어야 한다는 점이다.

7. 이동창 함수(moving window function)

시계열 연산에서 사용되는 배열 변형에서 중요한 요소는 움직이는 창이나 지수 가중과 함께 수행하는 통계와 여타 함수다. 이런 한수를 이용해 누락된 데이터로 인해 매끄럽지 않은 시계열 데이터를 매끄럽게 다듬을 수 있다. 이 책에선 이동창 함수로 부른다.

  • rolling 연산은 resample, groupby와 유사하게 작동한다. Series난 DataFrame에서 원하는 기간을 나타내는 window 값으로 호출할 수 있다.
  • rolling은 groupby와 비슷해 보이지만 그룹을 생성하는 대신 그룹핑할 수 있는 객체를 생성한다.
  • 확장창 평균을 구하려면 rolling 대신 expanding을 사용한다. 확장창 평균은 시계열 시작 지점에서부터 창의 크기가 시계열의 전체 크기가 될 때 까지 점점 창의 크기를 늘린다.

1) 지수 가중 함수

균등한 가중치를 갖는 관찰로 크기가 고정된 창을 사용하는 방법 대신, 감쇠 인자(decay factor) 상수에 더 많은 가중치를 주어 더 최근 값을 관찰하는 방법도 있다. 감쇠 인자 상수를 지정하는 여러 방법이 있지만 기간을 이용하는 방법응ㄹ 많이 사용한다.

  • 지수 가중 통꼐는 최근 값에 더 많은 가중치를 두는 방법이므로 균등 가중 방식에 비해 더 빠르게 변화를 수용한다.

판다스는 rolling, expanding 과 함께 사용할 수 있는 ewm 연산을 제공한다.

2) 이진 이동창 함수

상관관계와 공분산 같은 몇몇 통계 연산은 두 개의 시계열이 필요하다.

3) 사용자 정의 이동창 함수

rolling이나 다른 관련 메서드에 apply를 호출해 이동창에서 사용자 정의 연산을 수행할 수 있다. 예를 들어 rolling(...).quantile(q)로 표본 사분위수를 계산할 수 있는 것처럼 전체 표본에서 특정 값이 차지하는 백분위 점수를 구하는 함수를 작성할 수도 있다.

'IT > Data Analysis with python' 카테고리의 다른 글

시계열_1  (0) 2024.07.07
데이터 집계와 그룹 연산  (0) 2024.06.20
그래프와 시각화  (0) 2024.06.20
데이터 준비하기: 조인, 병합, 변형  (0) 2024.06.17
데이터 정제 및 준비  (1) 2024.06.14