[판다스 11화] 결측치(NaN) 처리 가이드: fillna와 dropna 사용법 | Python Pandas | 빅분기, 빅데이터분석기사 실기

수집한 원본 데이터를 데이터프레임으로 변환하여 기술통계를 확인하다 보면 데이터가 비어 있는 빈칸을 자주 발견하게 됩니다. 판다스(Pandas)에서는 이처럼 비어 있는 값을 NaN(Not a Number), None 또는 pd.NA 등의 형태로 표현하며, 이러한 값을 통칭하여 결측치(Missing Value)라고 부릅니다.

현업의 비즈니스 데이터나 빅데이터분석기사(빅분기) 실기 시험 데이터셋에서 결측치는 분석 결과를 왜곡하거나 알고리즘의 정상적인 연산을 방해하는 주요 원인이 됩니다. 따라서 결측치의 상태를 정확히 진단하고 적절하게 처리하는 것은 데이터 전처리 단계에서 매우 큰 비중을 차지합니다. 이번 글에서는 결측치를 확인하는 방법부터 이를 제거하거나(dropna) 대체하는(fillna) 대표적인 기법들을 체계적으로 살펴보겠습니다.

1. 데이터셋 내 결측치(NaN) 진단하기

결측치를 처리하기 전에 가장 먼저 수행해야 할 작업은 데이터프레임 내부 어디에, 얼마나 많은 결측치가 존재하는지 확인하는 것입니다.

1.1. 결측치 여부 확인 (isnull, isna)

판다스에서는 데이터가 결측치인지 여부를 판단하여 참(True) 또는 거짓(False)의 불리언 값으로 반환하는 isnull()isna() 함수를 제공합니다. 두 함수는 명칭만 다를 뿐 내부적으로 동일하게 작동합니다.

import pandas as pd
import numpy as np

# 가상의 비즈니스 고객 데이터 생성 (일부 결측치 포함)
customer_df = pd.DataFrame({
    '고객ID': ['C01', 'C02', 'C03', 'C04', 'C05'],
    '나이': [29, np.nan, 35, 41, np.nan],
    '직업': ['회사원', '자영업', np.nan, '전문직', '회사원'],
    '구매총액': [150000, 320000, 89000, np.nan, 450000]
})

# 각 원소의 결측치 여부 확인
print(customer_df.isnull())

1.2. 결측치 개수 집계 (sum)

데이터셋의 규모가 클 때는 눈으로 하나씩 확인할 수 없으므로, 열 단위로 합계를 구해주는 sum() 함수를 연결하여 결측치 빈도를 한눈에 파악합니다. 파이썬에서 True는 숫자 1로, False는 0으로 계산되는 성질을 활용한 방식입니다.

# 각 컬럼별 결측치 개수 집계
print(customer_df.isnull().sum())

[출력 결과]

고객ID    0
나이      2
직업      1
구매총액    1
dtype: int64

2. 누락된 행이나 열 제거하기: dropna() 함수

결측치를 처리하는 첫 번째 핵심 전략은 결측치가 포함된 영역을 데이터프레임에서 완전히 잘라내는 것입니다. 이 작업은 dropna() 함수를 사용해 제어할 수 있습니다.

2.1. dropna()의 핵심 파라미터 구조

  • axis: 결측치 제거 방향을 결정합니다. axis=0 또는 axis='index'는 행을 제거하고, axis=1 또는 axis='columns'는 열을 제거합니다. (기본값은 axis=0)
  • how: 제거 기준을 정합니다. 'any'는 대상 영역에 결측치가 단 하나라도 존재하면 제거하고, 'all'은 전체 데이터가 모두 결측치여야 제거합니다. (기본값은 'any')
  • subset: 특정 열들을 지정하여 해당 컬럼에 결측치가 존재하는 경우에만 행을 삭제하도록 범위를 제한합니다.
  • inplace: True 설정 시 원본 객체를 직접 갱신하며 복사본을 반환하지 않습니다.

2.2. 비즈니스 예시로 보는 dropna 활용

앞서 정의한 customer_df에 다양한 제거 방식을 적용해 보겠습니다.

# 1. 결측치가 하나라도 포함된 행은 모두 제거 (기본값)
clean_rows = customer_df.dropna()

# 2. '나이' 컬럼에 결측치가 있는 행만 선별적으로 제거
clean_age_rows = customer_df.dropna(subset=['나이'])

# 3. 결측치가 포함된 세로축 열 자체를 삭제
clean_columns = customer_df.dropna(axis=1)

제거 방식 적용 시 유의점: dropna()를 무분별하게 사용해 전체 행을 지우면 유용한 정보까지 함께 손실되어 데이터 분석 목적을 달성하기 어려워질 수 있습니다. 결측치 비율이 극단적으로 높은 열이나 대체가 불가능한 고유 키 항목이 누락된 경우에 제한적으로 사용하는 것이 합리적입니다.

3. 누락된 값 대체하여 메우기: fillna() 함수

결측치를 무작정 지우기보다 특정 값으로 채우는 방식은 데이터 손실을 최소화하는 효율적인 대안이 됩니다. fillna() 함수를 사용하면 다양한 시나리오에 맞춰 값을 채워 넣을 수 있습니다.

3.1. 특정 상수로 일괄 대체하기

모든 결측치를 동일한 고정 값이나 문자로 대체하는 방법입니다.

# '직업' 컬럼의 결측치를 '무직'으로 대체
customer_df['직업'] = customer_df['직업'].fillna('무직')

3.2. 대푯값(평균값, 중앙값, 최빈값)으로 대체하기

수치형 데이터의 경우, 전체 데이터의 통계적 요약 수치로 채우는 방식이 통계적 편향을 줄이는 데 주로 활용됩니다.

# '나이' 컬럼의 결측치를 결측치 제외 평균값으로 채우기
age_mean = customer_df['나이'].mean()
customer_df['나이'] = customer_df['나이'].fillna(age_mean)

# '구매총액' 컬럼의 결측치를 결측치 제외 중앙값(Median)으로 채우기
amount_median = customer_df['구매총액'].median()
customer_df['구매총액'] = customer_df['구매총액'].fillna(amount_median)

3.3. 시계열 혹은 전후 값 참조 대체 (ffill, bfill)

시간에 따라 기록된 연속적인 데이터의 경우, 누락된 값을 가장 최근 데이터 혹은 바로 뒤 데이터 값으로 채우는 것이 논리적인 흐름에 맞습니다. method 파라미터를 활용해 제어할 수 있습니다.

  • method=’ffill’ (forward fill): 결측치 바로 이전 행에 있는 값을 가져와 채웁니다.
  • method=’bfill’ (backward fill): 결측치 바로 다음 행에 있는 값을 가져와 채웁니다.
# 시계열 경향 반영을 위해 이전 행 값으로 대체
ts_df = customer_df.fillna(method='ffill')

4. 빅데이터분석기사 실기 시험 환경에서의 실전 활용 포인트

빅데이터분석기사 실기(특히 작업형 제1유형 및 제2유형) 환경에서 결측치 전처리는 필수적인 루틴 중 하나입니다.

4.1. 결측치 처리를 통한 모델 학습 오류 방지

Scikit-learn과 같은 머신러닝 라이브러리에 입력 데이터로 쓸 데이터프레임을 제공할 때, 결측치가 존재하면 파이프라인 연산 과정에서 오류가 발생하거나 예측 정확도가 하락합니다. 따라서 아래와 같은 전처리 순서를 확립해야 합니다.

  1. X_train.isnull().sum()으로 변수별 결측값 개수를 점검합니다.
  2. 수치형 피처의 결측치는 훈련 데이터(Train Data)의 대표값(예: 중앙값)을 계산한 뒤 훈련 셋과 평가 셋(Test Data)에 일관되게 대입합니다. (평가 데이터의 결측치를 처리할 때 평가 데이터 자체의 대표값을 쓰는 것이 아니라, 데이터 누수 방지를 위해 훈련 데이터의 대푯값을 사용해야 성능 평가의 객관성을 확보할 수 있습니다.)
# [실전 적용 프로토콜]
# 1. Train 데이터의 중앙값 산출
train_median = X_train['나이'].median()

# 2. Train 데이터와 Test 데이터의 결측치를 해당 중앙값으로 적용
X_train['나이'] = X_train['나이'].fillna(train_median)
X_test['나이'] = X_test['나이'].fillna(train_median)

4.2. 결측치 비율 기준 피처 드롭 결정

시험에서 제공되는 데이터셋을 분석하는 과정에서 특정 독립변수의 누락 데이터율이 전체 샘플 크기 대비 극단적으로 높은 비율(예: 대부분의 데이터가 누락된 경우)을 기록하는 경우, 결측치를 특정 값으로 채워 넣는 연산 자체가 모델의 예측 성능을 저하시킬 수 있는 노이즈가 될 수 있습니다. 이럴 때는 도리어 과감하게 해당 변수 열 자체를 전체 데이터프레임에서 제거(drop)하는 편이 최적의 예측 성능을 확보하는 전략이 됩니다.

5. 요약 및 다음 화 안내

  • isnull().sum(): 데이터 내 누락 수치를 컬럼별로 요약 집계하여 이상을 탐지하도록 돕습니다.
  • dropna(): 결측치를 포함한 행/열 영역을 삭제하며, 삭제 범위는 axis, subset 옵션을 조합하여 제어합니다.
  • fillna(): 통계적 대푯값이나 고정된 상수값, 혹은 인접 데이터를 참조하여 빈자리를 메우는 효율적인 데이터 복원 방식입니다.

다음 [판다스 12화]에서는 정합성 높은 데이터 수집을 완성하기 위한 다음 전처리 관문으로, 동일하게 입력된 정보를 교정하는 중복 데이터 제거하기(drop_duplicates)와 데이터 품질 관리에 대해 상세하게 알아보겠습니다. 데이터의 유일성을 유지하고 품질을 향상시키는 방법을 함께 학습해 봅시다.

댓글 남기기