본 자료는 [시나공 AI능력시험 AICE ASSOCIATE편] 책을 공부하면서 정리하는 내용임
Sec1. 수치형 데이터 정제하기
1.결측치 파악하기
ㅇ 결측치 : 데이터 없는거 : 데이터 분석 시 반드시 처리 해야함, N/A, Null, NaN
# 랜덤하게 결측치 생성하기
import pandas as pd
df=pd.read_csv('./Clean_Dataset.csv')
# 랜덤과 넘파이 불러오기
import random
import numpy as np
#같은 결과 출력을 위해 시드 고정하기
random.seed(2023)
np.random.seed(2023)
#랜덤한 위치에 결측치 5000개를 포함한 데이터 df_na 생성하기
df_na=df.copy()
for i in range(0,5000) :
df_na.iloc[random.randint(0,300152), random.randint(0,10)]=np.nan
#결측치 처리여부 확인을 위한 1번, 3번 인덱스 전체 결측치 처리하기(2개 결측치 생성)
df_na.iloc[1]=np.nan
df_na.iloc[3]=np.nan
1) 결측치 확인하기
#데이터 정보 확인하기
df_na.info()

2) 결측치 갯수 확인하기
DataFrame의 isnull() 함수(null이면 True를 반환)를 활용
컬럼명(axis=0) 기준으로 True(1)을 합하는 방법
df_na.isnull().sum(axis=0)

2.결측치 처리하기
ㅇ 결측치가 포함된 레코드를 제거
ㅇ 결측치가 포함된 칼럼을 제거
ㅇ 결측치를 특정한 값으로 채워넣기
# 데이터 변경에 대비하여 원본데이터를 df_na_origin에 저장해두기
df_na_origin=df_na.copy()
1) 결측치 삭제하기 - dropna메소드 사용하면 행 기준으로 결측치가 하나라도 있으면 해당 행을 삭제함
#결측치를 갖는 모든 행 삭제하기
df_na=df_na.dropna()
df_na.info()

ㅇ 모든 데이터가 결측치인 행만 삭제하기 how='all'
# 실습 전 원래 데이터 가져오기
df_na=df_na_origin.copy()
# 모든 데이터가 결측치인 행만 삭제하기
df_na=df_na.dropna(how='all')
df_na

3) 결측치 대체하기
가장 무난하고 많이 사용하는 방법
df_na=df_na_origin.copy()
#칼럼별 평균값으로 결측치 대체하기
df_na=df_na.fillna(df_na.mean())
df_na.info()

#텍스트 데이터 채우기
df_na=df_na.fillna(method='bfill')
df_na.head()

3. 이상치 파악하기 - 관측범위에서 아주 많이 벗어난 아주 작은 값이나 아주 큰 값 / outlier
1) Z-Score로 확인하기
신뢰구간과 관계 있음?
신뢰구간은 모수가 실제로 포함될 것으로 예측되는 범위를 말함
신뢰구간에 모집단의 실제 평균값이 포함될 확률을 신뢰수준이라고함
참고사항

Z분포는 표준정규분포, N(0,1)인 정규분포임
즉, 평균이 0이고, 표준편차와 분산이 1임
정규분포의 -1.96 ~ 1.96사이에 95%의 데이터가 존재함
즉 표준편차의 1.96사익밧 안에 있을 확률이 95%라고 할 수 있음
일반적으로 95%의 신뢰수준을 사요하기 때문에 Z-Score 1.96을 기준으로 이상치를 확인함
Z-Score = (xi-X의 평균)/X표준편차
# z-score를 기준으로 신뢰수준이 95%인 데이터 확인하기
df[(abs(df['price']-df['price'].mean())/df['price'].std())>1.96]

2) IQR로 이상치 확인
IQR은 3분위수에서 1분위수를 뺀 값
1분위수-1.5xIQR보다 작거나,
3분위수+1.5xIQR보다 크면 이상치로 판단함
# IQR로 이상치를 확인하는 함수 만들기
def findOutliers(x, column):
#1사분위수 구하기
q1=x[column].quantile(0.25)
#3사분위수 구하기
q3=x[column].quantile(0.75)
#iqr의 1.5배수 iqr 구하기
iqr=1.5*(q3-q1)
# 이상치를 저장한 데이터 y 만들기
y=x[(x[column] > (q3+iqr))|(x[column]<(q1-iqr))]
# IQR기준 이상치 y 반환하기
return len(y)
# price, duration, days_left에 대해 IQR 기준 이상치가 있는지 확인하기
print("price IQR Outliers : ", findOutliers(df, 'price'))
print("duration IQR Outliers : ", findOutliers(df, 'duration'))
print("days_left IQR Outliser : ", findOutliers(df, 'days_left'))

IQR이상치 시각화(박스그래프)
# 시각화를 위해 matplotlib.pyplot 불러오기
import matplotlib.pyplot as plt
plt.figure()
# 첫번째 subplot : 1행 5열로 나눈 영역에서 첫번째 영억
plt.subplot(151)
df[['duration']].boxplot()
plt.ylabel("Time")
# 두번째 subplot : 1행 5열로 나눈 영역에서 세번째 영억
plt.subplot(153)
df[['price']].boxplot()
plt.ylabel("Pirce")
# 세번째 subplot : 1행 5열로 나눈 영역에서 다섯번째 영역
plt.subplot(155)
df[['days_left']].boxplot()
plt.ylabel("Days")

4. 이상치 처리하기
ㅇ 삭제 : 데이터 손실
ㅇ 대채 : 데이터 변경
# 데이터 변형에 대비해 원본 복사하기
df_origin=df.copy()
1) 이상치 삭제하기
z-score로 찾아낸 이상치 제거 : 데이터프레임의 인덱스를 리스트로 만들어 제거
# 신뢰도 95% 기준 이상치 인덱스 추출하기
outlier = df[(abs(df['price']-df['price'].mean())/df['price'].std())>1.96].index
outlier

# 추출한 인덱스의 행을 삭제해서 clean_df 데이터프레임 만들기
clean_df = df.drop(outlier)
clean_df.info()

# boxolot으로 확인해보기
plt.figure(figsize=(4,5))
# boxplot
clean_df[['price']].boxplot()
plt.show()

2) 이상치 데이터 대체하기
IQR 하단의 이상치는 최소값으로, IQR 상단 이상치는 최대값으로 대체하는 함수 만들어서 데이터 처리하기
#IQR 기준을 벗어나는 이상치를 대체하는 함수 만들기
# 함수에서 x는 데이터프레임, column은 column 이름임
def chageOutlier(x, column):
#1분위수 구하기
q1=x[column].quantile(0.25)
#3분위수 구하기
q3=x[column].quantile(0.75)
#iqr의 1.5배수(iqr15)구하기
iqr15=1.5*(q3-q1)
#min, max값 설정하기
min=q1-iqr15
max=q3+iqr15
# max보다 큰 값은 max로 min보다 작은 값은 min으로 대체하기
x.loc[x[column]>max,column]=max
x.loc[x[column]<min,column]=min
# x 리턴하기
return(x)
# price에 대해 이상치 대체하기
clean_df=chageOutlier(df, 'price')
clean_df

# price에 대해 IQR 기준의 이상치 갯수 확인하기
print("price IQR Outlier : ", findOutliers(clean_df, 'price'))

5. 구간화
연속형 데이터를 특정 구간으로 나누어 범주형 또는 순위형으로 변환하는 방법
ㅇ 수능점수를 등급으로 변환, 나이를 세대로 변환하는 것
ㅇ 이상치로 발생할 수 있는 문제를 줄이고, 결과에 대한 해석이 쉬워짐
ㅇ 동일 길이로 구간화, 동일 갯수로 구간화
1) 동일 길이로 구간화 : cut, 사용자가 구간값을 직접 입력 (예, 40 이내의 소수를 10단위로 나누기)
구간화 하고자 하는 값, bins(구간화 지점 리스트)와 labels(구간화된 값의 이름, bins보다 1 적게)을 같이 지정해줘야 함
duration(비행시간)을 0~5시간은 단거리, 5~10시간을 중거리, 10시간 이상을 장거리로 구분해보기(distance칼럼 생성)
df['distance']=pd.cut(df['duration'], bins=[0,5,10,df['duration'].max()], labels=['short','medium','longg'])
df.head()

# distance 칼럼의 빈도 확인하기
df['distance'].value_counts()

2) 동일 갯수로 구간화 : qcut, 사용자가 구간 갯수를 입력 (예, 40 이내의 소수를 4개 구간으로 나누기)
cut 과 사용방법 동일하나, bins 대신 정수를 넣어 몇개 구간으로 나눌건지 지정
df['price_rate']=pd.qcut(df['price'], 4, labels=['cheap','normal','expensive','too expensive'])
df.head()

#price_rate 칼럽의 빈도 확인하기
df['price_rate'].value_counts()

'Tech' 카테고리의 다른 글
| Ch7. AI 모델링 (2) | 2024.06.24 |
|---|---|
| Ch6. 데이터 전처리 - 레이블 인코딩, 스케일링, 변수선택 (0) | 2024.06.08 |
| Ch5. 데이터 지표화 및 시각화 (1) | 2024.06.07 |
| Ch.4 기초데이터 다루기 / Sec2. 필요데이터 변경하기 (0) | 2024.06.01 |
| Ch.4 기초데이터 다루기 / Sec1. 필요 데이터 선택하기 (0) | 2024.05.30 |