변수 간 관계를 시각화하는 8가지 차트 유형

1. 산점도

산점도는 두 개의 연속형 변수 간 관계를 점의 위치로 표현하는 기본적인 시각화 기법입니다. 점들의 분포 패턴을 통해 선형 관계, 비선형 관계, 또는 무관계 여부를 판단할 수 있으며, 밀도와 추세선으로 상관성의 강도를 파악합니다.

활용 분야: 탐색적 데이터 분석, 변수 간 가설 검증, 이상치 탐지

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic", "sans-serif"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(2024)
horizontal = np.random.standard_normal(150)
vertical = 1.8 * horizontal + np.random.standard_normal(150) * 0.6

plt.figure(figsize=(9, 7))
plt.scatter(horizontal, vertical, c='coral', alpha=0.65, edgecolors='white', s=45)
plt.title('변수 간 선형 관계 시각화')
plt.xlabel('독립 변수')
plt.ylabel('종속 변수')
plt.axhline(y=0, color='gray', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='gray', linestyle='-', alpha=0.3)
plt.show()

pearson_r = np.corrcoef(horizontal, vertical)[0, 1]
print(f'상관계수: {pearson_r:.4f}')

2. 버블 차트

버블 차트는 산점도에 원의 크기와 색상을 추가하여 3~4차원 데이터를 동시에 표현합니다. x축과 y축에 두 변수를 배치하고, 원의 지름으로 세 번째 변수, 색조로 네 번째 변수를 나타냅니다.

활용 분야: 시장 세분화 분석, 국가/도시 지표 비교, 포트폴리오 매핑

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(2024)
nations = 25
country_list = ['대한민국', '일본', '독일', '프랑스', '영국', 
                '캐나다', '호주', '스웨덴', '네덜란드', '스위스',
                '벨기에', '오스트리아', '노르웨이', '덴마크', '핀란드',
                '이탈리아', '스페인', '포르투갈', '그리스', '아일랜드',
                '체코', '폴란드', '헝가리', '슬로바키아', '슬로베니아']

gdp = np.random.uniform(25000, 75000, nations)
lifespan = 50 + 0.0004 * gdp + np.random.normal(0, 4, nations)
pop = np.random.lognormal(15, 1.5, nations)
continent = np.random.choice(['동아시아', '서유럽', '북유럽', '중남유럽', '중동부유럽'], nations)

dataset = pd.DataFrame({
    '국가': country_list,
    'GDP': gdp,
    '수명': lifespan,
    '인구': pop,
    '대륙': continent
})

visual = px.scatter(
    dataset, x="GDP", y="수명", size="인구", color="대륙",
    hover_name="국가", log_x=True, size_max=55,
    title="국가별 발전 지표 버블 차트",
    color_discrete_sequence=px.colors.qualitative.Set2
)

visual.update_layout(
    font=dict(family="Malgun Gothic", size=11),
    height=650, width=1100,
    legend=dict(orientation="h", yanchor="bottom", y=1.02)
)
visual.show()

3. 상관행렬 히트맵

상관행렬 트맵은 다변량 데이터셋에서 모든 변수 쌍 간의 상관계수를 색상 그라데이션으로 표현합니다. 색상의 채도와 방향(빨강/파랑)으로 상관 방향과 강도를 동시에 전달합니다.

활용 분야: 다중공선성 확인, 특성 선택, 변수 클러스터링

import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(2024)
raw_data = pd.DataFrame({
    '매출': np.random.lognormal(10, 0.5, 120),
    '광고비': np.random.lognormal(8, 0.8, 120),
    '직원수': np.random.poisson(50, 120),
    '만족도': np.random.beta(7, 2, 120) * 10
})
raw_data['이익'] = raw_data['매출'] * 0.15 + np.random.normal(0, 50000, 120)
raw_data['성장률'] = np.random.normal(0.08, 0.15, 120)

corr = raw_data.corr(method='pearson')

plt.figure(figsize=(10, 8))
mask = np.triu(np.ones_like(corr, dtype=bool), k=1)
sns.heatmap(corr, mask=mask, annot=True, cmap='RdBu_r', center=0,
            square=True, fmt='.2f', vmin=-1, vmax=1,
            cbar_kws={'shrink': 0.8, 'label': 'Pearson r'})
plt.title('기업 지표 상관관계 매트릭스')
plt.tight_layout()
plt.show()

4. 집약 히트맵

집약 히트맵은 행렬 형태의 수치 데이터를 색상 밀도로 변환하여 패턴과 이상값을 강조합니다. 계층적 군집화와 결합하면 유사한 행/열을 자동으로 그룹화할 수 있습니다.

활용 분야: 시계열 패턴 분석, 유전자 발현 프로파일, 웹사이트 클릭스팀

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(2024)
branches = [f'지점{i:02d}' for i in range(1, 16)]
quarters = [f'{q}분기' for q in range(1, 5)]

base = np.random.gamma(2, 100, (15, 4))
trend = np.linspace(0, 50, 4)
seasonal = np.array([30, -20, 10, -20])

revenue = base + trend + seasonal + np.random.normal(0, 15, (15, 4))
revenue = np.clip(revenue, 50, 400)

sales_df = pd.DataFrame(revenue, index=branches, columns=quarters)

plt.figure(figsize=(10, 12))
sns.clustermap(sales_df, cmap='YlOrRd', annot=True, fmt='.0f',
               linewidths=0.5, col_cluster=False, 
               dendrogram_ratio=0.15, cbar_pos=(0.02, 0.8, 0.03, 0.15))
plt.suptitle('지점별 분기 매출 집약 히트맵', y=0.95)
plt.show()

5. 커널 밀도 추정도

커널 밀도 추정도(KDE)는 산점도의 점을 부드러운 색상 영역으로 대체하여 데이터 밀도의 연속적인 분포를 보여줍니다. 대용량 데이터에서 중첩 문제를 해결하고 분포의 형태를 명확히 드러냅니다.

활용 분야: 금융 수익률 분포, 공간 데이터, 물리 실험 데이터

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(2024)
samples = 2000
center = [5, -3]
covariance = [[2.5, 1.8], [1.8, 2.5]]

u, v = np.random.multivariate_normal(center, covariance, samples).T
frame = pd.DataFrame({'축1': u, '축2': v})

fig, axes = plt.subplots(1, 2, figsize=(14, 6))

sns.kdeplot(data=frame, x='축1', y='축2', fill=True, 
            cmap='viridis', levels=20, thresh=0.05, ax=axes[0])
axes[0].set_title('채움 밀도 추정')

sns.kdeplot(data=frame, x='축1', y='축2', fill=False,
            cmap='plasma', levels=15, linewidths=1.5, ax=axes[1])
axes[1].set_title('등고선 밀도 추정')

plt.tight_layout()
plt.show()

6. 다중 밀도 분포도

다중 밀도 분포도는 서로 다른 모집단이나 클러스터의 밀도를 겹쳐 표현하여 복수의 분포 중심을 동시에 시각화합니다. 각 집단의 경계와 중첩 영역을 통해 분리 가능성을 평가합니다.

활용 분야: 고객 세분화, 질병 하위유형 분류, 금융 위험 국면 식별

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(2024)

cluster_a = np.random.multivariate_normal([4, 4], [[1.2, 0.3], [0.3, 1.2]], 600)
cluster_b = np.random.multivariate_normal([-3, 2], [[0.8, -0.4], [-0.4, 0.8]], 400)
cluster_c = np.random.multivariate_normal([0, -4], [[1.5, 0], [0, 0.6]], 500)

combined = np.vstack([cluster_a, cluster_b, cluster_c])
labels = np.repeat(['프리미엄', '일반', '신규'], [600, 400, 500])

multi_df = pd.DataFrame({
    '소득': combined[:, 0],
    '지출': combined[:, 1],
    '등급': labels
})

plt.figure(figsize=(11, 9))
sns.kdeplot(data=multi_df, x='소득', y='지출', hue='등급',
            fill=True, common_norm=False, alpha=0.5,
            palette={'프리미엄': '#E74C3C', '일반': '#3498DB', '신규': '#2ECC71'})
plt.title('고객 세그먼트별 소득-지출 밀도 분포')
plt.legend(title='고객 등급', loc='upper left')
plt.show()

7. 극좌표 다각형도

극좌표 다각형도(레이더 차트)는 중심에서 방사형으로 뻗은 축에 각 평가 항목을 배치하고, 데이터 포인트를 연결한 다각형으로 다차원 성능을 비교합니다. 균형 잡힌 프로필과 편중된 프로필의 시각적 차이가 두드러집니다.

활용 분야: 제품 스펙 비교, 인재 역량 평가, 경쟁사 포지셔닝

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["font.family"] = ["Malgun Gothic", "Nanum Gothic"]
plt.rcParams["axes.unicode_minus"] = False

attributes = ['성능', '가격', '디자인', '내구성', '에너지효율', 'AS']
n_attr = len(attributes)

model_x = [9, 4, 8, 7, 6, 5]
model_y = [6, 9, 5, 8, 9, 7]
model_z = [7, 6, 9, 6, 5, 8]

angles = np.linspace(0, 2*np.pi, n_attr, endpoint=False).tolist()
model_x += model_x[:1]
model_y += model_y[:1]
model_z += model_z[:1]
angles += angles[:1]

fig, ax = plt.subplots(figsize=(10, 10), subplot_kw=dict(projection='polar'))
ax.set_theta_offset(np.pi/2)
ax.set_theta_direction(-1)

ax.plot(angles, model_x, 'D-', linewidth=2.5, color='#FF6B6B', label='프리미엄')
ax.fill(angles, model_x, alpha=0.15, color='#FF6B6B')
ax.plot(angles, model_y, 's-', linewidth=2.5, color='#4ECDC4', label='가성비')
ax.fill(angles, model_y, alpha=0.15, color='#4ECDC4')
ax.plot(angles, model_z, '^-', linewidth=2.5, color='#45B7D1', label='디자인')
ax.fill(angles, model_z, alpha=0.15, color='#45B7D1')

ax.set_xticks(angles[:-1])
ax.set_xticklabels(attributes, fontsize=12)
ax.set_ylim(0, 10)
ax.set_yticks([2, 4, 6, 8, 10])
ax.set_yticklabels(['2', '4', '6', '8', '10'], color='gray', size=9)
ax.grid(color='gray', alpha=0.3)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))

plt.title('노트북 모델 다차원 비교', fontsize=14, pad=20)
plt.tight_layout()
plt.show()

8. 흐름 다이어그램

흐름 다이어그램(상키 다이어그램)은 노드와 연결선의 너비로 양적 흐름을 표현하며, 단계별 변환과 분기를 추적합니다. 에너지, 자금, 사용자 등의 경로와 손실/전환율을 직관적으로 보여줍니다.

활용 분야: 공급망 관리, 전환율 분석, 탄소 발자국 추적

import plotly.graph_objects as go

sources = [0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
targets = [1, 2, 3, 4, 5, 4, 6, 5, 7, 8, 9, 9, 10]
values = [450, 320, 230, 280, 170, 210, 110, 150, 80, 220, 60, 180, 160]

node_labels = ['유입채널', '검색광고', '너광고', '이메일', 
               '랜딩페이지', '프로모션', '이탈', 
               '회원가입', '구매완료', '장바구니', '이탈']

colors = ['#636EFA', '#EF553B', '#00CC96', '#AB63FA', 
          '#FFA15A', '#19D3F3', '#FF6692', 
          '#B6E880', '#FF97FF', '#FECB52', '#FF6692']

fig = go.Figure(data=[go.Sankey(
    node=dict(
        pad=20,
        thickness=25,
        label=node_labels,
        color=colors
    ),
    link=dict(
        source=sources,
        target=targets,
        value=values,
        color=['rgba(99, 110, 250, 0.4)'] * len(values)
    )
)])

fig.update_layout(
    title_text="디지털 마케팅 퍼널 흐름 분석",
    font=dict(size=12, family="Malgun Gothic"),
    width=1000,
    height=650
)
fig.show()

차트 선택 가이드

차트 유형핵심 기능적합한 상황주의사항
산점도이변량 관계 탐색상관성 검증, 이상치 탐지점 중첩 시 투명도 조정 필요
버블 차트3-4차원 동시 표현복합 지표 비교크기 왜곡에 주의, 범례 필수
상관행렬다변량 상관성 요약특성 간 중복성 확인비선형 관계는 반영 못함
집약 히트맵패턴 및 군집 시각화시계열, 유전자 데이터색상 스케일 기준 명시
밀도 추정분포 형태 파악대용량 데이터 개요대역폭 파라미터 민감
다중 밀도집단 간 분리도 평가세그먼테이션, 분류영역 중첩 시 해석 주의
극좌표 다각형다차원 성능 균형 분석종합 평가, 포지셔닝축 8개 이하 권장
흐름 다이어그램양적 흐름 및 전환 추적퍼널, 공급망, 에너지노드 과다 시 복잡도 증가

태그: matplotlib Seaborn plotly 데이터시각화 상관분석

6월 21일 20:25에 게시됨