결측치 처리
결측치(Missing Data) : 데이터셋에서 값이 채우져 있지 않은 항목으로, 보통 빈 값, NULL. NaN(Not a Number) 등의 형태로 표현
결측치는 분석을 방해하고 잘못된 결과를 유발할 수 있으므로, 본격적인 분석 전에 반드시 처리해야 합니다. 처리 방법은 상황에 따라 삭제(drop)하거나 대체(impute) 하는 것이 일반적입니다.
결측치 확인
- isnull()/notnull(): 판다스 Series나 DataFrame의 각 원소가 결측치인지 아닌지를 True/False로 나타내는 동일한 모양의 객체를 반환합니다. df.isnull()은 결측이면 True, 값이 있으면 False를 줍니다. 반대로 df.notnull()은 값이 있으면 True입니다.
- 결측치 개수 파악: df.isnull().sum()을 이용하면 각 컬럼별 결측치 개수를 알 수 있습니다(True를 1로 간주하여 합계).
- 또는 df.info()에서도 Non-Null Count를 보여주므로 간접적으로 알 수 있습니다.
예제: 간단한 데이터프레임을 만들어 결측치 처리를 연습해보자
import numpy as np
df_miss = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, np.nan, 30],
'city': ['New York', 'Los Angeles', np.nan]
})
print(df_miss)
name age city
0 Alice 25.0 New York
1 Bob NaN Los Angeles
2 Charlie 30.0 NaN
df_miss.isnull().sum()을 해보면 age 1개, city 1개 결측치가 나옴을 확인할 수 있습니다.
결측치 삭제 (dropna)
📌 dropna
- 기본적으로 df.dropna()는 하나라도 결측치가 있는 행(가로줄)을 모두 제거합니다.
- 만약 결측치가 데이터의 일부 열에만 집중되어 있다면, 특정 열만 제거(df.dropna(subset=['컬럼명1', '컬럼명2'], inplace=False))하거나 thresh(임계치) 옵션으로 일정 개수 이상의 값이 있는 행만 남기는 등의 조정도 가능합니다.
print(df_miss.dropna())
name age city
0 Alice 25.0 New York
➡️ 위 결과를 보면 결측치가 있던 행(인덱스 1과 2)이 제거되고, Alice의 데이터만 남음
이렇게 하면 간단히 결측치를 없앨 수 있지만,
데이터 손실이 크기 때문에 상황에 따라 적절치 않을 수 있습니다.
(특히 행 개수가 많이 줄어드는 경우)
📌 특정 축 방향으로 삭제
- df.dropna(axis=1)로 하면 결측치 있는 컬럼(세로줄)을 제거합니다.
- 위 예에서 axis=1로 하면 age와 city 컬럼이 모두 날아가고 name만 남겠죠.???
- 이는 일반적으로 정보 손실이 크므로 잘 안 쓰입니다. 대신 행 삭제는 흔히 사용되지만, 가능한 경우에만 사용합니다.
결측치 대체 (fillna)
완전히 지워버리기 어려운 경우, 결측값을 다른 값으로 대체(impute)하는 방법을 많이 씁니다.
- 고정값 대체: df.fillna(0)처럼 하나의 값(예: 0)으로 모든 결측치를 채울 수 있습니다. 또는 컬럼별로 다른 값으로 채우고 싶다면 딕셔너리를 인자로 df.fillna({'age': df['age'].mean(), 'city': 'Unknown'})처럼 줄 수도 있습니다.
- 통계값으로 대체: 보통 수치형 데이터는 평균이나 중앙값으로 결측치를 채우고, 범주형 데이터는 최빈값 또는 'Unknown'같은 표시로 채우기도 합니다.
예제: 위 df_miss 에서 age 의 결측치는 나이 평균으로, city 의 결측치는 'Unknown' 으로 채워봅니다.
df_filled = df_miss.copy()
df_filled['age'].fillna(df_filled['age'].mean(), inplace=True)
df_filled['city'].fillna('Unknown', inplace=True)
print(df_filled)
name age city
0 Alice 25.0 New York
1 Bob 27.5 Los Angeles
2 Charlie 30.0 Unknown
- Bob의 age가 27.5로 채워졌습니다 (25과 30의 평균인 27.5를 대입).
- Charlie의 city가 'Unknown' 문자열로 채워졌습니다.
- (inplace 매개변수): 여기서는 inplace=True 를 사용해 원 데이터프레임을 직접 수정했다. inplace 를 사용하지 않으면 df_filled = df_miss.fillna({...}) 형태로 새로운 객체를 받아야 한다. 코드 스타일에 따라 둘 중 편한 것을 사용하면 된다. ????
결측치 처리 전략
어떤 방법이 좋은지는 데이터의 특성과 분석 목적에 따라 다릅니다. 중요한 컬럼에 결측치가 많다면 행을 버리는 것은 위험하고, 그렇다고 함부로 채우는 것도 왜곡을 줄 수 있습니다.
따라서 :
- 가능한 한 데이터 수집 단계에서 결측을 줄이도록 하고,
- 불가피한 결측에 대해서는 삭제해도 되는지, 대체해야 하는지 판단이 필요
- 대체한다면 그 근거(평균, 이전값, 도메인 지식 기반 등)를 생각해야 하며, 결측치를 별도의 범주로 취급하는 방법도 있음
'데이터 전처리 & 시각화' 카테고리의 다른 글
| [데이터 전처리 ] 중복 제거 (2) | 2025.08.28 |
|---|---|
| [데이터 전처리] 데이터 정렬(sorting) 및 정제(cleaning) (1) | 2025.08.28 |
| [데이터 전처리] 조건 필터링(filtering) (1) | 2025.08.28 |