📊맥주별 클러스터링 시각화
이번엔 맥주 데이터를 5가지 평가 요소를 기준으로 클러스터링 해보았습니다.
향, 외관, 맛 등의 요소에 따라 서로 다른 군집들이 나타날 것 같았기 때문입니다.
우선 필요한 라이브러리들을 import하고 데이터도 불러오겠습니다.
시각화 라이브러리로는 📊plotly를 사용했습니다.
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as po
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import warnings
warnings.filterwarnings('ignore')
pd.set_option('display.max_rows', 100)
data = pd.read_csv('전처리후데이터.csv', encoding='utf-8', index_col=0)
data.head(3)
✅맥주별 평점 계산하기
하나의 맥주에 대한 수많은 평가들이 있습니다.
이것을 맥주별 평점으로 환산하겠습니다.
우선 맥주 종류들을 뽑아내고 5가지 요소를 추가하려고 합니다.
tmp = data.copy()
tmp = tmp[['맥주']]
# 맥주 이름 중복행 제거 : df.drop_duplicates()
tmp.drop_duplicates(keep='first', inplace=True)
cols = ['Aroma','Appearance','Flavor','Mouthfeel','Overall']
# 5가지 요소를 컬럼에 추가합니다.
for col in cols:
tmp[col] = ''
tmp.head(5)
데이터 프레임은 잘 형성되었습니다.
이제 요소별 평균 평점을 계산하겠습니다.
# 전체 맥주 개수만큼 실행
for i in range(len(tmp)):
# 맥주 이름 추출
beer = tmp['맥주'].iloc[i]
# 평가한 유저 수
length = len(data[data['맥주']==beer])
# 5가지 평가 요소 계산
for col in cols:
# 요소별 평점 합
col_sum = data[data['맥주']==beer][col].sum()
# 요소별 평균 구하기
tmp[col].iloc[i] = col_sum/length
tmp.to_csv('맥주_종류별_평점_77.csv', encoding='utf-8')
tmp.head()
5가지 요소에 대한 평점이 잘 계산되었습니다.
✅클러스터링
실수형 컬럼들만 뽑아낸 뒤 표준화시켰습니다.
beer_names = data[['맥주']]
beer_values = data[['Aroma','Appearance','Flavor','Mouthfeel','Overall']]
# 값 표준화
scaler = MinMaxScaler()
scaler.fit(beer_values)
scaled = scaler.transform(beer_values)
scaled
이를 바탕으로 elbow point를 찾아보겠습니다.
def elbow(X):
sse = []
for i in range(1,11):
km = KMeans(n_clusters=i)
km.fit(X)
sse.append(km.inertia_)
fig = px.line(sse)
fig.show()
elbow(scaled)
x축은 cluster의 수, y축은 클러스터 내 요소들 간 거리를 제곱한 값입니다.
cluster 수는 3개로 정했습니다.
km = KMeans(n_clusters=3).fit(scaled)
km.cluster_centers_
예측된 결과값도 저장해줍니다.
# 클러스터링을 통해 맥주별 군집 예측
predict = pd.DataFrame(km.predict(scaled))
predict.columns = ['Cluster']
predict.head(3)
그리고 다시 데이터프레임으로 저장합니다.
scaled = pd.DataFrame(data=scaled, columns=['Aroma', 'Appearance', 'Flavor', 'Mouthfeel','Overall'])
scaled
여기서 beer_names의 경우 index가 0부터 순차 정렬되어 있지 않습니다.
따라서 나온 결과값과 병합하기 위해 index를 정렬합니다.
# 이거 맞춰줘야함
beer_names.reset_index(inplace=True, drop=True)
# scale 값과 클러스터링 예측값, 기존 맥주이름, 편의점 데이터 병합
result = pd.concat([scaled, beer_names], axis=1).reset_index(drop=True)
result
클러스터링 예측값도 합쳐주겠습니다.
# scale 값과 클러스터링 예측값, 기존 맥주이름, 편의점 데이터 병합
result = pd.concat([result, predict], axis=1).reset_index(drop=True)
result
그리고 각 클러스터 군집들의 Aroma, Appearance, Flavor, Mouthfeel, Overall은 어떤지 살펴보겠습니다.
c_result = km.cluster_centers_
c_result = pd.DataFrame(data=c_result)
c_result.columns = ['Aroma', 'Appearance', 'Flavor','Mouthfeel','Overall']
c_result.sort_values(by='Overall', inplace=True)
c_result
클러스터링 결과를 저장합니다.
c_result.to_csv('대표군집클러스터링.csv', encoding='utf-8')
result.to_csv('전체맥주클러스터링.csv', encoding='utf-8')
✅클러스터링 시각화
마지막으로는 각 클러스터와 특정 맥주의 군집을 방사형 차트로 표현해보겠습니다.
def show_cluster(result, name):
categories = ['Aroma', 'Appearance', 'Flavor','Mouthfeel', 'Overall']
color = ['skyblue', 'blue', 'salmon', 'green']
target = result[result['맥주'] == name]
cluster = target['Cluster'].iloc[0]
target = target[categories]
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r = c_result.values[0],
theta = categories,
fill='toself',
name='Soso',
line_color=color[0]
))
fig.add_trace(go.Scatterpolar(
r = c_result.values[1],
theta = categories,
fill='toself',
name='Sad',
line_color=color[1]
))
fig.add_trace(go.Scatterpolar(
r = c_result.values[2],
theta = categories,
fill='toself',
name='Good',
line_color=color[2]
))
fig.add_trace(go.Scatterpolar(
r = target.values[0],
theta = categories,
fill='toself',
name=name,
line_color=color[3]
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
)),
)
fig.show()
# 클라우드 맥주 클러스터링 결과
show_cluster(result, 'Kloud Original Gravity')
# 코젤 다크의 클러스터링 결과
show_cluster(result, 'Kozel Černý (Dark) 10°')
5가지 요소에 대해 특별한 인사이트를 찾을 수 없었다는 점이 아쉽습니다.
서로 모양도 비슷합니다.
다만 해당 맥주의 보편적인 평가는 유추할 수 있을 것 같습니다.
따라서 Sad, Soso, Good으로 클러스터링 결과를 Labeling하였습니다.
해당 맥주의 특징을 결정짓는 요소들을 더 추가했다면 유의미한 결과가 나왔을지도 모르겠습니다. 😢
다음 포스팅에서는 직접 추천시스템을 구현해 보려고 합니다.
'데이터사이언스 > 추천시스템' 카테고리의 다른 글
맥주 추천시스템 구현 - 6. 웹 설정하기(Django) (2) | 2021.02.28 |
---|---|
맥주 추천시스템 구현 - 5. CF 기반 추천시스템 구현 (0) | 2021.02.27 |
맥주 추천시스템 구현 - 2. 데이터 전처리 (0) | 2021.02.03 |
맥주 추천시스템 구현 - 1. 데이터 크롤링 (12) | 2021.02.02 |
협업 필터링 - 최근접 이웃 협업 필터링이란? (CF) (2) | 2021.01.07 |