Ver3.5 데이터 시각화의 끝판왕: Plotly & Seaborn으로 만드는 인터랙티브 차트 완전 정복

데이터 시각화의 끝판왕: Plotly & Seaborn으로 만드는 인터랙티브 차트 완전 정복
정적인 그래프는 이제 그만 🚀 | 데이터를 살아 숨쉬게 만드는 파이썬 시각화 가이드
야 솔직히 말해서... 데이터 분석하고 나서 그냥 숫자만 쭉 나열하면 아무도 안 봄 ㅋㅋㅋ 진짜로. 아무리 인사이트가 쩔어도 "그래서 이게 뭔데?" 소리 듣기 딱 좋음. 그래서 데이터 시각화가 존재하는 거고, 그 중에서도 Plotly랑 Seaborn은 파이썬 생태계에서 진짜 투탑이라고 할 수 있음.
이 글에서는 두 라이브러리의 특성부터 실전 코드까지 싹 다 정리해줄 거니까 끝까지 집중해줘! 데이터 시각화 처음 접하는 사람도, 이미 좀 써봤는데 더 깊이 파고 싶은 사람도 다 커버할 수 있게 구성했음 😎
일단 설치부터 해야지 뭘 하든 ㅋㅋ 파이썬 환경에서 pip 명령어로 간단하게 설치 가능함.
# Plotly 설치
pip install plotly
# Seaborn 설치 (Matplotlib도 같이 설치됨)
pip install seaborn
# 주피터 노트북에서 Plotly 인터랙션 활성화
pip install notebook ipywidgets
# 데이터 분석 기본 패키지
pip install pandas numpy
설치 완료했으면 이제 기본 임포트 구조를 알아두자. 매번 쓰는 거니까 외워두면 편함.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
plotly.express는 빠르고 간단한 차트용, plotly.graph_objects는 세밀한 커스터마이징용이라고 생각하면 됨. 이 두 개의 차이를 이해하는 게 Plotly 마스터의 첫걸음임 😤
Plotly Express(px)는 진짜 말도 안 되게 간단함. 코드 몇 줄로 인터랙티브 차트가 뚝딱 나옴. 처음 보면 "이게 맞아?" 싶을 정도 ㅋㅋㅋ
import plotly.express as px
import pandas as pd
import numpy as np
# 샘플 데이터 생성
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=100)
df = pd.DataFrame({
'날짜': dates,
'매출': np.cumsum(np.random.randn(100) * 100 + 50),
'비용': np.cumsum(np.random.randn(100) * 80 + 30)
})
# 라인 차트 생성
fig = px.line(
df,
x='날짜',
y=['매출', '비용'],
title='월별 매출 vs 비용 추이',
labels={'value': '금액(만원)', 'variable': '항목'},
color_discrete_map={'매출': '#5b9bd5', '비용': '#e8a96a'}
)
fig.update_layout(
plot_bgcolor='#f8f9fa',
paper_bgcolor='white',
font=dict(family='Malgun Gothic', size=13),
hovermode='x unified' # 호버 시 같은 x축 값 한번에 표시
)
fig.show()
산점도는 두 변수 간의 관계를 볼 때 쓰는 건데, Plotly로 만들면 각 점에 마우스 올렸을 때 해당 데이터 정보가 다 뜸. 진짜 개꿀 기능임.
# 내장 데이터셋 활용 (gapminder)
df_gap = px.data.gapminder().query("year == 2007")
fig = px.scatter(
df_gap,
x='gdpPercap',
y='lifeExp',
size='pop', # 버블 크기 = 인구수
color='continent', # 색상 = 대륙
hover_name='country', # 호버 시 국가명 표시
log_x=True, # x축 로그 스케일
size_max=60,
title='2007년 국가별 GDP vs 기대수명 (버블 크기 = 인구)',
labels={
'gdpPercap': '1인당 GDP (달러)',
'lifeExp': '기대수명 (세)',
'continent': '대륙'
}
)
fig.update_layout(
plot_bgcolor='#f8f9fa',
paper_bgcolor='white'
)
fig.show()
이 코드 한 번 실행해봐. 각 나라 버블에 마우스 올리면 국가명, GDP, 기대수명, 인구 다 뜨고 대륙별로 색이 구분됨. 이걸 정적 이미지로 만들면 절대 이 정보량을 담을 수 없음 ㅋㅋ
Plotly의 진짜 킬러 기능 중 하나가 애니메이션임. 시간에 따른 변화를 슬라이더로 조작하면서 볼 수 있음.
# 연도별 대륙 GDP 변화 애니메이션
df_anim = px.data.gapminder()
fig = px.bar(
df_anim,
x='continent',
y='gdpPercap',
color='continent',
animation_frame='year', # 연도별 애니메이션
animation_group='country',
range_y=[0, 50000],
title='연도별 대륙별 평균 GDP 변화',
labels={
'gdpPercap': '1인당 GDP',
'continent': '대륙'
}
)
fig.update_layout(
showlegend=False,
plot_bgcolor='#f8f9fa'
)
fig.show()
animation_frame 파라미터 하나로 슬라이더가 자동 생성됨. 재생 버튼 누르면 연도별로 자동 전환되는 애니메이션이 실행됨. 발표 자료로 쓰면 진짜 임팩트 쩔음 🔥px가 빠른 프로토타이핑용이라면, go(graph_objects)는 세밀한 제어가 필요할 때 씀. 좀 더 코드가 길어지지만 그만큼 자유도가 높음.
import plotly.graph_objects as go
labels = ['파이썬', '자바스크립트', '자바', 'C++', '기타']
values = [35, 28, 18, 12, 7]
colors = ['#5b9bd5', '#7bbf6a', '#e8a96a', '#d57b7b', '#a89bd5']
fig = go.Figure(data=[go.Pie(
labels=labels,
values=values,
hole=0.45, # 도넛 구멍 크기 (0~1)
marker=dict(
colors=colors,
line=dict(color='white', width=2)
),
textinfo='label+percent',
hovertemplate='<b>%{label}</b><br>비율: %{percent}<br>응답수: %{value}명<extra></extra>'
)])
fig.update_layout(
title=dict(
text='2024 개발자 선호 언어 조사',
font=dict(size=18, color='#1e3a5f')
),
showlegend=True,
legend=dict(orientation='h', yanchor='bottom', y=-0.2),
paper_bgcolor='white'
)
fig.show()
대시보드처럼 여러 차트를 한 화면에 배치하고 싶을 때 make_subplots를 씀.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
# 2행 2열 서브플롯 생성
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('라인 차트', '막대 차트', '산점도', '히스토그램'),
vertical_spacing=0.12,
horizontal_spacing=0.08
)
x = np.linspace(0, 10, 50)
# 1행 1열: 라인 차트
fig.add_trace(
go.Scatter(x=x, y=np.sin(x), name='sin(x)',
line=dict(color='#5b9bd5', width=2)),
row=1, col=1
)
# 1행 2열: 막대 차트
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 12, 67, 34]
fig.add_trace(
go.Bar(x=categories, y=values, name='카테고리별',
marker_color='#7bbf6a'),
row=1, col=2
)
# 2행 1열: 산점도
fig.add_trace(
go.Scatter(
x=np.random.randn(100),
y=np.random.randn(100),
mode='markers',
name='랜덤 데이터',
marker=dict(color='#e8a96a', size=6, opacity=0.7)
),
row=2, col=1
)
# 2행 2열: 히스토그램
fig.add_trace(
go.Histogram(
x=np.random.normal(0, 1, 500),
name='정규분포',
marker_color='#d57b7b',
opacity=0.75
),
row=2, col=2
)
fig.update_layout(
height=600,
title_text='대시보드 스타일 서브플롯',
showlegend=False,
plot_bgcolor='#f8f9fa',
paper_bgcolor='white'
)
fig.show()
make_subplots로 생성한 레이아웃에 add_trace()로 차트를 하나씩 추가하는 방식. row와 col로 위치 지정함.Seaborn은 Matplotlib 위에 올라탄 고수준 라이브러리인데, 통계적 시각화에 특화되어 있음. 특히 EDA(탐색적 데이터 분석) 단계에서 진짜 빛을 발함 ✨
변수들 간의 상관관계를 한눈에 보여주는 히트맵은 데이터 분석에서 거의 필수로 씀.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 한글 폰트 설정 (Windows)
plt.rcParams['font.family'] = 'Malgun Gothic'
plt.rcParams['axes.unicode_minus'] = False
# 샘플 데이터 생성
np.random.seed(42)
df = pd.DataFrame({
'매출': np.random.randn(100) * 100 + 500,
'광고비': np.random.randn(100) * 50 + 200,
'방문자수': np.random.randn(100) * 1000 + 5000,
'전환율': np.random.randn(100) * 0.05 + 0.15,
'고객만족도': np.random.randn(100) * 0.5 + 4.0
})
# 상관관계 행렬 계산
corr_matrix = df.corr()
# 히트맵 그리기
fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(
corr_matrix,
annot=True, # 셀 안에 수치 표시
fmt='.2f', # 소수점 2자리
cmap='RdYlBu_r', # 색상 팔레트
center=0, # 0을 중심으로 색상 분기
square=True, # 정사각형 셀
linewidths=0.5, # 셀 경계선
cbar_kws={'shrink': 0.8},
ax=ax
)
ax.set_title('변수 간 상관관계 히트맵', fontsize=15, fontweight='bold', pad=15)
plt.tight_layout()
plt.savefig('heatmap.png', dpi=150, bbox_inches='tight')
plt.show()
박스플롯보다 훨씬 더 많은 정보를 담을 수 있는 바이올린 플롯. 분포의 형태까지 보여줌.
# 내장 데이터셋 활용
tips = sns.load_dataset('tips')
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 왼쪽: 바이올린 플롯
sns.violinplot(
data=tips,
x='day',
y='total_bill',
hue='sex',
split=True, # 성별로 반반 나눠서 표시
palette={'Male': '#5b9bd5', 'Female': '#d57b7b'},
inner='quart', # 내부에 사분위수 표시
ax=axes[0]
)
axes[0].set_title('요일별 계산서 금액 분포 (성별)', fontsize=13, fontweight='bold')
axes[0].set_xlabel('요일')
axes[0].set_ylabel('계산서 금액 ($)')
# 오른쪽: 박스플롯 + 스트립플롯 조합
sns.boxplot(
data=tips,
x='day',
y='tip',
palette='pastel',
ax=axes[1]
)
sns.stripplot(
data=tips,
x='day',
y='tip',
color='#2d2d2d',
alpha=0.4,
size=3,
ax=axes[1]
)
axes[1].set_title('요일별 팁 분포', fontsize=13, fontweight='bold')
axes[1].set_xlabel('요일')
axes[1].set_ylabel('팁 ($)')
plt.tight_layout()
plt.show()
데이터셋의 모든 수치형 변수 쌍의 관계를 한 번에 보여주는 페어플롯. EDA할 때 진짜 자주 씀.
iris = sns.load_dataset('iris')
# 페어플롯 생성
g = sns.pairplot(
iris,
hue='species', # 종별 색상 구분
palette={'setosa': '#5b9bd5',
'versicolor': '#7bbf6a',
'virginica': '#e8a96a'},
diag_kind='kde', # 대각선: KDE 분포
plot_kws={'alpha': 0.6, 's': 40},
diag_kws={'alpha': 0.7}
)
g.fig.suptitle('붓꽃 데이터셋 페어플롯', y=1.02, fontsize=15, fontweight='bold')
plt.show()
실제 데이터 분석 프로젝트에서는 두 라이브러리를 상황에 맞게 섞어 쓰는 게 베스트임. 탐색은 Seaborn으로 빠르게, 최종 결과물은 Plotly로 인터랙티브하게 만드는 패턴이 많이 쓰임.
import plotly.express as px
import plotly.graph_objects as go
# Seaborn 팔레트를 Plotly에서 활용
import seaborn as sns
palette = sns.color_palette("husl", 8)
# RGB 튜플을 hex 코드로 변환
hex_colors = ['#{:02x}{:02x}{:02x}'.format(
int(r*255), int(g*255), int(b*255)
) for r, g, b in palette]
# Plotly에 Seaborn 색상 적용
df = px.data.gapminder().query("year == 2007")
fig = px.scatter(
df,
x='gdpPercap',
y='lifeExp',
color='continent',
size='pop',
hover_name='country',
log_x=True,
color_discrete_sequence=hex_colors,
title='Seaborn 팔레트 + Plotly 인터랙션의 조합'
)
fig.show()
Seaborn의 FacetGrid처럼 조건별로 나눠서 보는 걸 Plotly에서도 구현할 수 있음.
import plotly.express as px
tips = px.data.tips()
# facet_col로 요일별 분리, facet_row로 성별 분리
fig = px.histogram(
tips,
x='total_bill',
color='smoker',
facet_col='day',
facet_row='sex',
nbins=20,
title='요일 × 성별 × 흡연여부별 계산서 금액 분포',
color_discrete_map={'Yes': '#e8a96a', 'No': '#5b9bd5'},
labels={
'total_bill': '계산서 금액',
'smoker': '흡연 여부',
'day': '요일',
'sex': '성별'
}
)
fig.update_layout(
plot_bgcolor='#f8f9fa',
paper_bgcolor='white',
height=500
)
fig.show()
facet_col과 facet_row를 조합하면 Seaborn의 FacetGrid와 동일한 효과를 인터랙티브하게 구현 가능. 각 서브플롯이 독립적으로 줌/호버 기능을 지원함!Plotly의 숨겨진 강점 중 하나가 바로 지도 시각화임. 지리 데이터를 다룰 때 진짜 강력함 ㅋㅋ
import plotly.express as px
# 국가별 데이터 시각화 (Choropleth Map)
df = px.data.gapminder().query("year == 2007")
fig = px.choropleth(
df,
locations='iso_alpha', # ISO 국가 코드
color='lifeExp', # 색상으로 표현할 값
hover_name='country',
color_continuous_scale='RdYlGn', # 빨강→노랑→초록
range_color=[40, 85],
title='2007년 국가별 기대수명 세계 지도',
labels={'lifeExp': '기대수명(세)'}
)
fig.update_layout(
geo=dict(
showframe=False,
showcoastlines=True,
projection_type='natural earth'
),
coloraxis_colorbar=dict(
title='기대수명',
ticksuffix='세'
)
)
fig.show()
# 버블 맵 (특정 위치에 버블 표시)
import plotly.express as px
import pandas as pd
# 한국 주요 도시 데이터
cities = pd.DataFrame({
'도시': ['서울', '부산', '인천', '대구', '대전', '광주'],
'위도': [37.5665, 35.1796, 37.4563, 35.8714, 36.3504, 35.1595],
'경도': [126.9780, 129.0756, 126.7052, 128.6014, 127.3845, 126.8526],
'인구': [9720846, 3404423, 2947217, 2427954, 1471040, 1441970],
'지역': ['수도권', '영남', '수도권', '영남', '충청', '호남']
})
fig = px.scatter_mapbox(
cities,
lat='위도',
lon='경도',
size='인구',
color='지역',
hover_name='도시',
hover_data={'인구': ':,', '위도': False, '경도': False},
size_max=50,
zoom=6,
center={'lat': 36.5, 'lon': 127.8},
mapbox_style='carto-positron',
title='한국 주요 도시 인구 분포'
)
fig.update_layout(margin={'r': 0, 't': 40, 'l': 0, 'b': 0})
fig.show()
scatter_mapbox를 쓰려면 Mapbox 토큰이 필요하거나 mapbox_style='open-street-map'처럼 오픈소스 스타일을 쓰면 됨. carto-positron은 토큰 없이도 사용 가능한 깔끔한 스타일!Plotly의 진짜 고급 기능들을 알아보자. 이걸 쓸 줄 알면 진짜 프로처럼 보임 ㅋㅋㅋ
import plotly.graph_objects as go
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'제품명': [f'제품{i}' for i in range(1, 21)],
'매출': np.random.randint(100, 1000, 20),
'이익률': np.random.uniform(0.05, 0.35, 20),
'카테고리': np.random.choice(['전자', '의류', '식품', '가구'], 20)
})
# 카테고리별 색상 매핑
color_map = {'전자': '#5b9bd5', '의류': '#d57b7b',
'식품': '#7bbf6a', '가구': '#e8a96a'}
fig = go.Figure()
for category in df['카테고리'].unique():
mask = df['카테고리'] == category
subset = df[mask]
fig.add_trace(go.Scatter(
x=subset['매출'],
y=subset['이익률'],
mode='markers',
name=category,
marker=dict(
size=12,
color=color_map[category],
opacity=0.8,
line=dict(width=1, color='white')
),
# 커스텀 호버 템플릿
hovertemplate=(
'<b>%{customdata[0]}</b><br>'
'카테고리: ' + category + '<br>'
'매출: %{x:,}만원<br>'
'이익률: %{y:.1%}<br>'
'<extra></extra>' # 트레이스 이름 숨기기
),
customdata=subset[['제품명']].values
))
fig.update_layout(
title='제품별 매출 vs 이익률',
xaxis_title='매출 (만원)',
yaxis_title='이익률',
yaxis_tickformat='.0%',
plot_bgcolor='#f8f9fa',
paper_bgcolor='white',
hovermode='closest'
)
fig.show()
import plotly.graph_objects as go
import numpy as np
x = np.linspace(0, 4*np.pi, 200)
fig = go.Figure()
# 여러 함수 데이터 추가 (처음엔 sin만 보이게)
fig.add_trace(go.Scatter(
x=x, y=np.sin(x), name='sin(x)',
line=dict(color='#5b9bd5', width=2), visible=True
))
fig.add_trace(go.Scatter(
x=x, y=np.cos(x), name='cos(x)',
line=dict(color='#7bbf6a', width=2), visible=False
))
fig.add_trace(go.Scatter(
x=x, y=np.tan(x), name='tan(x)',
line=dict(color='#e8a96a', width=2), visible=False
))
# 드롭다운 메뉴 설정
fig.update_layout(
title='삼각함수 선택 차트',
updatemenus=[dict(
type='dropdown',
direction='down',
x=0.1, y=1.15,
showactive=True,
buttons=[
dict(label='sin(x)',
method='update',
args=[{'visible': [True, False, False]},
{'title': 'y = sin(x)'}]),
dict(label='cos(x)',
method='update',
args=[{'visible': [False, True, False]},
{'title': 'y = cos(x)'}]),
dict(label='tan(x)',
method='update',
args=[{'visible': [False, False, True]},
{'title': 'y = tan(x)'}]),
dict(label='전체 보기',
method='update',
args=[{'visible': [True, True, True]},
{'title': '삼각함수 비교'}])
]
)],
plot_bgcolor='#f8f9fa',
paper_bgcolor='white'
)
fig.show()
만든 차트를 어떻게 저장하고 공유하느냐도 중요함. 각 라이브러리별로 방법이 다름.
| 방법 | 라이브러리 | 코드 | 특징 |
|---|---|---|---|
| HTML 저장 | Plotly | fig.write_html('chart.html') |
인터랙션 유지, 공유 쉬움 |
| PNG/SVG 저장 | Plotly | fig.write_image('chart.png') |
kaleido 패키지 필요 |
| PNG 저장 | Seaborn | plt.savefig('chart.png', dpi=150) |
고해상도 정적 이미지 |
| JSON 저장 | Plotly | fig.write_json('chart.json') |
나중에 재로드 가능 |
| 임베드 코드 | Plotly | fig.to_html(include_plotlyjs='cdn') |
웹페이지에 삽입 가능 |
# Plotly HTML 저장 (인터랙션 완전 유지)
fig.write_html(
'interactive_chart.html',
include_plotlyjs='cdn', # CDN에서 plotly.js 로드 (파일 크기 절약)
full_html=True
)
# Plotly 이미지 저장 (kaleido 필요: pip install kaleido)
fig.write_image('chart.png', width=1200, height=800, scale=2)
fig.write_image('chart.svg') # 벡터 이미지
# Seaborn/Matplotlib 저장
plt.savefig(
'seaborn_chart.png',
dpi=300, # 해상도 (논문용은 300 이상)
bbox_inches='tight', # 여백 자동 조정
facecolor='white' # 배경색
)
지금까지 배운 걸 종합해서 실제로 쓸 수 있는 대시보드 스타일 시각화를 만들어보자. 이 정도 수준이면 포트폴리오에 올려도 손색없음 😎
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
# 샘플 판매 데이터 생성
np.random.seed(42)
months = ['1월', '2월', '3월', '4월', '5월', '6월',
'7월', '8월', '9월', '10월', '11월', '12월']
categories = ['전자제품', '의류', '식품', '가구']
# 월별 카테고리 매출 데이터
sales_data = {cat: np.random.randint(200, 800, 12) for cat in categories}
df_sales = pd.DataFrame(sales_data, index=months)
# 전체 월별 매출
total_sales = df_sales.sum(axis=1)
# 대시보드 레이아웃 생성
fig = make_subplots(
rows=2, cols=2,
subplot_titles=(
'월별 총 매출 추이',
'카테고리별 매출 비중',
'카테고리별 월별 매출',
'월별 성장률'
),
specs=[
[{'type': 'scatter'}, {'type': 'pie'}],
[{'type': 'bar'}, {'type': 'bar'}]
],
vertical_spacing=0.14,
horizontal_spacing=0.1
)
# 1. 월별 총 매출 라인 차트
fig.add_trace(
go.Scatter(
x=months,
y=total_sales,
mode='lines+markers',
name='총 매출',
line=dict(color='#5b9bd5', width=3),
marker=dict(size=8, color='#5b9bd5'),
fill='tozeroy',
fillcolor='rgba(91, 155, 213, 0.15)',
hovertemplate='%{x}: %{y:,}만원<extra></extra>'
),
row=1, col=1
)
# 2. 카테고리별 파이 차트
category_totals = df_sales.sum()
fig.add_trace(
go.Pie(
labels=category_totals.index,
values=category_totals.values,
hole=0.4,
marker=dict(colors=['#5b9bd5', '#d57b7b', '#7bbf6a', '#e8a96a']),
hovertemplate='%{label}: %{value:,}만원 (%{percent})<extra></extra>'
),
row=1, col=2
)
# 3. 카테고리별 누적 막대 차트
colors = ['#5b9bd5', '#d57b7b', '#7bbf6a', '#e8a96a']
for i, cat in enumerate(categories):
fig.add_trace(
go.Bar(
x=months,
y=df_sales[cat],
name=cat,
marker_color=colors[i],
hovertemplate=f'{cat}: %{{y:,}}만원<extra></extra>'
),
row=2, col=1
)
# 4. 월별 성장률
growth_rate = total_sales.pct_change() * 100
growth_colors = ['#7bbf6a' if v >= 0 else '#d57b7b'
for v in growth_rate.fillna(0)]
fig.add_trace(
go.Bar(
x=months[1:],
y=growth_rate.dropna(),
name='성장률',
marker_color=growth_colors[1:],
hovertemplate='%{x}: %{y:.1f}%<extra></extra>'
),
row=2, col=2
)
# 레이아웃 설정
fig.update_layout(
title=dict(
text='📊 2024년 연간 판매 대시보드',
font=dict(size=20, color='#1e3a5f'),
x=0.5
),
height=700,
plot_bgcolor='#f8f9fa',
paper_bgcolor='white',
barmode='stack',
showlegend=True,
legend=dict(
orientation='h',
yanchor='bottom',
y=-0.15,
xanchor='center',
x=0.5
),
font=dict(size=12)
)
# y축 포맷 설정
fig.update_yaxes(ticksuffix='만', row=1, col=1)
fig.update_yaxes(ticksuffix='%', row=2, col=2)
fig.show()
# HTML로 저장
fig.write_html('sales_dashboard.html', include_plotlyjs='cdn')
기본 스타일에서 벗어나 나만의 스타일을 만드는 방법도 알아두면 좋음.
import plotly.io as pio
import plotly.express as px
# 내장 테마 목록
# 'plotly', 'plotly_white', 'plotly_dark',
# 'ggplot2', 'seaborn', 'simple_white', 'none'
# 전역 테마 설정
pio.templates.default = 'plotly_white'
# 커스텀 테마 생성
import plotly.graph_objects as go
custom_template = go.layout.Template()
custom_template.layout = go.Layout(
font=dict(family='Malgun Gothic', size=13, color='#2d2d2d'),
plot_bgcolor='#f8f9fa',
paper_bgcolor='white',
colorway=['#5b9bd5', '#7bbf6a', '#e8a96a', '#d57b7b', '#a89bd5'],
title=dict(font=dict(size=18, color='#1e3a5f')),
xaxis=dict(gridcolor='#e0e8f0', linecolor='#c0d0e0'),
yaxis=dict(gridcolor='#e0e8f0', linecolor='#c0d0e0')
)
# 커스텀 테마 등록 및 적용
pio.templates['my_theme'] = custom_template
pio.templates.default = 'my_theme'
# 이제 모든 차트에 자동 적용됨
fig = px.line(px.data.gapminder().query("country=='Korea, Rep.'"),
x='year', y='gdpPercap', title='한국 GDP 추이')
fig.show()
import seaborn as sns
import matplotlib.pyplot as plt
# Seaborn 스타일 설정
# 스타일: 'darkgrid', 'whitegrid', 'dark', 'white', 'ticks'
# 컨텍스트: 'paper', 'notebook', 'talk', 'poster'
# 팔레트: 'deep', 'muted', 'bright', 'pastel', 'dark', 'colorblind'
sns.set_theme(
style='whitegrid',
context='notebook',
palette='muted',
font='Malgun Gothic',
font_scale=1.1,
rc={
'axes.spines.top': False,
'axes.spines.right': False,
'figure.facecolor': 'white',
'axes.facecolor': '#f8f9fa'
}
)
# 커스텀 팔레트 생성
custom_palette = ['#5b9bd5', '#7bbf6a', '#e8a96a', '#d57b7b', '#a89bd5']
sns.set_palette(custom_palette)
# 이제 모든 Seaborn 차트에 자동 적용
tips = sns.load_dataset('tips')
fig, ax = plt.subplots(figsize=(8, 5))
sns.boxplot(data=tips, x='day', y='total_bill', ax=ax)
ax.set_title('요일별 계산서 금액')
plt.show()
데이터가 많아지면 차트 렌더링이 느려질 수 있음. 이럴 때 쓸 수 있는 최적화 기법들을 알아두자.
대용량 데이터(10만 개 이상 포인트)에서는
go.Scattergl을 사용하면 WebGL 기반으로 렌더링되어 훨씬 빠름.go.Scatter → go.Scattergl 로 교체만 하면 됨!2. 데이터 샘플링
시각화 목적에 따라 전체 데이터가 필요 없을 수 있음. 트렌드 파악이 목적이라면 적절히 샘플링해서 사용.
3. 범주형 데이터 최적화
범주형 컬럼은
pd.Categorical로 변환하면 메모리와 처리 속도 모두 개선됨.
# WebGL 렌더러로 대용량 산점도
import plotly.graph_objects as go
import numpy as np
# 100만 개 데이터 포인트
n = 1_000_000
x = np.random.randn(n)
y = np.random.randn(n)
# go.Scatter 대신 go.Scattergl 사용
fig = go.Figure(go.Scattergl(
x=x,
y=y,
mode='markers',
marker=dict(
size=2,
color=np.random.randn(n),
colorscale='Viridis',
opacity=0.3
)
))
fig.update_layout(title=f'{n:,}개 데이터 포인트 WebGL 렌더링')
fig.show()
go.Scattergl은 일부 기능(예: 특정 마커 심볼)이 지원되지 않을 수 있음. 기능 제한 확인 후 사용할 것!데이터 시각화 스킬은 요즘 진짜 핫한 역량임. 재능넷에서도 데이터 분석, 파이썬 개발, 대시보드 제작 관련 의뢰가 꾸준히 올라오는 걸 볼 수 있음. Plotly로 인터랙티브 대시보드 만들어주는 서비스나, Seaborn으로 데이터 분석 보고서 시각화해주는 서비스 등 다양한 형태로 재능을 공유할 수 있음 💪
특히 비즈니스 데이터 분석 결과를 시각화해서 보여주는 능력은 클라이언트 입장에서 진짜 가치 있는 스킬임. 숫자만 나열한 엑셀 파일보다 인터랙티브 대시보드 하나가 훨씬 더 임팩트 있으니까!
자 이제 Plotly랑 Seaborn에 대해 꽤 깊이 파봤음 ㅋㅋ 핵심만 다시 정리하면:
- 발표 자료나 대시보드를 만들 때
- 사용자가 직접 데이터를 탐색해야 할 때
- 애니메이션이나 지도 시각화가 필요할 때
- HTML 파일로 공유해야 할 때
- 논문이나 보고서용 고품질 정적 이미지가 필요할 때
- 통계적 분포나 관계를 시각화할 때
- Matplotlib과 연동해서 세밀한 제어가 필요할 때
두 라이브러리 모두 파이썬 데이터 사이언스 생태계에서 없어서는 안 될 존재임. 어느 하나만 고집하지 말고 상황에 맞게 유연하게 활용하는 게 진짜 데이터 시각화 고수의 자세임 💪
그리고 재능넷에서 파이썬 데이터 시각화 관련 프로젝트를 찾거나 본인의 스킬을 공유하고 싶다면 적극적으로 활용해봐. 이 분야 수요가 진짜 많거든 😎
오늘 배운 코드들 직접 실행해보면서 손에 익히는 게 제일 중요함. 백 번 읽는 것보다 한 번 직접 돌려보는 게 훨씬 효과적이니까! 화이팅 🔥
댓글 작성
이 글에 대한 여러분의 생각을 들려주세요
로그인이 필요합니다
댓글을 작성하려면 먼저 로그인해주세요.
댓글 0
지식인의 숲 - 지적 재산권 보호 고지
지적 재산권 보호 고지
- 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
- AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
- 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
- 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
- AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.
아직 댓글이 없습니다.