테마
데이터 전처리
학습 목표
- 결측치(NaN)를 탐색하고 처리하는 방법을 이해한다
- 오브젝트 타입을 수치형으로 변환하는 방법을 익힌다
- 문자열 메서드(str.replace, str.strip)로 텍스트를 정제할 수 있다
- 불필요한 컬럼을 제거하여 메모리를 절약하는 방법을 이해한다
- 데이터 단위 변환과 새 컬럼 생성을 할 수 있다
전체 구조
1. 결측치(NaN) 탐색
결측치는 NaN(Not a Number)으로 표시되며, 데이터가 없는 상태를 의미한다.
결측치 확인 방법
python
import pandas as pd
df_last = pd.read_csv("data/분양가격.csv", encoding="cp949")
# 방법 1: isnull()로 True/False 확인
df_last.isnull()
# 방법 2: isnull().sum()으로 컬럼별 결측치 개수
df_last.isnull().sum()
# 방법 3: isna()도 동일한 기능
df_last.isna().sum()출력 예시:
지역명 0
규모구분 0
연도 0
월 0
분양가격(제곱미터) 277결측치 필터링
python
# 결측치가 없는 데이터만 가져오기
price = df_last.loc[df_last["평당분양가격"].notnull(), "평당분양가격"]
# 또는 DataFrame 전체에서 특정 컬럼 기준
df_not_null = df_last[df_last["평당분양가격"].notnull()]2. 타입 변환 - to_numeric
분양가격이 숫자처럼 보이지만 object 타입인 경우가 있다. 공백 문자가 섞여 있으면 astype(int)로 직접 변환할 수 없다.
python
# astype으로 변환 시도 → ValueError 발생
# df_last["분양가격(제곱미터)"].astype(int)
# to_numeric으로 강제 변환 (변환 불가 값은 NaN 처리)
df_last["분양가격"] = pd.to_numeric(
df_last["분양가격(제곱미터)"],
errors="coerce" # 변환 불가 → NaN
)
# 결과: float64 타입 (NaN이 float이므로)
print(df_last["분양가격"].dtype)
# float64errors 옵션 정리:
"raise"는 에러 발생,"coerce"는 NaN으로 강제 변환,"ignore"는 변환 불가 값을 원본 그대로 유지한다. 실무에서는"coerce"를 가장 많이 사용한다.
NaN이 float인 이유
python
import numpy as np
print(type(np.nan))
# <class 'float'>NaN은 float 타입이기 때문에, NaN이 포함된 컬럼은 자동으로 float64로 변환된다.
3. 문자열 정제 - str 메서드
str.replace로 텍스트 치환
Series.replace는 완전 일치만 치환하지만, str.replace는 부분 문자열도 치환할 수 있다.
python
# 원본: "전용면적 60초과 85이하"
# Series.replace → 완전 일치만 (동작 안 함)
df_last["규모구분"].replace("전용면적", "") # 변화 없음
# str.replace → 부분 문자열 치환 (동작함)
df_last["전용면적"] = df_last["규모구분"].str.replace("전용면적", "")
df_last["전용면적"] = df_last["전용면적"].str.replace("초과", "~")
df_last["전용면적"] = df_last["전용면적"].str.replace("이하", "")str.strip으로 공백 제거
python
# 앞뒤 공백 제거
df_last["전용면적"] = df_last["전용면적"].str.strip()
# 중간 공백도 제거
df_last["전용면적"] = df_last["전용면적"].str.replace(" ", "")4. 단위 변환과 새 컬럼 생성
데이터셋마다 단위가 다를 수 있다. 제곱미터당 가격을 평당 가격으로 변환하는 예시:
python
# 제곱미터 → 평 (1평 = 3.3제곱미터)
df_last["평당분양가격"] = df_last["분양가격"] * 3.3
# 확인
df_last.head(1)주의: 새 값을 DataFrame에 남기려면 연산 결과를 컬럼에 다시 할당해야 한다.
df["컬럼"] * 3.3만 실행하면 계산 결과는 보이지만 원본 컬럼은 바뀌지 않는다.
5. 불필요한 컬럼 제거 - drop
python
# 제거 전 메모리 확인
print(df_last.info()) # 271 KB
# 컬럼 제거 (axis=1 필수)
df_last = df_last.drop(["규모구분", "분양가격(제곱미터)"], axis=1)
# 제거 후 메모리 확인
print(df_last.info()) # 203 KB핵심 주의사항
axis=0은 행 삭제(기본값),axis=1은 열 삭제- 보통 결과를 다시 변수에 할당한다:
df = df.drop(...) - 사용하지 않는 컬럼 제거는 메모리 절약에 효과적이다
6. 결측치 시각화와 처리 전략
python
# 결측치가 많은 컬럼 순으로 정렬
null_counts = df.isnull().sum()
null_sorted = null_counts.sort_values(ascending=False)
null_sorted.head(10)
# 결측치 시각화
null_sorted.plot.barh(figsize=(7, 8))결측치 처리 전략
python
# 결측치 행 제거
df_clean = df.dropna(subset=["분양가격"])
# 평균값으로 대체
df["분양가격"] = df["분양가격"].fillna(df["분양가격"].mean())
# 특정 값으로 대체
df["분양가격"] = df["분양가격"].fillna(0)핵심 정리
- **isnull().sum()**으로 컬럼별 결측치 개수를 빠르게 파악한다
- **pd.to_numeric(errors="coerce")**로 문자열을 숫자로 안전하게 변환한다
- str.replace는 부분 문자열을, Series.replace는 완전 일치를 치환한다
- 새 컬럼 생성:
df["새컬럼"] = df["기존컬럼"] * 3.3 - **drop(axis=1)**로 불필요 컬럼을 제거하고, 보통 결과를 다시 할당한다
- 메모리 사용량은 불필요 컬럼 제거만으로도 크게 줄어든다