[Python] Plotly 상호작용: 버튼과 드롭다운 (updatemenus)
Plotly 인터랙티브 요소: 버튼과 드롭다운으로 대시보드 만들기
데이터 시각화의 꽃은 뭐니 뭐니 해도 사용자가 직접 데이터를 탐색할 수 있는 인터랙티브(Interactive) 요소라고 생각한다. 오늘은 Kaggle World Happiness Report 데이터를 활용해서, Plotly의 updatemenus 기능으로 버튼과 드롭다운을 구현하고 이를 세밀하게 튜닝하는 방법을 정리해 봤다.
1. 데이터 준비 및 설정
먼저 데이터를 불러오고 분석할 지표들을 정의한다.
import pandas as pd
import plotly.graph_objects as go
# 데이터 로드
df = pd.read_csv('world_happiness_report.csv')
# 1. 설정: 분석할 연도와 지표 정의
years = sorted(df['Year'].unique(), reverse=True)[:5] # 최근 5개년
metrics = {
'Happiness_Score': '행복 점수',
'Healthy_Life_Expectancy': '기대 수명',
'Social_Support': '사회적 지지'
}
metric_keys = list(metrics.keys())
2. 초기 그래프 생성
드롭다운을 만들기 전에, 가장 기본이 되는 첫 화면 그래프를 그려야 한다. 초기 연도와 초기 지표를 선택해서 산점도(Scatter Plot)를 그린다.
initial_year = years[0]
initial_metric = metric_keys[0]
curr_df = df[df['Year'] == initial_year]
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=curr_df['GDP_per_Capita'],
y=curr_df[initial_metric],
mode='markers',
text=curr_df['Country'],
marker=dict(
size=14,
color=curr_df[initial_metric],
colorscale='Electric',
showscale=True,
line=dict(width=1, color='White')
),
name=metrics[initial_metric]
)
)
3. 드롭다운(Dropdown) 구현: 연도 선택
updatemenus의 핵심은 method="update"다. 버튼을 클릭했을 때 데이터(x, y, text)를 새 데이터로 갈아끼우는 방식이다.
year_options = []
for year in years:
year_df = df[df['Year'] == year]
year_options.append(
dict(
method="update",
label=f"{year}년", # 라벨에 이모지 추가로 직관성 UP
args=[{
"x": [year_df['GDP_per_Capita']],
"y": [year_df[initial_metric]],
"text": [year_df['Country']]
}]
)
)
4. 버튼(Button) 구현: 지표 전환
이번엔 탭(Tab) 메뉴처럼 생긴 버튼을 만들어보자. 여기서는 단순히 데이터만 바꾸는 게 아니라, 축 제목과 차트 제목까지 동적으로 변경해야 한다. args의 두 번째 인자로 레이아웃 업데이트 정보를 넘겨주면 된다.
metric_buttons = []
for key, name in metrics.items():
metric_buttons.append(
dict(
method="update",
label=name,
args=[
{"y": [curr_df[key]], "marker.color": [curr_df[key]]}, # 데이터 변경
{"yaxis": {"title": name}, "title": f"<b>GDP 대비 {name} 상관관계</b>"} # 레이아웃 변경
]
)
)
5. 레이아웃 튜닝 (UI/UX 최적화)
이제 만든 메뉴들을 적절한 위치에 배치해야 한다.
fig.update_layout(
template="plotly_dark",
title=dict(text=f"<b>GDP 대비 {metrics[initial_metric]} 상관관계</b>", x=0.5, font=dict(size=20)),
xaxis_title="1인당 GDP (Purchasing Power)",
yaxis_title=metrics[initial_metric],
margin=dict(t=120), # 상단 여백 확보 (메뉴 공간)
updatemenus=[
# 1. 드롭다운 배치 (상단 왼쪽)
dict(
type="dropdown",
buttons=year_options,
direction="down",
showactive=True,
x=0.0, xanchor="left", y=1.2, yanchor="top"
),
# 2. 버튼 배치 (상단 오른쪽)
dict(
type="buttons",
buttons=metric_buttons,
direction="right",
x=1.0, xanchor="right", y=1.2, yanchor="top",
bgcolor="rgba(255, 255, 255, 0.1)", # 투명도 있는 배경
font=dict(color="white")
),
]
)
fig.show()
margin: 메뉴가 차트 제목을 가리지 않도록 상단 여백(t=120)을 넉넉히 준다.xanchor,yanchor: 드롭다운은 왼쪽 끝, 버튼은 오른쪽 끝에 배치하여 균형을 맞췄다.
6. 정리
Plotly의 updatemenus는 자바스크립트를 몰라도 파이썬만으로 훌륭한 인터랙티브 대시보드를 만들 수 있게 해준다.
| 기능 | 속성/값 | 설명 |
|---|---|---|
| 메뉴 타입 | type="dropdown" / "buttons" |
드롭다운 메뉴 또는 버튼 그룹 선택 |
| 동작 방식 | method="update" |
데이터와 레이아웃을 동시에 변경 |
| 데이터 변경 | args=[{data_dict}, ...] |
첫 번째 인자로 트레이스 데이터 변경 (x, y, marker.color 등) |
| 레이아웃 변경 | args=[..., {layout_dict}] |
두 번째 인자로 레이아웃 속성 변경 (title, yaxis 등) |
| 배치 | x, y, xanchor, yanchor |
메뉴의 위치 지정 (0~1 좌표계) |
단순히 정적인 그래프를 보여주는 것보다, 사용자가 직접 연도를 바꾸고 지표를 바꿔가며 데이터를 탐색하게 하면 분석의 깊이가 달라진다. 다음에는 슬라이더(Slider)를 연동해서 시계열 변화를 애니메이션으로 보여주는 것도 시도해봐야겠다.
Reference
- Dataset: Kaggle World Happiness Report
댓글남기기