Python(시계열)

짬그브·2025년 3월 5일

개요

시계열 데이터는 금융, 경제, 생태학, 물리학 등 여러 분야에서 사용되는 매우 중요한 구조화된 데이터이다.

시간상의 여러 지점을 관측하거나 측정할 수 있는 모든 것이 시계열이다.

-시간 내에서 특정 순간의 타임 스탬프

-2018년 9월이나 2017년 같은 고정된 시간

-시작과 끝이 타임 스탬프로 표시되는 시간 간격

-실험 혹은 경과시간

날짜, 시간 자료형

파이썬 표준 라이브러리에는 날짜와 시간 제어를 위한 datetime, time, calendar를 제공해준다.

date : 그레고리언 달력을 사용해서 날짜(년,월,일)을 저장한다.
time : 하루 중 시간을 시간, 분, 초, 마이크로초 단위로 저장한다.
datetime : 날짜와 시간을 같이 저장한다.
timedelta : 두 datetime 값 간의 차이(일,초,마이크로초)를 표현한다.

datetime 객체는 str 메서드나 strftime 메서드에 포맷 규칙을 넘겨 문자열로 나타낼 수 있다.

datetime 포맷 규칙

%Y : 네 자리 연도
%y : 두 자리 연도
%m : 두 자리 월 [01,12]
%d : 두 자리 일 [01,31]
%H : 24시 형식 시간 [00,23]
%I : 12시 형식 시간 [01,12]
%M : 두 자리 분 [00,59]
%S : 초
%w : 정수로 나타낸 요일 [0(일요일),6]
%f : %Y-%m-%d 형식에 대한 축약

from datetime import datetime

now = datetime.now()
print(now)
print('{}년 {}월 {}일'.format(now.year,now.month,now.day))

time1 = datetime(2015,2,22,10,20)
print(time1)
print(time1.strftime('%Y년도-%m월-%d일'))
print()

timestr = '2020-01-07'
time2 = datetime.strptime(timestr, '%Y-%m-%d')
print(time2)

from dateutil.parser import parse

print()
print(parse('2020-01-07'))
print(parse('Jan 31, 2020 10:45 PM'))


2025-03-05 16:40:04.292500
2025년 3월 5일
2015-02-22 10:20:00
2015년도-02월-22일

2020-01-07 00:00:00

2020-01-07 00:00:00
2020-01-31 22:45:00

시계열 기초

Pandas 에서 찾아 볼 수 있는 가장 기본적인 시계열의 종류는 파이썬 문자열이나 datetime 객체로 표현되는 타임스탬프로 색인된 Series 객체다

인덱싱,선택,부분 선택

TimeSeries 는 Series의 하위 클래스이므로 라벨에 기반해 데이터를 선택하고 인덱싱 하는데 있어서는 Series와 동일하게 동작한다.

중복된 색인을 갖는 시계열

from datetime import datetime
import pandas as pd
import numpy as np
np.random.seed(12345)

dates = [datetime(2024, 1, 1),datetime(2024, 1, 2),datetime(2024, 1, 3),
         datetime(2024, 1, 4),datetime(2024, 1, 5),datetime(2024, 1, 6),
         datetime(2024, 1, 7),datetime(2024, 1, 8)]

ts = pd.Series(np.random.randn(8), index=dates)
print(ts)
print()

print(ts['2024-01-03'])
print(ts['2024/01/03'])
print(ts['20240103'])
print(ts['01/03/2024'])
print(ts['01-03-2024'])


2024-01-01   -0.204708
2024-01-02    0.478943
2024-01-03   -0.519439
2024-01-04   -0.555730
2024-01-05    1.965781
2024-01-06    1.393406
2024-01-07    0.092908
2024-01-08    0.281746
dtype: float64

-0.5194387150567381
-0.5194387150567381
-0.5194387150567381
-0.5194387150567381
-0.5194387150567381

날자 범위, 빈도, 이동

Pandas 에서 일반적인 시계열은 불규칙적인 것으로 간주한다. 즉 고정된 빈도를 갖
지 않는다. 이를 위해 pandas는 리샘플링, 표준 시계열 빈도 모음, 빈도 추론, 그리
고 고정된 빈도의 날짜 범위를 위한 도구가 있다.

날짜 범위 생성

Pandas.date_range()

from datetime import datetime
import pandas as pd
import numpy as np
np.random.seed(12345)

ts2 = pd.Series(np.random.randn(1000),
                index=pd.date_range('1/1/2020',periods=1000))
print(ts2)
print()
print(ts2['2021'])
print()
print(ts2['2022-05'])
print(ts2['2022-05-01':'2022-05-10'])
print()

df1 = pd.DataFrame(np.random.randn(100,4),
                   index=pd.date_range('2020/1/1',periods=100,freq='W-WED'),
                   columns=['one','two','three','four'])
print(df1)
print()

print(pd.date_range(start='4/1/2020', end='6/1/2020'))
print(pd.date_range(end='6/1/2020',periods=20))
print(pd.date_range('1/1/2010','1/3/2010',freq='4h'))
print(pd.date_range('1/1/2020','1/3/2010',freq='1h30min'))
print(pd.date_range('1/1/2000','2/1/2000',freq='B'))
print(pd.date_range('1/1/2000','12/1/2000',freq='BME'))

2020-01-01   -0.204708
2020-01-02    0.478943
2020-01-03   -0.519439
2020-01-04   -0.555730
2020-01-05    1.965781
                ...   
2022-09-22    0.107657
2022-09-23   -0.139298
2022-09-24   -1.159926
2022-09-25    0.618965
2022-09-26    1.373890
Freq: D, Length: 1000, dtype: float64

2021-01-01   -1.610841
2021-01-02   -1.026621
2021-01-03    1.241573
2021-01-04   -0.156760
2021-01-05   -2.449096
                ...   
2021-12-27    1.578948
2021-12-28    0.000369
2021-12-29    0.900885
2021-12-30   -0.454869
2021-12-31   -0.864547
Freq: D, Length: 365, dtype: float64

2022-05-01    0.003193
2022-05-02   -2.595012
2022-05-03   -1.555569
2022-05-04    1.102996
2022-05-05    0.554737
2022-05-06   -1.289012
2022-05-07    0.385242
2022-05-08   -1.717292
2022-05-09   -1.018353
2022-05-10    0.051635
2022-05-11    0.503299
2022-05-12   -0.543186
2022-05-13   -0.506678
2022-05-14    0.729653
2022-05-15    0.434273
2022-05-16   -1.133674
2022-05-17    1.423953
2022-05-18    0.266352
2022-05-19   -0.854264
2022-05-20   -0.550597
2022-05-21   -0.619110
2022-05-22    1.038933
2022-05-23   -0.910611
2022-05-24    0.529953
2022-05-25   -0.008471
2022-05-26   -1.129038
2022-05-27    0.569854
2022-05-28   -0.863392
2022-05-29   -1.356144
2022-05-30   -0.057152
2022-05-31   -0.108621
Freq: D, dtype: float64
2022-05-01    0.003193
2022-05-02   -2.595012
2022-05-03   -1.555569
2022-05-04    1.102996
2022-05-05    0.554737
2022-05-06   -1.289012
2022-05-07    0.385242
2022-05-08   -1.717292
2022-05-09   -1.018353
2022-05-10    0.051635
Freq: D, dtype: float64

                 one       two     three      four
2020-01-01 -0.983505  0.930944 -0.811676 -1.830156
2020-01-08 -0.138730  0.334088  0.488675 -0.178098
2020-01-15  2.122315  0.061192  0.884111 -0.608506
2020-01-22 -0.072052  0.544066  0.323886 -1.683325
2020-01-29  0.526860  1.858791 -0.548419 -0.279397
...              ...       ...       ...       ...
2021-10-27  0.370548 -0.674167 -1.712340 -0.738151
2021-11-03  0.391813  1.763403 -0.054630 -0.656506
2021-11-10 -1.550087 -0.044347  0.681470 -0.953726
2021-11-17 -1.857016  0.449495 -0.061732  1.233914
2021-11-24  0.705830 -1.309077 -1.537380  0.531551

[100 rows x 4 columns]

DatetimeIndex(['2020-04-01', '2020-04-02', '2020-04-03', '2020-04-04',
               '2020-04-05', '2020-04-06', '2020-04-07', '2020-04-08',
               '2020-04-09', '2020-04-10', '2020-04-11', '2020-04-12',
               '2020-04-13', '2020-04-14', '2020-04-15', '2020-04-16',
               '2020-04-17', '2020-04-18', '2020-04-19', '2020-04-20',
               '2020-04-21', '2020-04-22', '2020-04-23', '2020-04-24',
               '2020-04-25', '2020-04-26', '2020-04-27', '2020-04-28',
               '2020-04-29', '2020-04-30', '2020-05-01', '2020-05-02',
               '2020-05-03', '2020-05-04', '2020-05-05', '2020-05-06',
               '2020-05-07', '2020-05-08', '2020-05-09', '2020-05-10',
               '2020-05-11', '2020-05-12', '2020-05-13', '2020-05-14',
               '2020-05-15', '2020-05-16', '2020-05-17', '2020-05-18',
               '2020-05-19', '2020-05-20', '2020-05-21', '2020-05-22',
               '2020-05-23', '2020-05-24', '2020-05-25', '2020-05-26',
               '2020-05-27', '2020-05-28', '2020-05-29', '2020-05-30',
               '2020-05-31', '2020-06-01'],
              dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2020-05-13', '2020-05-14', '2020-05-15', '2020-05-16',
               '2020-05-17', '2020-05-18', '2020-05-19', '2020-05-20',
               '2020-05-21', '2020-05-22', '2020-05-23', '2020-05-24',
               '2020-05-25', '2020-05-26', '2020-05-27', '2020-05-28',
               '2020-05-29', '2020-05-30', '2020-05-31', '2020-06-01'],
              dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2010-01-01 00:00:00', '2010-01-01 04:00:00',
               '2010-01-01 08:00:00', '2010-01-01 12:00:00',
               '2010-01-01 16:00:00', '2010-01-01 20:00:00',
               '2010-01-02 00:00:00', '2010-01-02 04:00:00',
               '2010-01-02 08:00:00', '2010-01-02 12:00:00',
               '2010-01-02 16:00:00', '2010-01-02 20:00:00',
               '2010-01-03 00:00:00'],
              dtype='datetime64[ns]', freq='4h')
DatetimeIndex(['2010-01-01 00:00:00', '2010-01-01 01:30:00',
               '2010-01-01 03:00:00', '2010-01-01 04:30:00',
               '2010-01-01 06:00:00', '2010-01-01 07:30:00',
               '2010-01-01 09:00:00', '2010-01-01 10:30:00',
               '2010-01-01 12:00:00', '2010-01-01 13:30:00',
               '2010-01-01 15:00:00', '2010-01-01 16:30:00',
               '2010-01-01 18:00:00', '2010-01-01 19:30:00',
               '2010-01-01 21:00:00', '2010-01-01 22:30:00',
               '2010-01-02 00:00:00', '2010-01-02 01:30:00',
               '2010-01-02 03:00:00', '2010-01-02 04:30:00',
               '2010-01-02 06:00:00', '2010-01-02 07:30:00',
               '2010-01-02 09:00:00', '2010-01-02 10:30:00',
               '2010-01-02 12:00:00', '2010-01-02 13:30:00',
               '2010-01-02 15:00:00', '2010-01-02 16:30:00',
               '2010-01-02 18:00:00', '2010-01-02 19:30:00',
               '2010-01-02 21:00:00', '2010-01-02 22:30:00',
               '2010-01-03 00:00:00'],
              dtype='datetime64[ns]', freq='90min')
DatetimeIndex(['2000-01-03', '2000-01-04', '2000-01-05', '2000-01-06',
               '2000-01-07', '2000-01-10', '2000-01-11', '2000-01-12',
               '2000-01-13', '2000-01-14', '2000-01-17', '2000-01-18',
               '2000-01-19', '2000-01-20', '2000-01-21', '2000-01-24',
               '2000-01-25', '2000-01-26', '2000-01-27', '2000-01-28',
               '2000-01-31', '2000-02-01'],
              dtype='datetime64[ns]', freq='B')
DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-28',
               '2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',
               '2000-09-29', '2000-10-31', '2000-11-30'],
              dtype='datetime64[ns]', freq='BME')

빈도와 날짜 오프셋

Pandas에서 빈도는 기본 빈도와 배수의 조합으로 이루어진다.
시간 빈도는 Hour 클래스를 사용하여 표현할 수 있다.

데이터 시프트

시프트는 데이터를 시간 축에서 앞이나 뒤로 이동하는 것을 말한다.
shift 메서드는 이 기능을 제공한다.

기간과 기간 연산

몇일, 몇 개월, 몇 분기, 몇 해 같은 기간은 period 클래스로 표현 할 수 있으며 문자열이나 정수 그리고 표의 빈도를 가지고 생성한다.

period의 빈도 변환

기간과 periodIndex 객체는 asfreq 메서드를 통해 다른 빈도로도 변환 할 수 있다.

분기 빈도

분기 데이터는 재정, 금융 및 다른 분야에서 표준으로 사용된다.
Pandas 는 12 가지 모든 경우의 수를 지원하면 분기 빈도는 Q-Jan부터 Q-DEC 까지다

타임스탬프와 기간 변환

타임스탬프로 색인된 Series와 DataFrame 객체는 to_period 메서드를 사용해서 Period로 변환할 수 있다.

배열을 이용한 periodIndex 생성

리샘플링과 변환

리샘플링은 시게열의 빈도를 변환하는 과정을 말한다. 상위 빈도의 데이터를 하위 빈도로 집계 하는 것을 다운 샘플링이라고 하면 반대의 과정을 업 샘플링이라고 한다.

Pandas.resample()

freq : 원하는 리샘플링 빈도를 가리키는 문자열이나 DataOffset
how='mean' : 'mean','np.max'같은 집계된 값을 생성하는 함수나 함수의 배열
axis=0 : 리샘플링을 수행할 축
fill_method=None : 업샘플링 시에 사용할 보간 방법.
closed='right' : 다운샘플링 시에 각 간격의 어느 쪽을 포함할지를 가리킨다.
label='right' : 다운샘플링 시에 집계된 결과의 라벨을 결정한다.
limit=None : 보간법 사용 시 보간을 적용할 최대 기간이다.
kind = None : 기간('period')별 혹은 타임스탬프별로 집계할 것인지 구분
convention=None : 기간을 리 샘플링할 때 하위 빈도 기간에서 상위 빈도로 변환할 때의 방식


import pandas as pd
import numpy as np

np.random.seed(12345)

date = pd.date_range('1/1/2020',periods=100,freq='D')
ts = pd.Series(np.random.randn(100), index=date)
print(ts)
print()

rsdata = ts.resample('ME')
print(rsdata)
print()

for data in rsdata:
    print(data, end='\n\n')
print()

print(rsdata.mean())
print()

frame= pd.DataFrame(np.random.randn(2,4),
                    index=pd.date_range('1/1/2020',periods=2,freq='W-WED'),
                    columns=['one','two','three','four'])
print(frame)
print()

rsdata2 = frame.resample('D')
for data in rsdata2:
    print(data, end='\n\n')

print()
print(frame.resample('D').ffill())
print()
print(frame.resample('D').ffill(limit=2))


2020-01-01   -0.204708
2020-01-02    0.478943
2020-01-03   -0.519439
2020-01-04   -0.555730
2020-01-05    1.965781
                ...   
2020-04-05    0.795253
2020-04-06    0.118110
2020-04-07   -0.748532
2020-04-08    0.584970
2020-04-09    0.152677
Freq: D, Length: 100, dtype: float64

DatetimeIndexResampler [freq=<MonthEnd>, axis=0, closed=right, label=right, convention=start, origin=start_day]

(Timestamp('2020-01-31 00:00:00'), 2020-01-01   -0.204708
2020-01-02    0.478943
2020-01-03   -0.519439
2020-01-04   -0.555730
2020-01-05    1.965781
2020-01-06    1.393406
2020-01-07    0.092908
2020-01-08    0.281746
2020-01-09    0.769023
2020-01-10    1.246435
2020-01-11    1.007189
2020-01-12   -1.296221
2020-01-13    0.274992
2020-01-14    0.228913
2020-01-15    1.352917
2020-01-16    0.886429
2020-01-17   -2.001637
2020-01-18   -0.371843
2020-01-19    1.669025
2020-01-20   -0.438570
2020-01-21   -0.539741
2020-01-22    0.476985
2020-01-23    3.248944
2020-01-24   -1.021228
2020-01-25   -0.577087
2020-01-26    0.124121
2020-01-27    0.302614
2020-01-28    0.523772
2020-01-29    0.000940
2020-01-30    1.343810
2020-01-31   -0.713544
Freq: D, dtype: float64)

(Timestamp('2020-02-29 00:00:00'), 2020-02-01   -0.831154
2020-02-02   -2.370232
2020-02-03   -1.860761
2020-02-04   -0.860757
2020-02-05    0.560145
2020-02-06   -1.265934
2020-02-07    0.119827
2020-02-08   -1.063512
2020-02-09    0.332883
2020-02-10   -2.359419
2020-02-11   -0.199543
2020-02-12   -1.541996
2020-02-13   -0.970736
2020-02-14   -1.307030
2020-02-15    0.286350
2020-02-16    0.377984
2020-02-17   -0.753887
2020-02-18    0.331286
2020-02-19    1.349742
2020-02-20    0.069877
2020-02-21    0.246674
2020-02-22   -0.011862
2020-02-23    1.004812
2020-02-24    1.327195
2020-02-25   -0.919262
2020-02-26   -1.549106
2020-02-27    0.022185
2020-02-28    0.758363
2020-02-29   -0.660524
Freq: D, dtype: float64)

(Timestamp('2020-03-31 00:00:00'), 2020-03-01    0.862580
2020-03-02   -0.010032
2020-03-03    0.050009
2020-03-04    0.670216
2020-03-05    0.852965
2020-03-06   -0.955869
2020-03-07   -0.023493
2020-03-08   -2.304234
2020-03-09   -0.652469
2020-03-10   -1.218302
2020-03-11   -1.332610
2020-03-12    1.074623
2020-03-13    0.723642
2020-03-14    0.690002
2020-03-15    1.001543
2020-03-16   -0.503087
2020-03-17   -0.622274
2020-03-18   -0.921169
2020-03-19   -0.726213
2020-03-20    0.222896
2020-03-21    0.051316
2020-03-22   -1.157719
2020-03-23    0.816707
2020-03-24    0.433610
2020-03-25    1.010737
2020-03-26    1.824875
2020-03-27   -0.997518
2020-03-28    0.850591
2020-03-29   -0.131578
2020-03-30    0.912414
2020-03-31    0.188211
Freq: D, dtype: float64)

(Timestamp('2020-04-30 00:00:00'), 2020-04-01    2.169461
2020-04-02   -0.114928
2020-04-03    2.003697
2020-04-04    0.029610
2020-04-05    0.795253
2020-04-06    0.118110
2020-04-07   -0.748532
2020-04-08    0.584970
2020-04-09    0.152677
Freq: D, dtype: float64)


2020-01-31    0.304166
2020-02-29   -0.404772
2020-03-31    0.021947
2020-04-30    0.554480
Freq: ME, dtype: float64

                 one       two     three      four
2020-01-01 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-08 -0.482573 -0.036264  1.095390  0.980928

(Timestamp('2020-01-01 00:00:00'),                  one      two     three      four
2020-01-01 -1.565657 -0.56254 -0.032664 -0.929006)

(Timestamp('2020-01-02 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-03 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-04 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-05 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-06 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-07 00:00:00'), Empty DataFrame
Columns: [one, two, three, four]
Index: [])

(Timestamp('2020-01-08 00:00:00'),                  one       two    three      four
2020-01-08 -0.482573 -0.036264  1.09539  0.980928)


                 one       two     three      four
2020-01-01 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-02 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-03 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-04 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-05 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-06 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-07 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-08 -0.482573 -0.036264  1.095390  0.980928

                 one       two     three      four
2020-01-01 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-02 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-03 -1.565657 -0.562540 -0.032664 -0.929006
2020-01-04       NaN       NaN       NaN       NaN
2020-01-05       NaN       NaN       NaN       NaN
2020-01-06       NaN       NaN       NaN       NaN
2020-01-07       NaN       NaN       NaN       NaN
2020-01-08 -0.482573 -0.036264  1.095390  0.980928

다운 샘플링

Resample()을 사용해서 데이터를 다운샘플링할 때 고려해야 할 사항

-각 간격의 양 끝 중에서 열어둘 쪽
-집계하려는 구간의 라벨을 간격의 시작으로 할지 끝으로 할지의 여부

profile
+AI to AI+

0개의 댓글