본문 바로가기
Pandas

[Pandas] 결측치 탐색과 처리 함수 (isna, fillna, dropna 등)

by PredictLab | 데이터 예측 연구소 2025. 4. 20.

 

1. 개요

데이터 분석에서 결측치는 피할 수 없는 문제입니다. 센서 오작동, 사용자의 미입력, 크롤링 실패 등 다양한 이유로 누락된 값이 생기며, 이를 제대로 처리하지 않으면 분석 결과가 왜곡될 수 있습니다. Pandas는 결측치를 탐지하고, 채우거나 제거하는 강력한 함수들을 제공합니다.

이번 글에서는 isna(), notna(), fillna(), dropna(), interpolate() 함수들을 중심으로 결측치 처리의 모든 것을 실습과 함께 정리해봅니다.

2. 내용

2-1. 결측치란?

Pandas에서 결측치는 일반적으로 np.nan (Not a Number)으로 표현됩니다. 숫자형, 문자열, 날짜 등 어떤 타입에도 NaN이 들어갈 수 있습니다. 이 값은 산술연산이나 조건 비교에 예외적인 처리를 유발하므로 반드시 확인 및 처리해야 합니다.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie', None],
    'Age': [25, np.nan, 35, 40],
    'Score': [88.5, 92.0, None, 70.0]
})
print(df)
      Name   Age  Score
0    Alice  25.0   88.5
1      Bob   NaN   92.0
2  Charlie  35.0    NaN
3     None  40.0   70.0

2-2. isna()

isna() 함수는 각 요소가 결측치인지 여부를 True/False로 반환합니다. 결측치 필터링, 개수 확인 등에 자주 사용됩니다.

print(df.isna())
    Name    Age  Score
0  False  False  False
1  False   True  False
2  False  False   True
3   True  False  False

결측치 개수만 보고 싶을 땐 sum()을 사용합니다.

print(df.isna().sum())
Name     1
Age      1
Score    1
dtype: int64

2-3. notna()

notna() 함수는 isna()의 반대 개념으로, 결측치가 아닌 값에 대해 True를 반환합니다. 조건 필터링과 함께 자주 쓰입니다.

print(df[df['Score'].notna()])
    Name   Age  Score
0  Alice  25.0   88.5
1    Bob   NaN   92.0
3   None  40.0   70.0

2-4. 결측치 탐색 활용 예제

# 하나라도 NaN이 있는 행
print(df[df.isna().any(axis=1)])
      Name   Age  Score
1      Bob   NaN   92.0
2  Charlie  35.0    NaN
3     None  40.0   70.0
# 모든 열이 NaN인 행만 추출 (예: 완전한 결측행)
df_all_na = df[df.isna().all(axis=1)]
print(df_all_na)

이런 방식은 결측치 분포를 파악하거나, 분석 대상에서 제외할 행을 정할 때 유용합니다.

2-5. fillna()

fillna()는 결측치를 사용자가 지정한 값으로 대체하는 함수입니다. 평균, 중간값, 이전 값, 특정 상수 등 다양한 방식으로 결측값을 채울 수 있어 매우 유연하게 사용됩니다.

# 평균으로 결측치 대체
mean_score = df['Score'].mean()
df_filled = df.fillna({'Score': mean_score})
print(df_filled)
      Name   Age  Score
0    Alice  25.0  88.50
1      Bob   NaN  92.00
2  Charlie  35.0  83.50
3     None  40.0  70.00

지정된 방향으로 결측치 채우기 (ffill, bfill)

# 이전 값으로 채우기 (forward fill)
print(df.fillna(method='ffill'))
      Name   Age  Score
0    Alice  25.0  88.5
1      Bob  25.0  92.0
2  Charlie  35.0  92.0
3  Charlie  40.0  70.0
# 이후 값으로 채우기 (backward fill)
print(df.fillna(method='bfill'))
      Name   Age  Score
0    Alice  25.0  88.5
1      Bob  35.0  92.0
2  Charlie  35.0  70.0
3     None  40.0  70.0

채울 수 있는 값이 없을 경우에는 그대로 NaN이 유지되며, limit 옵션을 통해 채울 횟수를 제한할 수도 있습니다.

2-6. dropna()

dropna()는 결측치를 포함한 행이나 열을 삭제하는 함수입니다. 단순하지만 강력한 기능이며, 분석의 목적과 데이터 특성에 따라 신중하게 사용해야 합니다.

# 하나라도 NaN이 있으면 해당 행 삭제
print(df.dropna())
    Name   Age  Score
0  Alice  25.0   88.5
# 모든 값이 NaN인 행만 삭제
df2 = pd.DataFrame({
    'A': [np.nan, np.nan, 3],
    'B': [np.nan, 2, 3]
})
print(df2.dropna(how='all'))
     A    B
1  NaN  2.0
2  3.0  3.0

열 단위로 결측치가 많은 열을 제거할 수도 있음

print(df.dropna(axis=1))
   Score
0  88.5
1  92.0
2   NaN
3  70.0

📌 결측치 처리 전략 요약

  • 분석 대상에 따라 행 삭제 (dropna) → 데이터 양이 충분할 때
  • 이전/다음 값으로 채우기 (ffill, bfill) → 시계열 데이터에 적합
  • 평균/중간값으로 채우기 → 수치형 변수 보정
  • 모델링에 따라 별도 라벨 지정 → NaN을 따로 의미 있는 값으로 인코딩

2-7. interpolate()

interpolate()는 결측치를 선형 보간법 등으로 자동 채워주는 함수입니다. 시계열, 연속형 데이터 처리에 매우 강력하며, method 옵션으로 다양한 방식의 보간이 가능합니다.

df_interp = pd.DataFrame({
    'Temperature': [23.5, np.nan, 24.8, np.nan, 25.6]
})

print(df_interp.interpolate())
   Temperature
0        23.5
1        24.15
2        24.8
3        25.2
4        25.6

선형(linear) 외에도 다양한 보간 방법이 존재합니다.

# index 기준으로 보간
df_interp.interpolate(method='index')

# 시간 간격에 따라 보간 (DatetimeIndex 필요)
# df.interpolate(method='time')

limit_direction 옵션을 통해 앞/뒤 한쪽 방향으로만 채울 수도 있으며, limit으로 최대 보간 개수도 설정할 수 있습니다.

df_interp.interpolate(limit=1, limit_direction='forward')

📊 실전 예제: 시계열 데이터의 결측값 보간

date_rng = pd.date_range(start='2023-01-01', periods=6, freq='D')
df_ts = pd.DataFrame({'value': [10, np.nan, np.nan, 13, np.nan, 15]}, index=date_rng)
print(df_ts)
            value
2023-01-01   10.0
2023-01-02    NaN
2023-01-03    NaN
2023-01-04   13.0
2023-01-05    NaN
2023-01-06   15.0
# 시간 기준 보간
print(df_ts.interpolate(method='time'))
            value
2023-01-01  10.00
2023-01-02  11.00
2023-01-03  12.00
2023-01-04  13.00
2023-01-05  14.00
2023-01-06  15.00

3. 결론

이번 글에서는 Pandas에서 결측치를 처리하기 위한 전방위적 방법들을 다뤘습니다. isna, notna로 결측값을 탐색하고, fillna, dropna, interpolate를 통해 데이터를 정제하는 것은 모든 분석 작업의 기본이자 핵심입니다.

결측치 처리는 단순한 대체를 넘어서 모델링, 예측 정확도, 통계 해석에 큰 영향을 미치므로, 데이터 특성과 목적에 맞는 전략을 세워 적용해야 합니다. 특히 interpolate()는 시계열 분석에서 강력한 무기가 될 수 있습니다.

데이터의 결측 상태를 무시하지 말고, 지금 소개한 함수들을 적극적으로 활용하여 분석의 신뢰성과 정확도를 높여보세요.