파이썬: 실전팁 for EDA [전용준.리비젼컨설팅]
(지극히 주관적인...) 실전에서의 탐색적 데이터 분석 방법 (Tips) 몇 가지
요점은 ....
? [1] 익숙한 하나의 라이브러리를 집중적으로 사용한다 (esp. plt.scatter )
? [2] 많은 변수가 있다면 핵심변수에 우선 집중한다 (esp. Target이 있는 경우)
? [3] 세개의 변수를 한 Set으로 (그리고 3 변수 까지만. 그리고, No 3D plot)
__Plus__
? 실전에서 그림이 예쁜지는 중요 X
? 초기 EDA는 보고용이 아니라 분석용
? 극명한 패턴을 빠르게 찾아내야
[ #머신러닝 #EDA #파이썬 #전용준 #리비젼 #리비젼컨설팅
#탐색적데이터분석 #데이터분석 #python #visualization
#scatter #decisiontree #catboost #variableimportance #변수중요도 ]
머신러닝, EDA, 파이썬, 전용준, 리비젼, 리비젼컨설팅, 탐색적데이터분석, 데이터분석, python, visualization, scatter, decisiontree, catboost, variable importance, 변수중요도
[ 유튜브 영상 ]
How I Do EDA :: Retail Customer Analysis -- BuyIt.com¶
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from numpy.polynomial.polynomial import polyfit
import matplotlib.style as style
from IPython.display import Image
import warnings
warnings.filterwarnings('ignore')
# define random jitter
def rjitt(arr):
stdev = .01*(max(arr)-min(arr))
return arr + np.random.randn(len(arr)) * stdev
dataPath = 'C:/YONG/m1710/myPydata/'
def rjitt2(arr):
stdev = .031*(max(arr)-min(arr))
return arr + np.random.randn(len(arr)) * stdev
# min max scaler
def mnmx_scl(vec):
vec = (vec-vec.min())/(vec.max()-vec.min())
return(vec)
def mnmx_scl2(vec):
vec = np.where(np.percentile(vec, 95) < vec,
np.percentile(vec, 95), vec)
vec = np.array(vec)
vec = (vec-vec.min())/(vec.max()-vec.min())
return(vec)
A Practitioner's Tips for EDA - How I Do EDA¶
[전용준. 리비젼컨설팅. 머신러닝]
? [1] 익숙한 하나의 라이브러리를 집중적으로 사용한다 (esp. plt.scatter )
? [2] 많은 변수가 있다면 핵심변수에 우선 집중한다 (esp. Target이 있는 경우)
? [3] 세개의 변수를 한 Set으로 (그리고 3 변수 까지만. 그리고, No 3D plot)
# 블로그로부터 연습용 CSV 형식의 데이터 불러오기
dff01 = pd.read_csv('https://t1.daumcdn.net/cfile/blog/992CFF3B5D5CC70C2C?download')
print('Shape of the dataset : ', dff01.shape)
dff01.head()
[1] 익숙한 하나의 라이브러리를 집중적으로 사용한다 (esp. plt.scatter() )¶
# matplotlib scatter 사용
plt.scatter(dff01.amt_strbk, dff01.amt_book)
plt.xlabel('AMT STARBUCKS')
plt.ylabel('AMT BOOK')
plt.show()
# alpha 투명도 옵션을 활용
plt.scatter(dff01.amt_strbk, dff01.amt_book, s=5, alpha=0.2)
plt.xlabel('AMT STARBUCKS')
plt.ylabel('AMT BOOK')
plt.show()
# matplotlib scatter 사용
plt.scatter(rjitt(dff01.amt_strbk), rjitt(dff01.amt_book), s=5, alpha=0.2)
plt.xlabel('AMT STARBUCKS')
plt.ylabel('AMT BOOK')
plt.show()
# target이 있다면 target을 표시
median_age = dff01.age.median()
colors1 = ['red' if x>median_age else 'blue' for x in dff01.age]
plt.scatter(rjitt(dff01.amt_strbk), rjitt(dff01.amt_book),
s=5, alpha=0.2,
color=colors1)
plt.xlabel('AMT STARBUCKS')
plt.ylabel('AMT BOOK')
plt.title('blue: young')
plt.show()
? matplotlib도 seaborn도 pandas도 좋다. 문제는 우왕좌왕하면서 구글검색에 시간을 낭비할 필요가 없다는 것
# 보조선은 시각적인 판단을 빠르게 하는데 크게 기여한다
median_age = dff01.age.median()
colors1 = ['red' if x>median_age else 'blue' for x in dff01.age]
plt.scatter(rjitt(dff01.amt_strbk), rjitt(dff01.amt_book),
s=5, alpha=0.2,
color=colors1)
plt.xlabel('AMT STARBUCKS')
plt.ylabel('AMT BOOK')
plt.title('blue: young ; orange line:20%')
plt.axvline(np.percentile(dff01.amt_strbk,80),
color='orange',linestyle=':')
plt.axhline(np.percentile(dff01.amt_book,80),
color='orange',linestyle=':')
plt.show()
Findings :¶
? 서적 구매가 전혀 없는 고객들이 다수
? 스타벅스 구매는 대부분의 고객들이 약간이라도 있음
? 젊은 여성쪽에서 스타벅스와 서적 모두의 구매금액이 큰 경우 많음
? 스타벅스와 서적 모두 구매한 집단에서는 두 품목간 양의 상관관계 존재하는듯
[2] 많은 변수가 있다면 핵심변수에 우선 집중한다 (esp. Target이 있는 경우)¶
? 변수가 여러개라면 DT나 RF(?), CatBoost로 변수 중요도를 구한다 (아직은 __모델__이 아니다. 변수 탐색을 위한 보조Tool일 뿐)
? RF를 사용하게되면 Categorical Variable을 encoding하는 번거러움이 있으니 __CatBoost__가 편하다
# searching for key variables using DT
from sklearn.tree import DecisionTreeRegressor
dt1 = DecisionTreeRegressor(min_samples_split=50, max_depth=3, min_samples_leaf=10, random_state=99)
dtfeatures = ['height','weight','amt_strbk','amt_book']
tgt = 'age'
dfdt = dff01
dt1.fit(dfdt[dtfeatures], dfdt[tgt])
# path should have set
# or [ InvocationException: GraphViz's executables not found ] occur
import os
os.environ["PATH"] += os.pathsep + 'C:\\Program Files\\Anaconda3\\Library\\bin\\graphviz'
from sklearn import tree
from IPython.display import Image
import pydotplus
import graphviz
print('variable importance : ', dict(zip(dfdt[dtfeatures].columns, dt1.feature_importances_)))
# Create DOT data
dot_data = tree.export_graphviz(dt1, out_file=None,
feature_names=dtfeatures)
# Draw graph
graph = pydotplus.graph_from_dot_data(dot_data)
# Show graph
Image(graph.create_png())
# searching for key variables
# A deeper and bush tree can show more info on Var Imp
from sklearn.tree import DecisionTreeRegressor
dt1 = DecisionTreeRegressor(min_samples_split=30, max_depth=5,
min_samples_leaf=5, random_state=99)
dtfeatures = ['height','weight','amt_strbk','amt_book']
tgt = 'age'
dfdt = dff01
dt1.fit(dfdt[dtfeatures], dfdt[tgt])
# path should have set
# or [ InvocationException: GraphViz's executables not found ] occur
import os
os.environ["PATH"] += os.pathsep + 'C:\\Program Files\\Anaconda3\\Library\\bin\\graphviz'
from sklearn import tree
from IPython.display import Image
import pydotplus
import graphviz
print('variable importance : ', dict(zip(dfdt[dtfeatures].columns, dt1.feature_importances_)))
# Create DOT data
dot_data = tree.export_graphviz(dt1, out_file=None,
feature_names=dtfeatures)
# Draw graph
graph = pydotplus.graph_from_dot_data(dot_data)
# Show graph
Image(graph.create_png())
d = dict(zip(dfdt[dtfeatures].columns, dt1.feature_importances_))
d.items()
ddf = pd.DataFrame(pd.Series(d, name='Importance')).reset_index().sort_values('Importance')
ddf.columns = ['VarName', 'Importance']
ddf
plt.barh(ddf['VarName'], ddf['Importance'], color='navy')
plt.title('Features Predicting AGE')
plt.xlabel('Relative Feature Importance from DT')
plt.show()
? __CatBoost__는 여러개의 트리를 생성하기 때문에 보다 안정적인 (=믿음직스런) 결과를 준다
? CatBoost는 한 두개 핵심변수 이외의 변수들의 중요도도 나름 공평하게 인정해준다.
(핵심변수의 영향을 과대평가하는 것을 방지하는데 도움이 된다. 다만, 실행에 조금 더 많은 리소스가 필요하다)
from catboost import CatBoostRegressor
model = CatBoostRegressor(iterations=300, depth=3, learning_rate=0.01,
eval_metric='R2',
use_best_model=True,
random_seed=42)
train_x = dfdt[dtfeatures]
tgt = 'age'
train_y = dfdt[tgt]
model.fit(
train_x, train_y,
# cat_features=categorical_features_indices,
# verbose=True, # you can uncomment this for text output
# plot=True, # does not work for classifier
eval_set=(train_x, train_y)
)
# Mapping Feature Importance
plt.figure()
fea_imp = pd.DataFrame({'imp': model.feature_importances_, 'col': train_x.columns})
fea_imp['imp'] = round(fea_imp.imp, 2)
fea_imp = fea_imp.sort_values(['imp', 'col'], ascending=[True, False]).iloc[-30:]
_ = fea_imp.plot(kind='barh', x='col', y='imp', figsize=(4, 4))
plt.title('Var Imp in Predicting AGE from CatBoost')
plt.show()
fea_imp1 = fea_imp.sort_values('imp', ascending=False)
# add row total
fea_imp1['cum_sum_imp']= round(fea_imp1['imp'].cumsum(),2)
fea_imp1.loc['row_total'] = fea_imp.apply(lambda x: x.sum())
fea_imp1
# 이제 핵심변수 두 가지를 중심으로 Scatter Plot을 그린다
# 일정한 규칙으로 X, Y 축을 정한다 (예: 중요도 1위 변수를 항상 X축에, 2등은 Y축에)
median_age = dff01.age.median()
colors1 = ['red' if x>median_age else 'blue' for x in dff01.age]
plt.scatter(rjitt(dff01.height), rjitt(dff01.amt_book),
s=5, alpha=0.2,
color=colors1)
plt.xlabel('HEIGHT')
plt.ylabel('AMT BOOK')
plt.title('blue: young ; orange line:20%')
plt.axvline(np.percentile(dff01.height,80),
color='orange',linestyle=':')
plt.axhline(np.percentile(dff01.amt_book,80),
color='orange',linestyle=':')
plt.show()
[3] 세개의 변수를 한 Set으로 (그리고 3 변수 까지만. 그리고, No 3D plot)¶
? 3d plot은 아무 것도 보이지 않으니까~
# 이 번에는 target인 age를 연속적으로 표시 (red~blue)
# scale age
rage = mnmx_scl(dff01.age)
colors1 = [(x, 0, 1-x) for x in rage]
plt.figure(figsize=(20, 3))
plt.subplot(141)
# 일정한 규칙으로 X, Y 축을 정한다 (예: 중요도 1위 변수를 항상 X축에, 2등은 Y축에)
# 첫번째 그림
plt.scatter(rjitt(dff01.height), rjitt(dff01.amt_book),
s=5, alpha=0.1,
color=colors1)
plt.xlabel('HEIGHT')
plt.ylabel('AMT BOOK')
plt.title('blue: young ; orange line:20%')
plt.axvline(np.percentile(dff01.height,80),
color='orange',linestyle=':')
plt.axhline(np.percentile(dff01.amt_book,80),
color='orange',linestyle=':')
# 두번째 그림
plt.subplot(142)
plt.scatter(rjitt(dff01.weight), rjitt(dff01.amt_book),
s=5, alpha=0.3,
color=colors1)
plt.xlabel('WEIGHT')
plt.ylabel('AMT BOOK')
plt.title('blue: young ; orange line:20%')
plt.axvline(np.percentile(dff01.weight,80),
color='orange',linestyle=':')
plt.axhline(np.percentile(dff01.amt_book,80),
color='orange',linestyle=':')
# 마지막 그림
plt.subplot(143)
plt.scatter(rjitt(dff01.height), rjitt(dff01.weight),
s=5, alpha=0.3,
color=colors1)
plt.xlabel('HEIGHT')
plt.ylabel('WEIGHT')
plt.title('blue: young ; orange line:20%')
plt.axvline(np.percentile(dff01.height,80),
color='orange',linestyle=':')
plt.axhline(np.percentile(dff01.weight,80),
color='orange',linestyle=':')
plt.show()
3차원 플롯을 그리는 것이야 어렵지 않겠으나 그린 결과에서 눈에 패턴이 선명하게 보이지 않는다
--> 회전을 시킨다고 잘 보일 것이라는 기대는 흔히 깨진다
# 3d scatter plotting
from mpl_toolkits import mplot3d
fig = plt.figure(figsize=(8,5))
ax = plt.axes(projection="3d")
ax.scatter3D(rjitt(dff01.height), rjitt(dff01.amt_book), rjitt(dff01.weight),
alpha=0.2, s=5, color=colors1)
plt.xlabel('HEIGHT')
plt.ylabel('AMT BOOK')
plt.title('blue: young')
plt.show()
Recap - 지극히 주관적인 EDA 실전 Tips¶
[전용준. 리비젼컨설팅. 머신러닝]
? [1] 익숙한 하나의 라이브러리를 집중적으로 사용한다 (esp. plt.scatter )
? [2] 많은 변수가 있다면 핵심변수에 우선 집중한다 (esp. Target이 있는 경우)
? [3] 세개의 변수를 한 Set으로 (그리고 3 변수 까지만. 그리고, No 3D plot)
Plus
? 실전에서 그림이 예쁜지는 중요 X
? 초기 EDA는 보고용이 아니라 분석용
? 극명한 패턴을 빠르게 찾아내야
- 끝 -
'Python데이터분석' 카테고리의 다른 글
py EDA practice (0) | 2019.10.29 |
---|---|
[ssfc_pda01] Class 분석 프로젝트 진행방안 (0) | 2019.10.22 |
[파이썬] 히트맵 heatmap 을 활용한 탐색적 분석 예제 (0) | 2019.08.21 |
[파이썬] Numpy와 Pandas 구글 검색 지수 추이 비교 - 시각화 (0) | 2019.08.08 |
[Python 분석]온라인 서점 고객세분화 Visual Data Exploration 예제 (0) | 2019.07.18 |