Python pandas 시계열 데이터 전처리

2025. 9. 30. 17:50·Basic Data Analysis

시계열 데이터 전처리는 원시 시계열 데이터를 분석 또는 모델링에 적합한 구조화된 형식으로 변환하는 과정입니다. Pandas 라이브러리는 이러한 작업을 위한 도구를 제공합니다.

 

Concept Scalar Class Array Class Data Type Creation Method
날짜와 시간 (Date times) Timestamp DatetimeIndex datetime64[ns], tz to_datetime, date_range
시간 간격 (Time deltas) Timedelta TimedeltaIndex timedelta64[ns] to_timedelta, timedelta_range
기간 (Time spans) Period PeriodIndex period[freq] Period, period_range
날짜 오프셋 (Date offsets) DateOffset None None DateOffset

 

 

  • Date times (Timestamp / DatetimeIndex): 특정 시점(날짜와 시간)을 나타내며 시계열 데이터의 기본입니다.
  • Time deltas (Timedelta / TimedeltaIndex): 두 시점 사이의 절대적인 기간(Duration)을 나타냅니다.
  • Time spans (Period / PeriodIndex): 특정 빈도(freq)로 정의된 기간을 나타냅니다.
  • Date offsets (DateOffset): 달력상의 규칙을 따르는 상대적 기간(예: 영업일 기준 3일 후) 계산에 사용됩니다.

Pandas에서 시계열 데이터를 다룰 때 시간을 일반적인 데이터(컬럼)로 두는 대신 DataFrame의 인덱스(색인)로 설정하는 것이 가장 일반적이고 강력한 방법입니다. 이를 DatetimeIndex라고 부릅니다.

 

또한 Pandas에서는 시간 또는 날짜 데이터(datetime64[ns], timedelta64[ns])에 대한 결측값(Missing Value)을 나타내기 위해 특별히 정의한 값입니다. 일반적인 결측값인 NaN(Not a Number)이 숫자형 데이터의 결측치를 나타내는 것과 대칭되는 개념입니다.

 

to_datetime

pandas.to_datetime() 함수는 강력하게 날짜 및 시간 형식의 데이터를 datetime 객체로 변환해주는 핵심 도구입니다.

pandas.to_datetime(arg, errors='raise', 
			dayfirst=False, 
                    yearfirst=False, 
                    utc=False, 
                    format=None, 
                    exact=<no_default>, 
                    unit=None, 
                    infer_datetime_format=<no_default>, 
                    origin='unix', cache=True)

 

 

- arg: int, float, str, datetime, list, tuple, 1d array, Series, DataFrame/dict like

- errors: ignore, raise, coerce

- dayfirst, yearfirst: bool

- utc: bool

- format: str, ISO801, mixed

- unit: str D,s,ms,us,ns

- origin: unix, Timestamp convertible

 

1. 컬럼 조합을 통한 날짜/시간 객체 생성 (Structured Input)

 

pd.to_datetime()은 DataFrame이나 딕셔너리(dict) 형태의 구조화된 입력을 받아 여러 컬럼을 조합하여 하나의 날짜/시간(Timestamp) 객체를 생성할 수 있습니다.

>>> df = pd.DataFrame({'year': [2015, 2016], 'month': [2, 3], 'day': [4, 5]}) 
>>> pd.to_datetime(df) 
0   2015-02-04 
1   2016-03-05 
dtype: datetime64[ns]

 

2. 정수(Integer) 값의 유닉스 시간 변환 (unit 파라미터)

 

정수(Integer)가 입력되면, pd.to_datetime()은 기본적으로 그 정수를 경과된 시간으로 해석하고 이를 Timestamp로 변환합니다. 이때 unit 파라미터를 사용하여 해당 정수의 시간 단위를 명시합니다.

>>> pd.to_datetime(1490195805, unit='s')
Timestamp('2017-03-22 15:16:45')

>>> pd.to_datetime(1490195805433502912, unit='ns')
pd.to_datetime(1490195805433502912, unit='ns')

 

3. 기준 시점 변경 (origin 파라미터)

 

unit을 사용하여 정수 값을 경과 시간으로 해석할 때, 시간 계산의 시작점(Epoch)을 설정할 수 있습니다. 기본은 유닉스 시간의 시작점인 '1970-01-01' 자정(UTC)부터 경과된 시간으로 계산합니다.

 

아래의 코드는 1960-01-01을 기준으로 일(Day, D) 단위로 계산 시작하는 것입니다. 

>>> pd.to_datetime([1, 2, 3], unit='D', origin=pd.Timestamp('1960-01-01')) 
DatetimeIndex(['1960-01-02', '1960-01-03', '1960-01-04'], 
              dtype='datetime64[ns]', freq=None)

 

4. 시간대(Timezone) 표준화 (utc 파라미터)

 

pd.to_datetime()은 다양한 시간대 정보를 포함하는 문자열을 UTC(협정 세계시) 기준으로 표준화할 수 있습니다.

>>> pd.to_datetime(['2018-10-26 12:00 -0530', '2018-10-26 12:00 -0500'], utc=True) 
DatetimeIndex(['2018-10-26 17:30:00+00:00', '2018-10-26 17:00:00+00:00'], 
              dtype='datetime64[ns, UTC]', freq=None)

 

date_range

date_range() 함수는 일정한 빈도(Frequency)를 가진 연속적인 날짜 및 시간(DatetimeIndex)을 생성하는 데 사용되는 핵심 함수입니다. 시계열 데이터 분석에서 인덱스를 만들거나, 누락된 시점을 채우는 데 매우 유용합니다.

 

date_range 함수는 시작, 끝, 또는 기간 중 최소 두 가지 정보를 제공해야 DatetimeIndex를 생성할 수 있습니다.

pandas.date_range(start=None, 
	end=None, 
	periods=None, 
	freq=None, 
	tz=None, 
	normalize=False, 
	name=None, 
	inclusive='both', 
	*, 
	unit=None, 
	**kwargs)

 

- start: str, datetime like

- end: str, datetime like

- periods: int

- freq: str, Timedelta, datetime.timedelta, DateOffset, default 'D' (빈도설정)

- normalize: True인 경우 start/end를 자정으로 맞춤

- inclusive: both, neither, left, right

- unit: str

 

DatetimeIndex

Pandas가 DatetimeIndex를 사용하면 날짜와 시간을 문자열이나 표준 datetime 객체로 전달받아도 자동으로 해당 시점이나 기간을 인식하고 데이터를 추출해줍니다.

 

예시 내용을 통해서 알아봅시다. 먼저 시계열 데이터의 기반을 마련합니다.

>>> start = datetime.datetime(2025, 1, 1) 
>>> end = datetime.datetime(2025, 12, 31) 
>>> rng = pd.date_range(start, end, freq="BME")

 

DatetimeIndex는 일반적인 Python 리스트나 NumPy 배열처럼 정수 기반의 슬라이싱을 적용할 수 있습니다. 여기서는 2 간격으로 데이터를 추출했습니다.

>>> ts = pd.Series(range(len(rng)), index=rng)
>>> ts[::2].index
DatetimeIndex(['2025-01-31', '2025-03-31', '2025-05-30', '2025-07-31', 
               '2025-09-30', '2025-11-28'], 
              dtype='datetime64[ns]', freq=‘2BME')

 

Pandas는 '5/30/2025'와 같은 날짜 문자열을 전달받으면, 이를 자동으로 Timestamp 객체로 파싱하고 정확히 일치하는 인덱스를 찾아 해당 값을 반환합니다. 이처럼 사용자가 날짜/시간 포맷을 직접 맞추지 않아도 되는 유연성을 제공합니다.

>>> ts['5/30/2025'] 
np.float64(0.37875684785407626)

 

마지막으로 datetime.datetime(2025, 11, 15)와 같이 Python의 표준 datetime 객체를 슬라이싱 경계로 사용할 수 있습니다.

>>> ts[datetime.datetime(2025, 11, 15):] 
2025-11-28    1.180612 
2025-12-31    0.554140 
Freq: BME, dtype: float64

 

시계열 데이터의 인덱스(DatetimeIndex)를 사용하여 데이터를 조회할 때, 사용자가 입력한 시간 문자열의 정밀도(해상도)에 따라 Pandas가 하나의 정확한 시점을 찾을지, 아니면 특정 기간을 포괄하는 범위(슬라이스)를 반환할지 결정할 수 있습니다.

 

즉, 사용자가 인덱스에 있는 데이터보다 덜 구체적인 시간 정보(즉, 더 낮은 해상도)를 입력하면, Pandas는 해당 문자열이 포괄하는 전체 기간을 자동으로 슬라이싱하여 반환합니다.

>>> ts['2025']
2025-01-31     0
2025-02-28     1
2025-03-31     2
2025-04-30     3
2025-05-30     4
2025-06-30     5
2025-07-31     6
2025-08-29     7
2025-09-30     8
2025-10-31     9
2025-11-28    10
2025-12-31    11
Freq: BME, dtype: int64

 

Resample

resample()은 고빈도 데이터를 저빈도 데이터로 집계하거나(Downsampling), 저빈도 데이터를 고빈도 데이터로 확장(Upsampling)할 때 사용됩니다.

 

resample()은 기본적으로 지정된 새로운 시간 주기(예: 5분)를 기준으로 데이터를 그룹화(GroupBy)하고, 이 그룹화된 데이터에 대해 통계 함수를 적용할 수 있는 Resampler 객체를 반환합니다.

 

아래의 코드는 Pandas의 date_range 함수와 resample 메서드를 사용하여 초(second) 단위의 시계열 데이터를 5분 단위로 집계(다운샘플링)하는 과정을 보여줍니다.

 

2025년 1월 1일부터 총 900개의 시점을 생성하여 초(second) 단위 간격으로 생성합니다. (총 900초 = 15분 동안의 데이터)

rng = pd.date_range("1/1/2025", periods=900, freq="s")

 

0부터 499 사이의 정수 난수 900개를 생성하여 위에서 생성한 초 단위의 시간 인덱스(rng)를 지정하여, 초 단위 시계열 데이터 ts를 만듭니다.

ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)

 

초 단위 데이터(ts)를 5분("5Min") 단위로 그룹화하는 Resampler 객체를 생성합니다. 그룹화된 각 5분 단위 데이터 블록에 대해 평균을 계산하여 최종 결과를 반환합니다.

>>> ts.resample("5Min").mean() 
2025-01-01 00:00:00    250.456667
2025-01-01 00:05:00    253.023333
2025-01-01 00:10:00    225.970000
Freq: 5min, dtype: float64

 

resample의 인자는 다음과 같습니다.

DataFrame.resample(rule, 
	axis=<no_default>, 
    closed=None, 
    label=None, 
    convention='start', 
    kind=<no_default>, 
    on=None, 
    level=None, 
    origin='start_day', 
    offset=None, 
    group_keys=False)

 

- rule: DateOffset, Timedelta, str

- closed: right for ME, YE, QE, BME, BA, BQE, W, left for the others

- label: right, left

- on: str

- level: str, int

- origin: Timestamp, epoch, start, startday, end, endday

- offset: Timedelta, str

- groupkeys: boo

 

Shift

DataFrame.shift(periods=1, 
	freq=None, 
    axis=0, 
    fill_value=<no_default>, 
    suffix=None
)

 

- periods: int, Sequence (이동시킬 step 정도) 

- freq: DataOffset, tseries.offsets, timedelta, str. 값이 주어지는 여부에 따라 동작이 달라짐.

- axis: 0 or Index, 1 or columns

- fill value: object (결측값 채우기)

- suff: str. periods가 sequence로 주어졌을 때 유효.

 

pd.date_range("2020-01-01", "2020-01-04")에 의해 2020년 1월 1일부터 1월 4일까지의 일별 시계열 인덱스가 설정됩니다.

df = pd.DataFrame({"Col1": [10, 20, 15, 30], "Col2": [13, 23, 18, 33], "Col3": [17, 27, 22, 37]}, index=pd.date_range("2020-01-01", "2020-01-04"))
df

 

이 코드는 DataFrame df의 모든 데이터를 periods=2 만큼 아래로 이동시킵니다.

df.shift(periods=2)

 

 

데이터를 시간 축(index)이 아닌 컬럼 축으로 이동시킵니다.

df.shift(periods=1, axis="columns")

 

freq 파라미터를 사용하여 달력상의 빈도를 기반으로 데이터를 이동시킵니다. freq 파라미터를 사용하면 periods 인자는 무시됩니다.

df.shift(periods=3, freq="D")

 

Rolling

 

롤링은 시계열 데이터에서 고정된 크기의 윈도우(Window, 창)를 순차적으로 이동시키면서, 그 윈도우 내의 데이터에 대해 통계 함수를 적용하는 분석 방법입니다. 이렇게 계산된 값을 이동 통계(Moving Statistics)라고 부르며, 가장 흔한 예가 이동 평균(Moving Average)입니다.

DataFrame.rolling(window, 
	min_periods=None, 
    center=False, 
    win_type=None, 
    on=None, 
    axis=<no_default>, 
    closed=None, 
    step=None, 
    method='single'
)

 

- window: int, timedelta, str, offset, BaseIndexer (롤링의 크기)

- minperiods: int. windows로 입력되는 값의 type에 따라서 default 값이 달라짐.

- center: bool. Right edge를 label로.

- wintype: str. None이 주어지면 모든 값이 동일하게 다루어짐.

- on: str. DataFrame에서 Column name.

- closed: right, left, both, neither (윈도우의 경계)

- step: int

- method: single, table

 

아래와 같은 데이터프레임을 만듭니다. 

df_time = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]},
                       index=[pd.Timestamp('20130101 09:00:00'),
                              pd.Timestamp('20130101 09:00:02'),
                              pd.Timestamp('20130101 09:00:03'),
                              pd.Timestamp('20130101 09:00:05'),
                              pd.Timestamp('20130101 09:00:06')])

 

window=2는 데이터 포인트 2개를 포함하는 윈도우를 의미합니다. (시간 간격 무시)

df_time.rolling('2s').sum()

 

window='2s'는 2초의 시간 간격을 윈도우로 정의합니다. (데이터 개수 무시)

df_time.rolling(2).sum()

 

 

위의 두 예시 코드가 비슷해보이나 rolling의 인자로 int 2와 str '2s'의 차이점을 확인할 수 있습니다.

시간 간격(Offset) 문자열로 지정했을 때 min_periods는 1로 설정됩니다. 지정된 시간 간격 내에 유효한 데이터 포인트가 최소 1개만 있으면 롤링 계산(평균, 합계 등)을 수행합니다. 그러나 정수(Integer)로 윈도우를 지정할 경우 min_periods는 윈도우의 크기(정수 값)와 동일하게 설정됩니다.  롤링 계산을 수행하려면 지정한 윈도우 크기 2를 채우는 충분한 데이터 개수가 필요하다는 의미입니다. 그렇지않으면 NaN을 반환합니다. 

 

Expanding

DataFrame.expanding(min_periods=1, 
	axis=<no_default>, 
    method='single'
)

 

- minperiods: int

- axis: 0 or index, 1 or columns

- method: single, table

 

expanding()은 데이터 세트의 시작점부터 현재 시점까지의 모든 관측치를 포함하는 윈도우를 사용합니다. 데이터가 추가될 때마다 윈도우 크기가 1씩 커지며, 윈도우 내의 모든 값에 대해 지정된 통계량을 계산합니다.

 

아래의 코드는 누적 평균(Cumulative Mean)을 계산하며, min_periods=2 조건이 적용됩니다.

df = pd.DataFrame({"B" : [0, 1, 2, np.nan, 4]})
df.expanding(2).mean()

 

누적 합계(Cumulative Sum)를 계산하지만, min_periods=3 조건이 적용됩니다.

df.expanding(3).sum()

 

'Basic Data Analysis' 카테고리의 다른 글

데이터 문해력  (1) 2026.02.11
Python 따릉이 데이터 분석  (0) 2025.09.30
Python Pandas를 활용한 데이터 분석 실습  (0) 2025.09.26
Python Pandas  (0) 2025.09.25
'Basic Data Analysis' 카테고리의 다른 글
  • 데이터 문해력
  • Python 따릉이 데이터 분석
  • Python Pandas를 활용한 데이터 분석 실습
  • Python Pandas
David0903
David0903
  • David0903
    별별 코딩
    David0903
  • 전체
    오늘
    어제
    • 전체 (92)
      • Microsoft Azure (33)
      • FastAPI (8)
      • YOLO (4)
      • C++ (27)
      • Deep Learning (12)
      • Business Data Analysis (2)
      • Basic Data Analysis (5)
      • Statistics (1)
      • Data Analysis (0)
      • Computer Science (0)
      • InfoSec (0)
  • 블로그 메뉴

    • 홈
  • 링크

    • 블로그
  • 공지사항

  • 인기 글

  • 태그

    c++
    원-핫 인코딩
    ROS
    생성자
    deep learing
    object
    모델 설계
    데이터 다루기
    call by value
    k겹 교차
    Friend
    operator overloading
    call by reference
    모델
    학습셋
    경사하강법
    deep learning
    상속
    테스트셋
    딥러닝
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
David0903
Python pandas 시계열 데이터 전처리
상단으로

티스토리툴바