240531 Today I Learn
์ด์์น, ๊ฒฐ์ธก์น๋?
๐ก ๊ฒฐ์ธก์น
๋ฐ์ดํฐ ์์ง ๊ณผ์ ์์ ์ธก์ ๋์ง ์๊ฑฐ๋ ๋๋ฝ๋ ๋ฐ์ดํฐ
๐ก ์ด์์น
์ ์ฒด ๋ฐ์ดํฐ ๋ฒ์์์ ๋ฒ์ด๋ ์์ฃผ ์์ ๊ฐ์ด๋ ํฐ ๊ฐ
ํ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๋๋ณด๊ธฐ
import pandas as pd
import numpy as np
import time
from PIL import Image
import warnings
# ์ค๋ฅ ๊ฒฝ๊ณ ๋ฌด์ํ๊ธฐ
warnings.filterwarnings(action='ignore')
๊ฒฐ์ธก์น ์ฒ๋ฆฌํ๊ธฐ
1. ๊ฒฐ์ธก์น ์ ๊ฑฐํ๊ธฐ
- ๊ฒฐ์ธก์น๊ฐ ์๋ ์ด ์ ๊ฑฐํ๊ธฐ
# ์ปฌ๋ผ๋ช
์ด 'Unnamed:4'์ธ ์ด ์ ๊ฑฐํ๊ธฐ
df3 = df3.drop('Unnamed: 4', axis=1)
# ์ปฌ๋ผ์ด ์ ๊ฑฐ๋์๋์ง ํ์ธํ๊ธฐ
df3.isnull().sum()
## user id 295
## product id 295
## Interaction type 423
## Time stamp 295
- ๊ฒฐ์ธก์น๊ฐ ์๋ ํ ์ ๊ฑฐํ๊ธฐ
# ๊ฒฐ์ธก์น๊ฐ ์๋ ํ๋ค์ ๋ชจ๋ ์ ๊ฑฐํ๊ธฐ
df3.dropna(inplace=True)
# ๊ฒฐ์ธก์น๊ฐ ์ ๊ฑฐ๋์๋์ง ํ์ธํ๊ธฐ
df3.isnull().sum()
## user id 0
## product id 0
## Interaction type 0
## Time stamp 0
2. ๊ฒฐ์ธก์น ์ฑ์ฐ๊ธฐ
- ๋ฒ์ฃผํ ๋ณ์ : ์ต๋น๊ฐ์ผ๋ก ์ฑ์ฐ๊ธฐ
- df3์ ์๋ 'Interaction Type' ์ปฌ๋ผ์ ์ด 423๊ฐ์ ๊ฒฐ์ธก์น๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
- ํด๋น ์ปฌ๋ผ์ 'purchase', 'view', 'like' ์ด ์ธ๊ฐ์ ๋ฒ์ฃผ๋ก ๊ตฌ๋ถ๋ ๋ฒ์ฃผํ ๋ฐ์ดํฐ๊ฐ ์๋ ์ปฌ๋ผ์ด๋ฏ๋ก ์ต๋น๊ฐ์ผ๋ก ๊ฒฐ์ธก์น๋ฅผ ์ฑ์ธ ์ ์๋ค.
# ๊ฒฐ์ธก์น๊ฐ ์๋ Interaction type ์ปฌ๋ผ์ ์ต๋น๊ฐ์ผ๋ก ๋์ฒดํ๊ธฐ ์ํด, ํด๋น ์ปฌ๋ผ์ ์ต๋น๊ฐ์ ๊ตฌํจ
df3['Interaction type'].mode()
# ์ต๋น๊ฐ ๊ฒ์ฆ : ๊ฒฐ์ธก์น๋ ์นด์ดํธ๋์ง ์์์
df3.groupby('Interaction type').count()
→ df3์ 'Interaction type' ์ปฌ๋ผ์ ์ต๋น๊ฐ์ like์ด๋ค.
# fillna()๋ฅผ ์ด์ฉํด ์ต๋น๊ฐ์ผ๋ก ๊ฒฐ์ธก์น ์ฑ์ฐ๊ธฐ
df3 = df3['Interaction type'].fillna(df3['Interaction type'].mode().iloc[0])
# ์ฐ์ฐ ํ ์ธ๋ฑ์ค ์ฌ์ค์
df3= df3.reset_index()
# ์ต๋น๊ฐ์ผ๋ก ๋์ฒด๋ ๋ฐ์ดํฐํ๋ ์ ํ์ธ
df3.groupby('Interaction type').count()
→ df3์ 'Interaction type' ์ปฌ๋ผ์ ์์๋ 423๊ฐ์ ๊ฒฐ์ธก์น๊ฐ ์ต๋น๊ฐ์ธ 'like'๋ก ๋ชจ๋ ์ฑ์์ก๋ค.
- ์์นํ ๋ณ์: ํ๊ท / ์ค์๊ฐ์ผ๋ก ์ฑ์ฐ๊ธฐ
# Shipping Weight ์ ๊ฒฝ์ฐ, 1138 ๊ฐ์ ๊ฒฐ์ธก์น๊ฐ ์์ต๋๋ค.
df['Shipping Weight'].isnull().sum()
# split ์ด์ฉํด ๋จ์ ๋ถ๋ถ์ ์ ์ธํ ๋ฌด๊ฒ ์ ๋ณด ์ถ์ถ
df['Shipping Weight'].str.split().str[1]
# string to float, ์๋ฌ๋ฌด์
df['sw'] = pd.to_numeric(df['sw'] , errors='coerce')
# ํ๊ท ๊ฐ ๋์ฒด
# inplace=True ๋ก ํ๋ฉด ์๋ณธ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๊ฒ ๋ฉ๋๋ค.
df['sw'] = df['sw'].fillna(df['sw'].mean())
# ์ค๊ฐ๊ฐ ๋์ฒด
# inplace=True ๋ก ํ๋ฉด ์๋ณธ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๊ฒ ๋ฉ๋๋ค.
df['sw'] = df['sw'].fillna(df['sw'].median())
# group by ๋ฅผ ํ์ฉํ ๋์ฒด
# Is Amazon Seller ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค์๊ฐ ๊ณ์ฐํ์ฌ ๋์ฒด
df['sw'] = df['sw'].fillna(df.groupby('Is Amazon Seller')['sw'].transform('median'))
- ์์นํ ๋ณ์: KNN Imputation
๐ก KNN Imputation
๋ชจ๋ ๋ณ์๋ฅผ ๊ณ ๋ คํ์ฌ k๊ฐ์ ๊ฐ๊น์ด ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ ๊ทธ ๋ฐ์ดํฐ์์ ๊ฑฐ๋ฆฌ์ ๋ฐ๋ผ ๊ฐ์ค ํ๊ท ์ ์ทจํด์ค
์ด๋ป๊ฒ ์ฑ์์ผํ ์ง ์์ด๋์ด๊ฐ ์์ ๋ ์ฃผ๋ก ์ฌ์ฉ
- KnnImputer๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ฐ์ดํฐ์ ๋ฌธ์์ด์ด ์กด์ฌํด์ ์๋จ
# ์๋ ์ฝ๋๋ Shipping Weight ๋ฅผ int ํ์์ผ๋ก ๋ณ๊ฒฝ
df['sw'] = df['Shipping Weight'].str.split().str[0]
df['sw'] = pd.to_numeric(df['sw'] , errors='coerce').fillna(0.0).astype(int)
# KNN -> ๋ฐ๋์ ์ธ์ฝ๋ฉ ์์
์ ํตํด ๋ฐ์ดํฐํ๋ ์์ ์ซ์ํํ๋ก ๋ณํํด์ฃผ์ด์ผํจ.
knn_df = df[['sw']]
- ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ ํ์คํ๊ฐ ์ ํ๋์ด์ผํจ. → ๋ชจ๋ ๋ณ์๋ค์ ๊ฑฐ๋ฆฌ๊ณ์ฐ์ ๋ํ ๊ธฐ์ฌ๋๋ฅผ ๋น์ทํ๊ฒ ํ๊ธฐ ์ํด์
# ํ์คํ๋ฅผ ์งํํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ธ
from sklearn.preprocessing import StandardScaler
# ํ์คํ ์งํ
scale_df = StandardScaler().fit_transform(knn_df)
# KNN Imputation ์งํํ๊ธฐ
import pandas as pd
from sklearn.impute import KNNImputer
# KNNImputer ๊ฐ์ฒด ์์ฑ
imputer = KNNImputer(n_neighbors=3) # K(์ด์์ ์) ์ง์
# KNN์ ์ฌ์ฉํ์ฌ ๊ฒฐ์ธก์น ๋์ฒด
filled_df = pd.DataFrame(imputer.fit_transform(scale_df), columns=knn_df.columns)
์ด์์น ์ฒ๋ฆฌํ๊ธฐ
1. ์ด์์น ์๋ณ ๊ธฐ๋ฒ
๐ก Z-Score
๋ฐ์ดํฐ์ ๋ถํฌ๊ฐ ์ ๊ท ๋ถํฌ๋ฅผ ์ด๋ฃฐ ๋, ๋ฐ์ดํฐ์ ํ์ค ํธ์ฐจ๋ฅผ ์ด์ฉํด ์ด์์น๋ฅผ ํ์งํ๋ ๋ฐฉ๋ฒ.
๊ฐ ๋ฐ์ดํฐ(ํ) ๋ง๋ค Z-score ๋ฅผ ๊ตฌํฉ๋๋ค. Z ๊ฐ์ X์์ ํ๊ท ์ ๋บ ๋ฐ์ดํฐ๋ฅผ ํ์คํธ์ฐจ๋ก ๋๋ ๊ฐ์ด๋ฉฐ, ํ์ค ์ ์๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํ์ค์ ์(Z๊ฐ)์ ํ๊ท ์ผ๋ก๋ถํฐ ์ผ๋ง๋ ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ฉฐ, ±3 ์ด์์ด๋ฉด ์ด์์น๋ก ๊ฐ์ฃผ
- Z-Score : 0 ํด๋น ๋ฐ์ดํฐ๋ ํ๊ท ๊ณผ ๊ฐ์ (=ํ๊ท ์์ ๋จ์ด์ง ๊ฑฐ๋ฆฌ๊ฐ 0)
- Z-Score > 0 : ํด๋น ๋ฐ์ดํฐ ํ๊ท ๋ณด๋ค ํผ.
- Z-Score = 1 : ํด๋น ๋ฐ์ดํฐ ํฌ์ธํธ๋ ํ๊ท ๋ณด๋ค 1 ํ์คํธ์ฐจ๋งํผ ๋ ํฐ ๊ฐ์ด๋ค.
- Z-Score > 0 : ํด๋น ๋ฐ์ดํฐ๋ ํ๊ท ๋ณด๋ค ์๋ค.
- Z-Score = -1 : ํด๋น ๋ฐ์ดํฐ ํฌ์ธํธ๋ ํ๊ท ๋ณด๋ค 1 ํ์คํธ์ฐจ๋งํผ ๋ ์์
# 1. string -> float -> int ๋ก ํ์
๋ณํ
df['sw'] = df['Shipping Weight'].str.split().str[0]
df['sw'] = pd.to_numeric(df['sw'] , errors='coerce').fillna(0.0).astype(int)
# 2. z-score ๋ฅผ ์ ์ฉํ ์ปฌ๋ผ ์ ์ ๋ฐ ํ์คํ ์งํ
# ์ปฌ๋ผ์ ์
df1 = df[['sw']]
# ํ์คํ ์งํ
scale_df = StandardScaler().fit_transform(df1)
# ํ์คํ๋ scale_df๋ฅผ df1์ ์ฐ๊ฒฐํ๊ณ ์ปฌ๋ผ๋ช
๋ณ๊ฒฝ
merge_df = pd.concat([df1, pd.DataFrame(scale_df)],axis=1)
merge_df.columns = ['Shipping Weight', 'zscore']
# 3. ์ด์์น ๊ฐ์ง
# Z-SCORE ๊ธฐ๋ฐ, -3 ๋ณด๋ค ์๊ฑฐ๋ 3๋ณด๋ค ํฐ ๊ฒฝ์ฐ๋ฅผ ์ด์์น๋ก ํ๋ณ
mask = ((merge_df['zscore']<-3) | (merge_df['zscore']>3))
# mask ๋ฉ์๋ ์ฌ์ฉํด ์ด์์น ๊ฐ ๋ฝ๊ธฐ
strange_df = merge_df[mask]
strange_df
# ์ด 55 ๊ฑด ํ์ง
strange_df.count()
## Shipping Weight 55
## zscore 55
๐ก IQR
IQR : (์ 3์ฌ๋ถ์ ๊ฐ) - (์ 1์ฌ๋ถ์ ๊ฐ)
๋ฐ์ดํฐ์ 25% ์ง์ ()๊ณผ 75% ์ง์ () ์ฌ์ด์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ๊ฐ๋ค์ ๋ชจ๋ ์ด์์น๋ก ๊ฐ์ฃผ
๐จ ์ด์์น๋ Q3 + 1.5 * IQR๋ณด๋ค ๋๊ฑฐ๋ Q1 - 1.5 * IQR๋ณด๋ค ๋ฎ์ ๊ฐ์ ์๋ฏธ
- ์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ฆฐ ๊ฒ์ Box Plot ์ด๋ฉฐ, IQR ๋ฐ์ ๋ฐ์ดํฐ ํฌ์ธํธ๋ ์ด์์น๋ก ํ์๋ฉ๋๋ค.
- ๋ฐ์ดํฐ์ ๋ถํฌ๊ฐ ์ ๊ท ๋ถํฌ๋ฅผ ์ด๋ฃจ์ง ์์ ๋ ์ฌ์ฉ
# 1. string -> float -> int ๋ก ํ์
๋ณํ
df['sw'] = df['Shipping Weight'].str.split().str[0]
df['sw'] = pd.to_numeric(df['sw'] , errors='coerce').fillna(0.0).astype(int)
# 2. z-score ๋ฅผ ์ ์ฉํ ์ปฌ๋ผ ์ ์ ๋ฐ ํ์คํ ์งํ
# ์ปฌ๋ผ์ ์
df1 = df[['sw']]
# Q3, Q1, IQR ๊ฐ ๊ตฌํ๊ธฐ
q3 = df1['sw'].quantile(0.75)
q1 = df1['sw'].quantile(0.25)
iqr = q3 - q1
q3, q1, iqr
## (7.0, 1.0, 6.0)
→ ๋ฐฑ๋ถ์์๋ฅผ ๊ตฌํด์ฃผ๋ quantile ํจ์๋ฅผ ์ ์ฉํ์ฌ ์ฝ๊ฒ ๊ตฌํ ์ ์์
→ ๋ฐ์ดํฐํ๋ ์ ์ ์ฒด ํน์ ํน์ ์ด์ ๋ํ์ฌ ๋ชจ๋ ์ ์ฉ์ด ๊ฐ๋ฅ
# 3. IQR ๊ธฐ์ค ์ด์์น ํํฐ๋ง
# ์ด์์น : Q3 + 1.5 * IQR๋ณด๋ค ๋๊ฑฐ๋ Q1 - 1.5 * IQR๋ณด๋ค ๋ฎ์ ๊ฐ์ ์๋ฏธ
def is_outlier(df1):
score = df1['sw']
if score > q3 + (1.5 * iqr) or score < q1 - (1.5 * iqr):
return '์ด์์น'
else:
return '์ด์์น์๋'
# apply ํจ์๋ฅผ ํตํ์ฌ ๊ฐ ๊ฐ์ ์ด์์น ์ฌ๋ถ๋ฅผ ์ฐพ๊ณ ์๋ก์ด ์ด์ ๊ฒฐ๊ณผ ์ ์ฅ
df1['์ด์์น์ฌ๋ถ'] = df1.apply(is_outlier, axis = 1) # axis = 1 ์ง์ ํ์
# IQR ๋ฐฉ์์ผ๋ก ๊ตฌํ ์ด์์น ๊ฐ์๋ 349 ๊ฐ
df1.groupby('์ด์์น์ฌ๋ถ').count()
๐ก Isolation Forest
๋จธ์ ๋ฌ๋ ๊ธฐ๋ฒ ์ค ํ๋๋ก, ์ปฌ๋ผ ๊ฐฏ์๊ฐ ๋ง์ ๋ ์ด์์น๋ฅผ ํ๋ณํ๊ธฐ ์ฉ์ดํจ.
ํ ๋ฒ ๋ถ๋ฆฌ๋ ๋ ๋ง๋ค ๊ฒฝ๋ก ๊ธธ์ด๊ฐ ๋ถ์ฌ๋๊ณ , ํธ๋ฆฌ์์ ๋ช ๋ฒ์ ๋ถ๋ฆฌํด์ผ ํ๋์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ด์์น์ธ์ง ์๋์ง๋ฅผ ํ๋จ.
→ ์ด์์น๋ ๋ค๋ฅธ ๊ด์ธก์น์ ๋นํด ์งง์ ๊ฒฝ๋ก ๊ธธ์ด๋ฅผ ๊ฐ์ง ๋ฐ์ดํฐ์ด๋ค.
- ๋ฐ์ดํฐ์
์ ๊ฒฐ์ ํธ๋ฆฌ ํํ๋ก ํํํจ.
→ ์ง๋ฌธ๋ค์ด ๊ผฌ๋ฆฌ๋ฅผ ๋ฌผ๊ณ ์ด์ด์ ธ, ์ด์ ๊ฐ ๊ฐ์ ๋งค, ํญ๊ท, ๋๊ณ ๋, ๊ณฐ ์ค ํ๋์ ๋ฐฐ์น๋๊ฒ ๋จ. - ๊ฒฝ๋ก ๊ธธ์ด๋ก ์ ์๋ 0 ์์ 1 ์ฌ์ด๋ก ์ฐ์ถ๋๋ฉฐ, ๊ฒฐ๊ณผ๊ฐ 1 ์ ๊ฐ๊น์ธ์๋ก ์ด์์น๋ก ๊ฐ์ฃผํ๊ฒ .
๐ก DBScan
๋ฐ๋ ๊ธฐ๋ฐ์ ํด๋ฌ์คํฐ๋ง ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ด๋ ํ ํด๋ฌ์คํฐ์๋ ํฌํจ๋์ง ์๋ ๋ฐ์ดํฐ๋ฅผ ์ด์์น๋ก ํ์งํ๋ ๋ฐฉ๋ฒ
ํต์ฌ ํฌ์ธํธ๋ค์ด ์๋ก ์ฐ๊ฒฐ๋์ด ๊ตฐ์ง์ ํ์ฑํ๋ฉฐ, ์ด์ ์ฐ๊ฒฐ๋์ง ์์ ํฌ์ธํธ๋ ์ด์์น๋ก ๋ถ๋ฅํจ.
- ๋ณต์กํ ๊ตฌ์กฐ์ ๋ฐ์ดํฐ์์ ์ด์์น๋ฅผ ํ๋ณํ๋ ๋ฐ ์ ์ฉ
- ์ฃผ๋ก ์ง๋ฆฌ ๋ฐ์ดํฐ ๋ถ์, ์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ถ์์ ์ด์์น ๊ธฐ๋ฒ์ผ๋ก ์ฌ์ฉ๋จ.
- ๊ฐ ๋ฐ์ดํฐ์ ๋ฐ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฐ์ง์ ํ์ฑ์ํค๊ณ , ์ค์ ๋ ๊ฑฐ๋ฆฌ ๋ด์ ์ค์ ๋ ์ต์ ๊ฐ์์ ๋ค๋ฅธ ํฌ์ธํธ๊ฐ ์์ ๊ฒฝ์ฐ, ํด๋น ํฌ์ธํธ๋ ํต์ฌ ํฌ์ธํธ๋ก ๊ฐ์ฃผํฉ๋๋ค.
2. ์ด์์น ์ฒ๋ฆฌ
๐ ์ด์์น ์ ๊ฑฐ
- ์ด์์น๊ฐ ๋ฐ์ดํฐ ์ค๋ฅ๋ ์ ์ ํ์ง ์์ ๊ฐ์ผ ๊ฒฝ์ฐ ์ ๊ฑฐ
- ๊ทธ๋ฌ๋ ๋ฐ์ดํฐ์ ํ๋ณธ ํฌ๊ธฐ๋ฅผ ์ค์ผ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์คํ๊ฒ ํ๋ ๊ฒ์ด ์ข์
๐ ์ด์์น ๋์ฒด
- ๋ก๊ทธ ๋ณํ: ๋ฐ์ดํฐ์ ๋ก๊ทธ ๋ณํ์ ์ ์ฉํ์ฌ ๊ทน๋จ์ ์ธ ๊ฐ์ ์ํํ ์ ์์ต๋๋ค.
- ์ํ๊ฐ๊ณผ ํํ๊ฐ: ํํ๊ฐ๊ณผ ์ํ๊ฐ์ ๊ฒฐ์ ํ ํ ํํ๊ฐ๋ณด๋ค ์ ์ผ๋ฉด ํํ๊ฐ์ผ๋ก ๋์ฒด, ์ํ๊ฐ๋ณด๋ค ํฌ๋ฉด ์ํ๊ฐ์ผ๋ก ๋์ฒด
- ํ๊ท ์ ๋ ํธ์ฐจ: ์ค์์๋ก๋ถํฐ nํธ์ฐจ ํฐ ๊ฐ์ ๋์ฒดํ๋ค.
๐ ์ด์์น ๋ถ๋ฆฌ
- ์ด์์น๋ฅผ ๋ณ๋์ ๊ทธ๋ฃน์ผ๋ก ๋ถ๋ฆฌํ์ฌ ๋ถ์ํ ์ ์์ผ๋ฉฐ, ์ด์์น๊ฐ ๋ฐ์ดํฐ์ ์ค์ํ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์์ ๋ ์ ์ฉ
→ ์๋ก์ด ๋ฐ์ดํฐํ๋ ์์ ์์ฑํ์ฌ ์ด์์น๋ฅผ ์ ์ฅํด๋๋ค