
오늘의 학습 목표
- 데이터 전처리의 전 과정에 대해 살펴본다
- 중복 데이터 처리, 결측치 처리, 데이터 정규화, 이상치 처리에 대해 이해한다
- 범주형 데이터의 전처리 방법으로 원-핫 인코딩 방법을 이해한다
- 연속적인 데이터를 구간으로 나눠 범주형 데이터로 변환하는 방법을 이해한다
- 위의 전 과정을 python 환경에서 경험한다 (단, 처리 방법에 대해 경험하는 수준으로 완벽한 데이터 전처리를 요구하지 않는다)
!pip install kagglehub
import kagglehub
# Download latest version
path = kagglehub.dataset_download("gregorut/videogamesales")
print("Path to dataset files:", path)import pandas as pd
trade = pd.read_csv("f{path}/vgsales.csv")
train.head() #데이터 상단의 n개 행 출력
train.info() #변수 정보 확인하기
print('전체 데이터 건수:', len(train))
print('컬럼별 결측치 개수', len(train) - train.count())
info() 함수의 결과를 보면 변수별로 non-null count가 나오는데 이를 통해서도 알 수 있다train['Year'].isna().sum()train['Missing_Data'] = None # Missing_Data 컬럼을 추가하고 NaN값으로 채워줌
train.info() # 실행해보면 Missing_Data 컬럼은 0 Non-Null 로 모두 null값임을 확인할 수 있다
train = train.drop('Missing_Data', axis=1) # drop() 사용자가 지정한 특정 행/열 삭제 함수. axis = 1은 열을 의미. axis=0은 행을 의미.
train.columns
drop 대신 train.dropna(axis=1, how='any', subset=['Missing_Data'], inplace=True) 를 사용할 수도 있다inplace = True 덕분에 따로 train = train.dropna ... 을 할 필요 없이 원본 데이터에 바로 적용된다how 옵션으로는all 전부가 결측치인 경우any 하나라도 결측치인 경우dropna, fillna 모두 결측치에 대해 동작# Year 결측치: 중앙값으로 대체
median_year = train['Year'].median()
train['Year'].fillna(median_year, inplace=True) # 결측치 채워 넣기
# train['Year'] = train['Year'].fillna(median_year) 이 방식을 권장
train['Year'] = train['Year'].astype('int')
print("Year 대체 후:", train['Year'].isna().sum())
print("중앙값:", median_year)
# Publisher 결측치: 'Unknown'으로 대체 (범주형)
train['Publisher'].fillna('Unknown', inplace=True)
print("Publisher 대체 후:", train['Publisher'].isnull().sum())
print("'Unknown' 비율:", (train['Publisher']=='Unknown').mean()*100, "%")
train.loc[row, column] 특정 행과 열 추출print("전체 중복:", train.duplicated().sum())
print("Name+Platform+Year 중복:", train.duplicated(subset=['Name', 'Platform', 'Year']).sum())
# 중복 데이터 확인
duplicate_rows = train[train.duplicated(subset=['Name', 'Platform', 'Year'], keep=False)]
print(duplicate_rows)
# 중복 데이터 제거
train = train.drop_duplicates(subset=['Name', 'Platform', 'Year'])
print("Name+Platform+Year 중복제거확인:", train.duplicated(subset=['Name', 'Platform', 'Year']).sum())
z score 방법abs(df[col] - np.mean(df[col])) 데이터에서 평균을 빼준 것에 절대값을 취합니다.abs(df[col] - np.mean(df[col]))/np.std(df[col]) 위에서 얻은 값을 표준편차로 나눠줍니다.df[abs(df[col] - np.mean(df[col]))/np.std(df[col])>z].index 값이 z보다 큰 데이터의 인덱스를 추출합니다.def outlier(df, col, z):
return df[abs(df[col] - np.mean(df[col]))/np.std(df[col])>z].index
import numpy as np
# IQR 함수
def detect_outliers_iqr(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df[column] < lower) | (df[column] > upper)]
print(f"{column} 이상치: {len(outliers)}개")
return lower, upper
# Global_Sales에 IQR 적용
lower, upper = detect_outliers_iqr(train, 'Global_Sales')
train = train[(train['Global_Sales'] >= lower) & (train['Global_Sales'] <= upper)]
# Year 이상치 제한
train = train[(train['Year'] >= 1980) & (train['Year'] <= 2020)]
print("Year 범위 제한 후:", len(train))
x_standardization = (x-x.mean())/x.std()x_min_max = (x-x.min())/(x.max()-x.min())from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
sales_cols = ['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']
train[sales_cols] = scaler.fit_transform(train[sales_cols])
print("정규화 범위 (Global_Sales):", train['Global_Sales'].min(), "~", train['Global_Sales'].max())
from sklearn.preprocessing import OneHotEncoder
cat_cols = ['Platform', 'Genre']
encoder = OneHotEncoder(sparse_output=False, drop='first')
encoded = encoder.fit_transform(train[cat_cols])
encoded_df = pd.DataFrame(encoded, columns=encoder.get_feature_names_out(cat_cols))
train = pd.concat([train.drop(cat_cols, axis=1).reset_index(drop=True), encoded_df.reset_index(drop=True)], axis=1)
# concat: 두 데이터프레임을 합쳐주는 함수
print("원-핫 후 컬럼 수:", len(train.columns))
get_dummies 함수 이용하는 방법도 있다bins_year = [1980, 1995, 2005, 2015, 2021]
labels_year = ['80s-94', '95-04', '05-14', '15-20']
# cut함수에 데이터와 구간을 입력하면 데이터를 구간별로 나눠준다
train['Year_Group'] = pd.cut(train['Year'], bins=bins_year, labels=labels_year, right=False)
print(train['Year_Group'].value_counts())
bins_sales = [0, 0.1, 0.5, float('inf')]
labels_sales = ['플래티넘', '골드', '실버']
train['Sales_Rank'] = pd.cut(train['Global_Sales'], bins=bins_sales, labels=labels_sales, right=False)
print(train['Sales_Rank'].value_counts()) # value_counts()로 구간별 값을 확인할 수 있다
cut 함수 대신 qcut함수를 사용할 수도 있다
qcut은 구간을 일정하게 나누는 것이 아니라 데이터의 분포를 비슷한 크기의 그룹으로 나눠줌실습 마무리
print("최종 shape:", train.shape)
train.info()
train.head()
train.to_csv('processed_vgsales.csv', index=False)
실습 결과 모음
![]()