PythonPython 데이터 분석강의 8개 중 3번째난이도 기초

데이터 정제 — 결측값, 이상값, 타입 변환

발행 읽는 시간 약 1 분

  • Python
  • Pandas
  • 데이터정제
  • 결측값
  • 이상값
  • 전처리

강의 소개

실제 데이터에서 발생하는 결측값 처리, 이상값 탐지와 제거, 데이터 타입 변환 방법을 배웁니다. 깨끗한 데이터가 좋은 분석의 시작입니다.

현실 데이터의 문제점#

Python
import pandas as pd
import numpy as np

df = pd.read_csv("messy_data.csv")
df.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 1000 entries
# Data columns:
#  #   Column   Non-Null Count  Dtype
#  0   name     998 non-null    object    ← 2개 결측
#  1   age      950 non-null    float64   ← 50개 결측
#  2   salary   1000 non-null   object    ← 숫자인데 object!
#  3   date     1000 non-null   object    ← 날짜인데 string!

결측값 탐지#

Python
# 결측값 확인
print(df.isnull().sum())           # 열별 결측 개수
print(df.isnull().mean() * 100)    # 결측 비율 (%)

# 결측이 있는 행
print(df[df.isnull().any(axis=1)])

# 히트맵으로 시각화
import seaborn as sns
import matplotlib.pyplot as plt

sns.heatmap(df.isnull(), yticklabels=False, cbar=False, cmap="viridis")
plt.title("결측값 분포")

결측값 처리#

Python
# 1. 삭제
df_dropped = df.dropna()                         # 결측 있는 행 모두 삭제
df_dropped = df.dropna(subset=["name", "age"])   # 특정 열만 기준
df_dropped = df.dropna(thresh=3)                 # 3개 이상 채워진 행만 유지

# 2. 채우기 (수치형)
df["age"].fillna(df["age"].mean(), inplace=True)    # 평균으로
df["age"].fillna(df["age"].median(), inplace=True)  # 중앙값으로
df["age"].fillna(method="ffill", inplace=True)      # 앞 값으로

# 3. 채우기 (범주형)
df["department"].fillna("미지정", inplace=True)
df["department"].fillna(df["department"].mode()[0], inplace=True)  # 최빈값

# 4. 그룹별 채우기
df["salary"] = df.groupby("department")["salary"].transform(
    lambda x: x.fillna(x.median())
)

데이터 타입 변환#

Python
# 문자열 → 숫자
df["salary"] = pd.to_numeric(df["salary"], errors="coerce")  # 변환 실패 시 NaN

# 문자열 → 날짜
df["date"] = pd.to_datetime(df["date"], format="%Y-%m-%d")
df["date"] = pd.to_datetime(df["date"], infer_datetime_format=True)

# 날짜에서 성분 추출
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["weekday"] = df["date"].dt.day_name()

# 숫자 → 범주
df["age_group"] = pd.cut(df["age"],
                         bins=[0, 20, 30, 40, 100],
                         labels=["10대", "20대", "30대", "40대이상"])

이상값 탐지#

Python
# IQR 방법
Q1 = df["salary"].quantile(0.25)
Q3 = df["salary"].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

outliers = df[(df["salary"] < lower) | (df["salary"] > upper)]
print(f"이상값 개수: {len(outliers)}")

# Z-score 방법
from scipy import stats
z_scores = np.abs(stats.zscore(df["salary"].dropna()))
outlier_mask = z_scores > 3
print(f"3σ 이상: {outlier_mask.sum()}개")

이상값 처리#

Python
# 1. 제거
df_clean = df[(df["salary"] >= lower) & (df["salary"] <= upper)]

# 2. 클리핑 (상한/하한으로 대체)
df["salary"] = df["salary"].clip(lower=lower, upper=upper)

# 3. 로그 변환 (왜도 감소)
df["salary_log"] = np.log1p(df["salary"])  # log(1+x)

문자열 정제#

Python
# 공백 제거
df["name"] = df["name"].str.strip()

# 대소문자 통일
df["city"] = df["city"].str.lower()

# 특수문자 제거
df["phone"] = df["phone"].str.replace(r"[^0-9]", "", regex=True)

# 일관성 없는 값 통일
mapping = {"서울시": "서울", "서울특별시": "서울", "seoul": "서울"}
df["city"] = df["city"].replace(mapping)

데이터 정제 파이프라인#

Python
def clean_data(df: pd.DataFrame) -> pd.DataFrame:
    df = df.copy()

    # 타입 변환
    df["salary"] = pd.to_numeric(df["salary"], errors="coerce")
    df["date"] = pd.to_datetime(df["date"], errors="coerce")

    # 문자열 정제
    df["name"] = df["name"].str.strip()

    # 결측값 처리
    df["salary"].fillna(df["salary"].median(), inplace=True)
    df.dropna(subset=["name", "date"], inplace=True)

    # 이상값 클리핑
    Q1, Q3 = df["salary"].quantile([0.25, 0.75])
    IQR = Q3 - Q1
    df["salary"] = df["salary"].clip(Q1 - 1.5*IQR, Q3 + 1.5*IQR)

    return df

df_clean = clean_data(df)
print(f"정제 전: {len(df)}행, 정제 후: {len(df_clean)}행")

정리#

문제처리 방법
결측값dropna, fillna (평균/중앙값/최빈값)
잘못된 타입pd.to_numeric, pd.to_datetime
이상값IQR, Z-score, clip
문자열 불일치str.strip, replace

다음 편에서는 데이터 시각화 — Matplotlib과 Seaborn으로 인사이트를 그림으로 표현합니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.