0Pricing
Pandas & NumPy Academy · 강의

시프트와 지연 특성

shift()로 지연 열과 선행 열을 만들고 diff()로 기간별 변화를 계산하며 백분율 변화를 구합니다.

시프트와 지연 특성은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Lag Features Matter

In time series analysis, the value at a previous time step (a lag) is often one of the best predictors of the current value. For example, yesterday's sales are informative about today's sales. Creating lag columns lets you use historical values as features in machine learning models or in statistical analysis of autocorrelation. Pandas provides shift() to create lag features in a single vectorised call.

shift(): Moving Values Forward or Backward

Series.shift(n) moves all values down by n positions (positive n creates a lag), filling the first n rows with NaN. Passing a negative n moves values up (creates a lead, shifting future values back to the current row). The index remains unchanged — only the values are displaced.

import pandas as pd
import numpy as np

df = pd.DataFrame(
    {'sales': [100, 120, 115, 130, 140, 125]},
    index=pd.date_range('2024-01-01', periods=6, freq='D')
)

# Lag-1: yesterday's sales
df['sales_lag1'] = df['sales'].shift(1)
# Lead-1: tomorrow's sales (shifted up)
df['sales_lead1'] = df['sales'].shift(-1)
print(df)

Creating Multiple Lag Columns

You typically create several lag features at once for machine learning — lag-1, lag-7 (same day last week), and lag-30 (same day last month). The most readable way is to create them in a loop and assign each to a new column. The resulting DataFrame has the original series plus all its lagged versions ready for modelling.

for lag in [1, 2, 3, 7]:
    df[f'sales_lag{lag}'] = df['sales'].shift(lag)

print(df.columns.tolist())
# ['sales', 'sales_lag1', 'sales_lag2', 'sales_lag3', 'sales_lag7']

# Drop rows with NaN from the largest lag period
df_model = df.dropna()
print('Ready for modelling, shape:', df_model.shape)

shift() with freq for Time-Based Shifting

Instead of shifting by an integer number of rows, you can shift by a time offset using the freq parameter. df.shift(1, freq='ME') shifts the index forward by one month-end, keeping the values in place but changing the index. This is useful for aligning two time series that are offset by a fixed time period without rearranging the values.

monthly = pd.Series(
    [100, 120, 115],
    index=pd.date_range('2024-01-31', periods=3, freq='ME')
)

# Shift the index forward by 1 month (values stay, index moves)
shifted_index = monthly.shift(1, freq='ME')
print('Original index:', monthly.index.tolist())
print('Shifted index: ', shifted_index.index.tolist())
# Original: [2024-01-31, 2024-02-29, 2024-03-31]
# Shifted:  [2024-02-29, 2024-03-31, 2024-04-30]

diff(): Period-over-Period Change

Series.diff(n) computes the difference between a value and the value n positions before it: x[t] - x[t-n]. This is commonly used to compute day-over-day changes, week-over-week differences, or year-over-year deltas. The first n rows are NaN since there are no previous values to subtract from.

df['sales_diff1'] = df['sales'].diff(1)  # day-over-day change
df['sales_diff7'] = df['sales'].diff(7)  # week-over-week change

print(df[['sales', 'sales_diff1']].head())
#             sales  sales_diff1
# 2024-01-01    100          NaN
# 2024-01-02    120         20.0  <- +20 from yesterday
# 2024-01-03    115         -5.0  <- -5 from yesterday

pct_change(): Percentage Change

Series.pct_change(n) computes the relative percentage change: (x[t] - x[t-n]) / x[t-n]. This is essential for financial analysis (daily returns), growth rate computation, and any situation where the absolute change is less meaningful than the relative change. Multiply by 100 to get percentage points.

df['pct_chg'] = df['sales'].pct_change().round(3)
df['pct_chg_7d'] = df['sales'].pct_change(7).round(3)

print(df[['sales', 'pct_chg']].head())
#             sales  pct_chg
# 2024-01-01    100      NaN
# 2024-01-02    120    0.200  <- 20% increase
# 2024-01-03    115   -0.042  <- 4.2% decrease

Combining shift() with Arithmetic

You can combine shift() with arithmetic to compute derived time features. For example: the ratio of today's value to last week's value, the cumulative sum since a fixed start, or the difference from the year-ago value. All of these follow the same pattern: shift the original series and perform element-wise arithmetic with the current values.

# Week-over-week growth index (today / last week)
df['wow_ratio'] = (df['sales'] / df['sales'].shift(7)).round(3)

# Deviation from 3-day lag
df['dev_3d'] = df['sales'] - df['sales'].shift(3)

# Is today higher than yesterday? (boolean feature)
df['higher_than_yesterday'] = df['sales'] > df['sales'].shift(1)

print(df[['sales', 'wow_ratio', 'higher_than_yesterday']].head())

cumsum() and cumprod() for Cumulative Features

Series.cumsum() computes the running total from the first row up to each row, while Series.cumprod() computes the cumulative product. These are useful for cumulative revenue, cumulative returns (compound growth), and year-to-date totals. They require no arguments and work on any numeric Series or DataFrame column.

# Cumulative sales (year-to-date total)
df['ytd_sales'] = df['sales'].cumsum()

# Cumulative product: compound growth factor
returns = pd.Series([0.02, -0.01, 0.03, 0.01, -0.005])
df_ret = pd.DataFrame({'daily_return': returns})
df_ret['compound'] = (1 + df_ret['daily_return']).cumprod() - 1
print(df_ret)

Lag Features for Machine Learning

When preparing time series data for machine learning, a standard feature engineering step is to create a matrix of lag features. Each column represents the target variable at a different past time step. After creating lags, drop rows with NaN (which appear at the start due to missing history) and split into train and test sets without shuffling, respecting the temporal order.

def make_lag_matrix(series, n_lags):
    df_lags = pd.DataFrame({'y': series})
    for lag in range(1, n_lags + 1):
        df_lags[f'lag_{lag}'] = series.shift(lag)
    return df_lags.dropna()

lag_df = make_lag_matrix(df['sales'], n_lags=3)
print(lag_df)
# y    lag_1  lag_2  lag_3
# ...  ...    ...    ...

Shifting Within Groups

When your data contains multiple entities (e.g., multiple products or regions in one DataFrame), you must compute shifts within each entity's group separately. Use groupby().shift() to ensure that the lag for product A's first row is NaN and not the last value of product B. Mixing groups without this step is a common and subtle data leakage bug.

df_multi = pd.DataFrame({
    'product': ['A', 'A', 'A', 'B', 'B', 'B'],
    'sales': [100, 120, 115, 200, 210, 195]
})

# WRONG: lag crosses product boundary
df_multi['lag_wrong'] = df_multi['sales'].shift(1)

# CORRECT: lag within each product
df_multi['lag_correct'] = df_multi.groupby('product')['sales'].shift(1)
print(df_multi)

Interpreting pct_change Signs

A positive pct_change() value means the current value is higher than the previous one; a negative value means it is lower. Watch out for division-by-zero when the previous value is zero — the result is NaN or inf depending on the sign of the current value. Use replace([float('inf'), float('-inf')], float('nan')) to clean infinite values after pct_change().

import numpy as np

s = pd.Series([0, 100, 50, 200])
chg = s.pct_change()
print(chg)
# 0      NaN  <- no prior value
# 1      inf  <- 0 -> 100 (division by zero)
# 2    -0.5   <- 100 -> 50 (-50%)
# 3     3.0   <- 50 -> 200 (+300%)

# Clean infinite values
chg_clean = chg.replace([float('inf'), float('-inf')], float('nan'))
print(chg_clean)

Quick Check

Test your understanding of shifting and lag features from this lesson.

Lesson Recap

In this lesson you learned: shift(n) creates lag features by moving values down by n positions; diff(n) computes period-over-period absolute change; pct_change(n) computes relative percentage change; and when working with multiple groups you must use groupby().shift() to avoid data leakage. Next up we extract temporal features using the .dt accessor.

자주 묻는 질문

“시프트와 지연 특성” 강의는 무료인가요?

네 — “시프트와 지연 특성” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“시프트와 지연 특성”에서 뭘 배우나요?

shift()로 지연 열과 선행 열을 만들고 diff()로 기간별 변화를 계산하며 백분율 변화를 구합니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“시프트와 지연 특성” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. DatetimeIndex와 기간 범위
  2. 시계열 리샘플링
  3. 시프트와 지연 특성
  4. 시간 특성 추출하기
← Pandas & NumPy Academy(으)로 돌아가기