Silver bullet
데이터 탐색과 기술 통계 분석 본문
1. 데이터 탐색과 빈도 분석 (Pie chart & Bar chart)
# EDA
# Exploratory Data Analysis
# 탐색적 데이터 분석
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore") # 불필요한 Warning 메시지를 꺼줍니다.
%matplotlib inline
df = pd.read_csv('cosmetics_.csv')
df.head()
df['gender'] = df['gender'].replace([1, 2], ['male', 'female']) # 교체하다
df.head()
df['gender'].value_counts().plot(kind = 'pie') # plotting a "pie" graph
df['gender'].value_counts().plot(kind = 'bar') # plotting a "bar" graph
df['marriage'] = df['marriage'].replace([1, 2, 3], ['single', 'married', 'other'])
df['marriage'].value_counts() / len(df) * 100 # 결혼한 고객 백분율로 확인
2. 데이터 탐색과 기술통계분석
DataFrame의 기본적인 기술통계량 함수 ('1회 평균 구매 비용'을 기준으로)
df = pd.read_csv('cosmetics_.csv')
df.mean()
df['amount'].max() # 가장 높은 [ 1회 평균 구매 비용 ]
df['amount'].min()
total_amount = df['count'] * df['amount']
total_amount.sum()
df['amount'].sum()
df['amount'].mean()
df['amount'].var() # 분산 variance
df['amount'].std() # 표준편차 standard deviation
df['amount'].describe()
df.info()
분포의 왜도와 첨도
- 왜도(분포가 좌우로 치우쳐진 정도)가 0 & 첨도(분포가 뾰족한 정도)가 1일 때 완전한 정규 분표로 가정할 수 있다. (https://j.mp/367VXKj)
# amount == 1회 평균 구매 비용
df['amount'].hist() # Histogram
# 왜도 (Skewness) : 0에 가까울수록 정규분포라고 가정할 수 있음 (절대값 기준 3 미초과)
# - 분포에서 긴 꼬리가 왼쪽에 있으면(분포가 우측으로 치우친 경우) 음(negative)의 왜도
# - 분포에서 긴 꼬리가 오른쪽에 있으면(분포가 왼쪽으로 치우친 경우) 양(positive)의 왜도
df['amount'].skew()
# 첨도 (Kurtosis, 분포의 뾰족한 정도) : 1에 가까울수록 정규분포라고 가정할 수 있음 (절대값 기준 8 또는 10을 미초과)
df['amount'].kurtosis()
df['decision'].hist() # 구매 요인 (사회적 요인, 심리적 요인, 외모적 요인)
df['decision'].skew() # 왜도, 분포에서 긴 꼬리가 왼쪽에 있으면 음(negative)의 왜도, 그 반대의 경우 양(positive)의 왜도를 가진다고 한다.
df['job'].kurtosis() # 첨도, 분포의 뾰족한 정도
Histogram & Distribution plot & Joint plot ('연 구매 횟수'와 '1회 평균 구매 비용'을 기준으로)
df.describe()
df.hist(bins=50, figsize=(20,15))
df_amount = df['amount'] # 1회 평균 구매 비용
df_amount.hist(bins=50, figsize=(20,15))
df_count= df['count'] # 연 구매 횟수
df_count.hist(bins=50, figsize=(20,15))
df[ df['amount'] > 3000000 ] # 이상치 확인
import seaborn as sns
sns.distplot(df_amount, rug=True)
# "dist"ribution plot
# rug : Whether to draw a rugplot on the support axis
# rugplot : 그래프 상에서 x축 위의 작은 선분으로 실제 데이터의 위치를 나타내준 것 (False로 지정하여 차이를 확인)
sns.jointplot(x="amount", y="count", data=df) # 산점도와 히스토그램을 한번에 -> Joint-plot
sns.jointplot(x="amount", y="count", data=df, kind="kde") # Kernel-density (커널이라는 함수를 활용해 추정한 확률밀도함수를 겹쳐 그려주는 방법으로 히스토그램보다 부드러운 형태의 분포 곡선을 보여줌, 상세 설명 @ https://j.mp/35TVL12)
# 꼬리가 너무 긴 형태의 분포 -> 이상치가 분포를 제대로 확인하는 것을 방해하고 있을 수 있음
3. Outlier(이상치) 의 탐지 및 제거와 전후 분포 비교 (IQR Score 활용)
- How to Detect Outliers in Machine Learning (4 Methods for Outlier Detection) @ https://bit.ly/3Pdjq1h
- Ways to Detect and Remove the Outliers @ https://j.mp/2JmPKSN
- (추가 학습) Outlier는 모두 제거해야할까?: Outlier detection, IQR @ https://j.mp/35467fq
Outlier는 모두 제거해야할까? — Outlier detection, IQR
Outlier는 정말 불필요할까? outlier를 모두 제거해야만 할까? 이 글을 통해 생각해본다.
medium.com
# 수염상자그림
df.boxplot(column='amount') # 위와 아래의 작은 검정색 선이 상/하한선, 그 밖의 경우는 Outlier (동그라미로 표시해 줌)

Interquartile Range(IQR)은 Lower Quartile(25%)와 Upper Quartile(75%) 사이의 값 (만약 Lower Quartile이 30000이고 Upper Quartile이 100000 이면 IQR은 70000이다.)
Lower Whisker = Lower Quartile - (IQR * 1.5)
Upper Whisker = Upper Quartile + (IQR * 1.5)
df['amount'].describe()
# count 2.470000e+02
# mean 1.539393e+05
# std 3.980750e+05
# min 3.000000e+03
# 25% 3.000000e+04
# 50% 5.200000e+04
# 75% 1.000000e+05
# max 5.000000e+06
# Name: amount, dtype: float64
df['amount'].quantile() # 사분위수(Quantile), default == 0.5
df['amount'].median() # 중위값 (Median)
30000 - (100000 - 30000) *1.5 #lower Whisker 근데 마이너스 값은 가격에서 나올수 없으므로 최소값(여기선 3000)으로 설정
100000 + (100000 - 30000) *1.5

24.65 * 2+50 # 전체 데이터의 99.3% -> IQR 기법
데이터 분포가 항상 정규 분포를 이루는 것은 아니기 때문에 IQR 값은 항상 적용되는 것은 아니다.
# Inter-Quantile Range == 바닥부터 75% 지점의 값 - 바닥부터 25% 지점의 값
Q1 = df['amount'].quantile(q = 0.25)
Q3 = df['amount'].quantile(q = 0.75)
IQR = Q3 - Q1
IQR
# 상한치 : 바닥부터 75% 지점의 값 + IQR의 1.5배
# 하한치 : 바닥부터 25% 지점의 값 - IQR의 1.5배
# 그 기준을 넘기면 Outlier로 판단이 가능
df_IQR = df[ (df['amount'] < Q3 + IQR * 1.5) & (df['amount'] > Q1 - IQR * 1.5) ]
df_IQR.boxplot(column='amount') # 위 아래의 작은 검정색 선이 상/하한선, 그 밖의 경우는 Outlier (동그라미로 표시해 줌)
df.boxplot(column='count') # 위 아래의 작은 검정색 선이 상/하한선, 그 밖의 경우는 Outlier (동그라미로 표시해 줌)
processed_df = df[['amount', 'count']]
processed_df = processed_df[ (processed_df['count'] < 10) & (processed_df['amount'] < 205000) ] # 상한선에 해당하는 값
processed_df.hist(bins=50, figsize=(20,15))
4. Log 함수를 활용한 Data(Feature) Scaling
- log는 큰 수를 같은 비율의 작은 수로 바꿔주는 역할을 할 수 있음 (큰 수를 작게 만들고 복잡한 계산을 간편하게 만듦, 100 vs 10000(==100^2) -> 10 vs 100(==10^2))
- 데이터 분포의 왜도(좌우로 치우친 정도) 혹은 첨도(뾰족한 정도)가 너무 큰 경우, Log 함수를 적용해 왜도/첨도를 낮춰주는 전처리를 적용할 수 있음
- 결과적으로 이를 통해 데이터(열)의 정규성을 높이고 각종 분석에서 보다 나은(정확한) 값을 얻을 수 있음
sns.jointplot(x="amount", y="count", data=processed_df, kind="kde")
# count에 비해 amount의 Scale이 너무 큰 상태
processed_df['logamount'] = np.log(processed_df['amount']) # Log 를 취한다.
processed_df['logamount']
sns.jointplot(x="logamount", y="count", data=processed_df, kind="kde")
'AI > AI' 카테고리의 다른 글
| 그로스 해킹을 위한 파이썬 통계 분석 (0) | 2024.07.04 |
|---|---|
| 교차 검정 (p-value) (0) | 2024.07.04 |
| 기초 Numpy & Pandas (0) | 2024.07.02 |
| 한글 텍스트 데이터 전처리 (0) | 2024.07.02 |
| TF-IDF & Cosine similarity 이론 (0) | 2024.07.02 |