목차
1. 결측치 처리(제거, 대체)
1-1 결측치란
1-2 결측치 제거
1-3 결측치 대체
2. 이상치 처리(IQR, Z-Score)
2-1 이상치란
2-2 IQR(Interquartile Range) 방법
2-3 Z-Score 방법
3. 데이터 중복 확인 및 제거
3-1 중복 데이터란
3-2 중복 데이터 확인
3-3 중복 데이터 제거
1. 결측치 처리(제거, 대체)
1-1 결측치란
결측치란 데이터셋에서 특정 값이 누락된 상태를 의미한다.
결측치는 pandas에서 NaN(Not a Number) 형태로 표시된다.
NaN은 실제 숫자가 아닌 결측값을 의미하는 특수한 값이다.
결측치는 데이터 분석 결과에 영향을 줄 수 있으므로 반드시 처리해야 한다.
- 분석 왜곡 방지
- 모델 학습 방해 방지
- 데이터 품질 향상
결측치 처리시 결측치의 양, 데이터의 중요성, 분석 목표를 고려해야 한다.
간단한 데이터셋에서는 제거와 평균/중간값 대체가 유용하다.
하지만, 복잡한 데이터에서는 머신러닝 기반 대체를 활용한다.
결측치 처리는 2가지 방법이 있다.
- 결측치 제거
- 결측치 대체
1-2 결측치 제거
결측치 제거는 다음과 같은 상황에서 사용한다.
- 결측치가 데이터셋에서 차지하는 비율이 매우 적을 때
- 해당 열이나 행이 분석에 큰 영향을 주지 않을 때
결측치 제거는 2가지 방법이 있다.
- 열 제거 : 특정 열에 결측값이 너무 많을 경우, 해당 열 자체를 삭제한다.
- 형 제거 : 특정 행에 결측값이 있을 경우, 해당 행을 삭제한다.
행을 삭제할 경우 데이터의 전체 개수가 줄어들 수 있으므로 데이터 손실 가능성을 고려해야 한다.
예제 1) 결측치 data 생성
import pandas as pd
data = {
'Name': ['Alice', 'Bob', None],
'Age': [25, None, 30],
'Score': [85, 90, None]
}
df = pd.DataFrame(data)
df를 출력해보면 아래와 같은 표가 출력된다.
NaN로 된 결측치를 확인할 수 있다.
Name Age Score
0 Alice 25.0 85.0
1 Bob NaN 90.0
2 NaN 30.0 NaN
예제 2) 결측치 확인하기
isnull() 메서드를 사용하여 결측치가 있는지 확인한다.
결측치일 경우 True가 반환된다.
df.isnull()
아래와 같은 표가 출력된다.
Name Age Score
0 False False False
1 False True False
2 True False True
예제 3) 결측치가 있는 행 삭제
dropna() 메서드를 사용하여 결측치가 있는 행을 삭제한다.
df_missing_rows = df.dropna()
print(df_missing_rows)
출력 결과 아래와 같은 표가 출력된다.
기존에 결측값이 있던 행 2개가 삭제된 것을 볼 수 있다.
Name Age Score
0 Alice 25.0 85.0
예제 4) 결측치가 있는 열 삭제
dropna(axis=1) 메서드를 사용하여 결측치가 있는 열을 삭제한다.
axis는 축이라는 뜻으로, dropna의 axis의 기본값은 0이다.
axis=0이면 행을 기준으로, axis=1이면 열을 기준으로 데이터를 삭제한다.
df_missing_cols = df.dropna(axis=1) # axis = 1(열단위), axis = 0(default, 행단위)
print(df_missing_cols)
출력 결과 아래와 같은 표가 출력된다.
기존에 결측값이 모든 열에 있었으므로, 모든 데이터가 삭제된 것을 볼 수 있다.
Empty DataFrame
Columns: []
Index: [0, 1, 2]
예제 5) 결측치가 있는 특정 열 삭제
Cabin 열에 결측값이 매우 많을 경우 해당 열 자체를 삭제할 수 있다.
inplace=True 옵션은 기존 DataFrame을 직접 수정하는 것을 의미한다.
df.drop('Cabin', axis=1, inplace=True)
1-3 결측치 대체
결측치 대체는 다음과 같은 상황에서 사용한다.
- 데이터의 양이 적을 때
- 결측치가 무작정 삭제되면 데이터 손실이 너무 클 때
결측치 대체는 데이터의 분포를 유지하면서 데이터 손실을 최소화할 수 있다는 장점이 있다.
결측치 대체는 3가지 방법이 있다.
- 고정 값으로 대체 : 특정 값으로 결측치를 채운다. 예) 평균, 중앙값, 0
- 통계 기반 대체
- 평균값으로 대체하기 : 수치형 데이터에서 결측값을 해당 열의 평균으로 대체한다.
- 중간값으로 대체하기 : 평균이 극단값에 영향을 받는 경우, 중간값을 사용한다.
- 최빈값으로 대체하기 : 범주형 데이터에서 가장 많이 등장한 값으로 결측치를 대체한다.
- 예측 기반 대체 : 머신러닝 모델을 사용하여, 결측치를 예측해 채운다.
평균값(mean)은 모든 값의 평균을 의미하며, 극단값(outlier)의 영향을 받을 수 있다.
중앙값(median)은 데이터를 정렬했을 때 중앙에 위치한 값으로,극단값의 영향을 덜 받는다.
예제 0) 고정 값으로 대체
Age 열에서 결측값이 있는 행을 찾아 0으로 대체한다.
df.loc[df['Age'].isnull(), 'Age'] = 0
예제 1) 결측치를 평균값으로 대체
.mean() 메서드와 .fillna() 메서드를 사용하여 결측치를 평균값으로 대체한다.
Pandas의 .fillna() 메서드는 NULL 값을 지정된 값으로 대체한다.
Pandas의 .mean() 메서드는 각 열의 평균값을 포함하는 Series를 반환한다.
df['Age'] = df["Age"].fillna(df['Age'].mean())
df
출력 결과는 다음과 같다.
Name Age Score
0 Alice 25.0 85.0
1 Bob 27.5 90.0
2 NaN 30.0 NaN
1행의 Age 값이 25와 30의 평균값인 27.5의 값으로 채워진 것을 볼 수 있다.
예제 2) 결측치를 중간값으로 대체
.median() 메서드와 .fillna() 메서드를 사용하여 결측치를 중간값으로 대체한다.
Pandas의 .fillna() 메서드는 NULL 값을 지정된 값으로 대체한다.
Pandas의 .median() 메서드는 각 열의 중앙값을 포함하는 Series를 반환한다.
df['Score'] = df['Score'].fillna(df['Score'].median())
df
출력 결과는 다음과 같다.
Name Age Score
0 Alice 25.0 85.0
1 Bob 27.5 90.0
2 NaN 30.0 87.5
2행의 Score 값이 85와 90의 중앙값 87.5로 채워진 것을 볼 수 있다.
예제 3) 결측치를 최빈값으로 대체
.mode() 메서드와 .fillna() 메서드를 사용하여 결측치를 최빈값으로 대체한다.
Pandas의 .fillna() 메서드는 NULL 값을 지정된 값으로 대체한다.
Pandas의 .mode() 메서드는 각 열의 최빈값을 반환한다.
df['Name'] = df['Name'].fillna(df['Name'].mode()[0])
df
이때 mode()[0]은 최빈값이 여러 개일 경우 가장 처음 값을 가져온다는 의미이다.
출력 결과는 다음과 같다.
Name Age Score
0 Alice 25.0 85.0
1 Bob 27.5 90.0
2 Alice 30.0 87.5
2행의 Name 값이 Alice로 채워진 것을 볼 수 있다.
최빈값 인 Alice, Bob 중 가장 처음 값을 가져온 것을 의미한다.
2. 이상치 처리(IQR, Z-Score)
2-1 이상치란
이상치란 데이터셋에서 다른 값들과 크게 동떨어져 있는 값을 의미한다.
이상치는 분석 결과를 곡하거나 모델의 성능을 저하시킬 수 있으므로 적절히 처리해야 한다.
- 데이터 왜곡 방지
- 모델 성능 향상
- 데이터 신뢰성 확보
이상치 처리는 2가지 방법이 있다.
- IQR(Interquartile Range) 방법
- Z-Score 방법
2-2 IQR(Interquartile Range) 방법
IQR은 데이터 중간 50%를 포함하는 범위를 이용해 이상치를 탐지하는 방법이다.
보통 비대칭 분포 데이터에 적합하다.
IQR 방법은 극단값(outlier)에 비교적 영향을 덜 받기 때문에, 비대칭 분포 데이터에서도 안정적으로 이상치를 탐지할 수 있다.
- Q1 (1사분위수) : 하위 25%의 값
- Q3 (3사분의 수) : 상위 75%의 값
- IQR : Q3-Q1
- 이상치 기준
- 아래쪽 : Q1 - 1.5 * IQR
- 위쪽 : Q3 + 1.5*IQR
예제 1) 이상치 데이터 생성
# 이상치 처리
data = {
'score' : [70, 75, 80, 85, 90, 150]
}
df = pd.DataFrame(data)
df
예제 2) IQR 값 계산
quantile() 메드를 사용하면, 분위수를 계산할 수 있다.
# IQR
Q1 = df['score'].quantile(0.25)
Q3 = df['score'].quantile(0.75)
IQR = Q3 - Q1
print(Q1, Q3, IQR)
예제 3) 이상치 범주 구하기
변수명 뒤에 _를 붙이는 것은 Python 예약어와의 충돌을 피하거나, 임시 변수임을 나타내기 위해 사용하기도 한다.
이상치 범주는 low_ 값보다 작은 값이거나(or) up_ 값보다 큰 값이다.
low_ = Q1 -1.5* IQR
up_ = Q3 + 1.5* IQR
print(f'이상치 범주: {low_}보다 작은 값, {up_}보다 큰 값')
예제 4) 이상치 값 찾기
이상치 값은 l ow_ 값보다 작은 값이거나(or) up_ 값보다 큰 값이다.
df_1 = df[(df['score'] < low_) | (df['score'] > up_)]
df_1
예제 5) 이상치 제거하기
이상치가 아닌 값은 low_값보다 같거나 크고(and) up_값보다 같거나 작은 값이다.
df_2 = df[(df['score'] >= low_) & (df['score'] <= up_)]
df_2
예제 6) 이상치 데이터 변경하기
이상치 데이터는 loc[]를 이용하여 변경할 수 있다.
df['score'] = df['score'].astype(float)
df.loc[df['score'] < low_, 'score'] = low_
df.loc[df['score'] > up_, 'score'] = up_
df
2-3 Z-Score 방법
Z-Score는 데이터의 값이 평균에서 얼마나 떨어져 있는지를 표준 편차 단위로 나타내는 방법이다.
보통 정규분포를 따르는 데이터에 적합하다.
계산이 간단하다.
- Z = (x - μ) / σ
- x : 개별 데이터 값
- μ : 평균
- σ : 표준 편차 이상치 기준
- 일반적으로 |Z| > 3 이면 이상치로 간주한다.
예제 0) 모듈 설치하기
pip install scipy
예제 1) 예제 데이터 생성하기
import pandas as pd
from scipy.stats import zscore
data = {'Scores' : [70, 75, 80, 85, 90, 1000000]}
df = pd.DataFrame(data)
예제 2) Z-Score 계산하기
zscore(arr, axis=- ddof=0)은 입력 데이터의 상대적 Z-점수를 표본 평균 및 표준 편차에 대한 상대값을 계산한다.
아래 코드는 'Scores'의 열 데이터에 대한 Z-Score을 계산하는 코드이다.
df['Z_Score'] = zscore(df['Scores'])
df
예제 2) 출력 결과
Scores Z_Score
0 70 -0.447240
1 75 -0.447227
2 80 -0.447214
3 85 -0.447200
4 90 -0.447187
5 1000000 2.236068
예제 3) 이상치 확인하기
아래 코드에서는 2를 이상치의 기준으로 설정하였다.
outliers=df[(df['Z_Score'] >2)]
print(outliers)
예제 3) 출력 결과
Scores Z_Score
5 1000000 2.236068
예제 4) 이상치 제거하기
df_deleted = df[df['Z_Score'] <= 2]
df_deleted
예제 4) 출력 결과
Scores Z_Score
0 70 -0.447240
1 75 -0.447227
2 80 -0.447214
3 85 -0.447200
4 90 -0.447187
예제 5) 이상치 중간값으로 대체하기
중앙값은 데이터 개수가 짝수일 경우 두 가운데 값의 평균으로 계산되므로 소수점 값이 나올 수 있다.
따라서 정수형(int64) 컬럼에 중앙값을 대입하려면 컬럼을 실수형(float)으로 변환해야 한다.
astype() 메서드를 이용하여 형 변환을 한다.
df['Scores'] = df['Scores'].astype(float)
median = df['Scores'].median()
df.loc[df['Z_Score'] > 2, 'Scores'] = median
print(df)
예제 5) 출력 결과
Scores Z_Score
0 70.0 -0.447240
1 75.0 -0.447227
2 80.0 -0.447214
3 85.0 -0.447200
4 90.0 -0.447187
5 82.5 2.236068
결측값 대체 후, Z-Score 계산 및 이상치 확인을 다시 해보면, 이상치가 없는 것을 확인할 수 있다.
예제 6) 이상치 재확인
#Z-Score계산
df['Z_Score'] = zscore(df['Scores'])
# 이상치 확인
outliers=df[(df['Z_Score'] >2)]
print(outliers)
예제 6) 출력 결과
Empty DataFrame
Columns: [Scores, Z_Score]
Index: []
3. 데이터 중복 확인 및 제거
3-1 중복 데이터란
중복 데이터는 데이터셋에서 동일한 행(row)이 반복적으로 나타나는 것을 의미한다.
중복 데이터가 있으면 분석 결과가 왜곡될 수 있고, 데이터의 크기가 큰 경우 처리 속도와 메모리 사용량에 영향을 줄 수 있다.
중복 데이터의 형태로는 다음과 같은 것이 있을 수 있다.
- 완전 중복 : 모든 열의 값이 동일한 행
- 보통 삭제를 한다.
- 부분 중복 : 특정 열의 값만 동일한 행
예제 1) 중복 데이터 생성
data = {
'Name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'],
'Age': [25, 30, 25, 35, 30],
'Score': [85, 90, 85, 95, 90]
}
df = pd.DataFrame(data)
df
예제 1) 출력 결과
Name Age Score
0 Alice 25 85
1 Bob 30 90
2 Alice 25 85
3 Charlie 35 95
4 Bob 30 90
3-2 중복데이터 확인
중복 데이터를 찾을 경우 pandas의 duplicated() 메서드를 사용한다.
duplicated() 메서드는 데이터에서 중복된 행을 빠르게 찾아, 중복된 행은 'True' 고유한 행은 'False'를 반환한다.
기본적으로 이전 행과 동일한 값을 가진 두 번째 행부터 True를 반환한다.
예제 2) 전체 행이 같은 중복 찾기
df.duplicated()
예제 2) 출력 결과
각 행마다 중복 데이터의 여부를 판별한다.
위에서부터 아래로 순서대로 검사하기 때문에, 중복 데이터의 두번째부터 True를 반환한다.
0 False
1 False
2 True
3 False
4 True
dtype: bool
예제 3) 중복된 행의 개수 구하기
중복된 행의 개수를 계산할 때는 sum() 메서드를 사용한다.
print(df.duplicated().sum())
예제 3) 출력 결과
2
예제 4) 특정 열의 값을 기준으로 중복 찾기
subset 옵션을 이용한다. 예제에서는 'Name' 열을 기준으로 중복을 찾는다.
df.duplicated(subset='Name')
예제 4) 출력 결과
0 False
1 False
2 True
3 False
4 True
dtype: bool
예제 5) 중복된 행 추출
duplicated()는 False, True의 Bool 값을 반환하기 때문에, 아래와 같은 코드로 추출이 가능하다.
df[df.duplicated()]
예제 5) 출력 결과
Name Age Score
2 Alice 25 85
4 Bob 30 90
3-3 중복데이터 제거
예제 1) 중복된 행 삭제하기
중복된 행을 삭제할 때는 pandas의 drop_duplicates() 메서드를 사용한다.
drop_duplicates()는 열 또는 특정 열을 기준으로 DataFrame에서 중복 행을 제거한다.
df_cleaned = df.drop_duplicates()
print(df_cleaned)
예제 1) 출력 결과
중복 데이터인 2행과 4행이 삭제된 것을 볼 수 있다.
Name Age Score
0 Alice 25 85
1 Bob 30 90
3 Charlie 35 95
예제 2) 중복 시 삭제 기준 정하기
drop_duplicates() 함수는 기본적으로 중복된 항목 중 첫 번째 항목만 유지한다.
마지막 항목까지 유지하려면 keep='last' 옵션을 사용하면 된다.
df_cleaned2 = df.drop_duplicates(keep='last')
print(df_cleaned2)
예제 2) 출력 결과
중복 데이터인 0행과 1행이 삭제된 것을 볼 수 있다.
Name Age Score
2 Alice 25 85
3 Charlie 35 95
4 Bob 30 90
예제 3) 특정 열을 기준으로 삭제하기(?)
subset 옵션으로 중복을 확인할 열을 지정한다.
지정하지 않으면 모든 열이 고려된다.
df_cleaned3 = df.drop_duplicates(subset=['Name'])
예제 3) 출력 결과
Name을 기준으로 중복된 행이 삭제된 것을 볼 수 있다.
Name Age Score
0 Alice 25 85
1 Bob 30 90
3 Charlie 35 95
예제 4) 중복된 항목 모두 제거하기
중복된 행을 모두 제거하려면 keep=False로 설정하면 된다.
df_cleaned4 = df.drop_duplicates(subset=['Name'], keep=False)
예제 4) 출력 결과
Name Age Score
3 Charlie 35 95
'머신러닝&딥러닝' 카테고리의 다른 글
| 머신러닝 & 딥러닝 기초 9편 | 데이터 통합, 조인(merge, concat) (0) | 2026.03.13 |
|---|---|
| 머신러닝 & 딥러닝 기초 8편 | 데이터 변환 및 스케일링 (0) | 2026.03.13 |
| 머신러닝 & 딥러닝 기초 6편 | 데이터 전처리 (0) | 2026.03.12 |
| 머신러닝 & 딥러닝 기초 5편 | 데이터 저장 방법 (CSV, Excel, JSON, SQLite) (0) | 2026.03.12 |
| 머신러닝 & 딥러닝 기초 4편 | API를 활용한 데이터 수집 (REST API) (1) | 2026.03.11 |