본문으로 건너뛰기

버그 제보

이상한 점을 알려 주시면 고칠게요. 지금 보고 있는 페이지와 브라우저 정보가 함께 담겨요.

페이지:

AI & Data

데이터 시각화: 인코딩, 차트 고르기, 디자인 원칙

작성 2026. 10. 31.추가
목차23개 항목
출처와 참고

고려사이버대학교 「데이터 시각화」(2024 여름계절학기) 강의 내용을 바탕으로 정리했다.

왜 숫자 대신 그림인가

요약 통계만 보면 같은 데이터처럼 보여도 그려 보면 전혀 다른 경우가 있다. 대표 예가 앤스컴 콰르텟(Anscombe's quartet) 이다. 네 데이터셋의 평균, 분산, 상관계수, 회귀선이 거의 같은데, 산점도로 그리면 하나는 직선 관계, 하나는 곡선, 하나는 이상치 하나가 회귀선을 끌고 가는 모양, 하나는 x값이 한 점만 빼고 모두 같은 모양이다.

쓰임하는 일예
탐색숫자 표로는 안 보이던 패턴과 이상치를 찾는다EDA 단계의 산점도 행렬, 분포 확인
전달분석 결과를 근거로 상대를 설득한다보고서의 핵심 차트 한 장

시각화는 숫자를 대체하기보다 숫자와 함께 둘 때 전달력이 가장 높다. 정답 차트는 없다. 데이터 특성과 목적을 보고 여러 방식으로 그려 본 뒤 사람이 고른다. 분석 흐름 안에서 시각화가 놓이는 자리는 파이썬 데이터 분석 프로세스에, 대시보드처럼 사람이 계속 쓰는 시각화 시스템을 설계하는 과정은 시각화 설계 과정에 있다. 남이 만든 시각화를 읽을 때도 같은 틀로 본다. 입력 데이터가 무엇이고 어떻게 가공됐나, 왜 이 형태를 골랐나, 어떤 시각 요소와 상호작용을 썼나.

그래픽 문법: 차트를 일곱 부품으로 나누기

그래픽 문법(Grammar of Graphics) 은 릴런드 윌킨슨(Leland Wilkinson)이 정리한 틀로, 모든 차트를 같은 부품의 조합으로 본다. 막대 차트와 산점도를 별개의 "차트 종류"로 외우는 대신, 어떤 부품을 바꿨는지로 설명할 수 있다. R의 ggplot2, 파이썬의 plotnine·Altair(Vega-Lite)가 이 문법을 API로 그대로 옮겼다.

요소묻는 것예
데이터(data)어떤 열을 그리나월, 지역, 매출
시각 속성 매핑(aesthetics)어느 열을 어느 채널에 대응시키나월 → x 위치, 매출 → y 위치, 지역 → 색
스케일(scale)값의 범위를 채널의 범위로 어떻게 바꾸나y축 0~120, 지역 3개 → 색 3개
기하 객체(geometry)표시를 어떤 모양으로 하나점, 선, 막대, 면
통계 변환(statistics)원값을 그리나, 계산한 값을 그리나원값, 평균, 구간별 개수, 회귀선
면분할(facets)데이터를 쪼개 여러 패널로 나누나지역별 작은 차트 3개
좌표계(coordinates)위치를 어떤 공간에 놓나직교 좌표, 극좌표, 지도 투영

같은 데이터에서 기하 객체만 점에서 선으로 바꾸면 산점도가 선 그래프가 되고, 좌표계만 극좌표로 바꾸면 누적 막대가 파이 차트가 된다.

# Altair: 문법 요소가 코드에 그대로 드러난다
import altair as alt
 
alt.Chart(df).mark_line().encode(   # geometry: 선
    x="month:T",                     # 매핑 + 데이터 유형(T=시간)
    y="sales:Q",                     # Q=정량
    color="region:N",                # N=명목 범주
).facet(column="channel:N")          # 면분할

데이터 유형이 채널을 정한다

시각화 매핑은 데이터 공간에서 시각 공간으로의 변환이다. 데이터 쪽에서 먼저 볼 것은 각 열의 유형이다.

유형예성질
정량 · 연속기온 23.4, 매출어떤 실수든 가능
정량 · 이산방문 횟수 1, 2, 3단위가 끊겨 있다
범주 · 명목개, 고양이 / 부서명순서가 없다
범주 · 순서좋음, 보통, 나쁨 / 사원·과장·부장순서는 있지만 간격은 정해지지 않았다
날짜 · 시간2024-01-01, 오전 8시연속으로도 이산으로도 다룬다
텍스트자유 서술필요하면 범주로 바꿔 처리한다

시각 쪽 채널에는 위치, 길이, 각도, 면적, 밝기, 색조, 채도, 모양, 기울기, 질감, 움직임이 있다. 매핑을 고를 때 기준은 두 가지다.

  • 표현성(expressiveness): 데이터에 있는 정보를 담되, 없는 정보를 암시하지 않는다. 순서 없는 부서명을 밝기 단계로 칠하면 부서 사이에 서열이 있는 것처럼 읽힌다.
  • 효과성(effectiveness): 중요한 열일수록 눈에 잘 띄고 정확히 읽히는 채널에 둔다.

채널마다 읽는 정확도가 다르다. 클리블랜드와 맥길(Cleveland & McGill, 1984)의 실험 이후 널리 받아들여진 순서는 대략 이렇다.

정량값을 읽는 정확도채널
높음같은 축 위의 위치
↓축이 다른 위치, 길이
↓각도, 기울기
↓면적
낮음부피, 색의 밝기·채도

그래서 핵심 비교는 위치나 길이로 하고, 색과 크기는 보조 변수에 쓴다. 범주를 구분할 때는 반대로 색조와 모양이 강하다. 면적 채널에는 함정이 있다. A가 100, B가 200일 때 원의 지름을 두 배로 하면 면적은 네 배가 되어 B가 실제보다 훨씬 커 보인다. 값은 면적에 비례시켜야 한다.

색

색은 색조(hue), 채도(chroma), 밝기(luminance)로 나눠 생각한다.

스케일쓰는 데이터만드는 법
순차(sequential)순서·연속값(인구 밀도)한 방향으로만 변하는 밝기 단계
범주(qualitative)순서 없는 범주(지역)서로 잘 구별되고 밝기가 비슷한 색조들
발산(diverging)기준점 양쪽으로 갈리는 값(전년 대비 증감)가운데 중립색, 양끝에 서로 다른 색조. 중립점을 0이나 평균 같은 의미 있는 값에 맞춘다
  • RGB 값의 차이와 눈이 느끼는 차이는 다르다. CIELAB처럼 지각 거리에 맞춘 색 공간에서 만든 스케일(matplotlib의 viridis, cividis 등)은 같은 값 차이가 같은 색 차이로 보인다.
  • 무지개 색 스케일은 피한다. 밝기가 오르내려 순서가 직관적이지 않고, 색이 바뀌는 지점에 데이터에 없는 경계가 생긴다.
  • 범주를 색으로 구분하는 건 3~5개까지가 편하다. 8~10개를 넘으면 범례를 오가며 맞추기 어렵다. 그보다 많으면 중요한 몇 개에만 색을 주고 나머지는 회색으로 둔다.
  • 사람은 범례보다 강한 색에 먼저 눈이 간다. 범주 색들의 눈에 띄는 정도를 비슷하게 맞추고, 강조할 대상에만 강한 색을 쓴다. 아무 뜻 없는 색은 방해이고, 넓은 면적에는 채도를 낮춘다.
  • 색각 이상을 고려한다. 적록 구분이 어려운 경우가 가장 흔하다. ColorBrewer의 색각 친화 팔레트, Okabe-Ito 팔레트, viridis·cividis를 쓰고 시뮬레이터로 확인한다.
  • 표시가 작아지면(작은 점, 가는 선) 색 구별이 급격히 어려워진다. 작은 표시일수록 대비가 큰 색을 쓴다.

밝기와 색조의 지각 차이는 인터페이스 심리학에, 웹 화면의 대비 기준은 색과 움직임의 접근성에 있다.

좌표계와 축

직교 좌표계가 기본이다.

  • 축에는 변수 이름과 단위를 적는다.
  • 두 축의 단위가 같으면(예: 섭씨 대 섭씨) 격자 간격도 같게 둔다. 단위가 다르면 종횡비는 전하려는 메시지에 맞춰 조절한다. 선 그래프는 종횡비만 바꿔도 변화가 가파르게도 완만하게도 보인다.
  • 값이 몇 자릿수에 걸쳐 퍼져 있거나 비율(배수)이 의미 있는 데이터는 로그 축을 쓴다. 로그 축에서는 같은 간격이 같은 배수를 뜻하므로, 로그 스케일이라는 사실과 눈금 값을 분명히 적는다.
곡선 좌표계맞는 데이터
극좌표끝이 처음과 이어지는 순환 데이터(12개월, 풍향 360도)
지도 투영(로빈슨, 빈켈 트리펠 등)위경도 데이터. 위경도를 그냥 직교 좌표에 펴면 고위도가 부풀려진다

지각과 주의: 사람은 어떻게 보나

차트를 처음 보는 짧은 순간에 사람은 세부가 아니라 요지(gist) 를 잡는다. 전체 윤곽과, 점들의 평균 크기·퍼짐 같은 집합 수준의 특징(앙상블 코딩)이다. 차트를 흐리게 했을 때 보이는 모양이 대략 첫인상이다. 그래서 같은 데이터도 인코딩에 따라 "최댓값이 있는 달"이 먼저 보이기도, "평균이 높은 달"이 먼저 보이기도 한다.

색조, 기울기, 길이, 크기, 밝기, 채움 같은 사전 주의 속성은 하나만 다르면 찾으려 애쓰지 않아도 튀어나온다(pop-out). 강조는 이 속성 하나로 한다. 두 가지를 섞어야 구별되는 대상은 하나씩 살펴야 찾는다. 묶음은 게슈탈트 원리를 따른다. 가까우면(근접), 비슷하면(유사), 같은 영역 안에 있으면(공통 영역), 선을 따라 늘어서 있으면(연속) 한 그룹으로 보고, 끊긴 모양도 닫힌 하나로 보며(폐쇄), 강조 대상과 배경을 나눠 본다(전경-배경). 레이아웃 쪽 설명은 웹 레이아웃 디자인과 UI 밀도에 있다.

시야 전체가 선명하다고 느끼지만 해상도 높게 보는 곳은 시선이 머무는 작은 중심부뿐이다.

주의 방식무엇이 시선을 이끄나언제
하향식(top-down)보는 사람의 목적과 지식 ("B가 A보다 얼마나 큰가")찾을 것이 정해진 확인·비교
상향식(bottom-up)색·모양·크기 같은 차트의 특징처음 보는 데이터를 탐색할 때. 인코딩이 결론을 유도한다
  • 변화 맹시(change blindness): 장면이 바뀔 때 일부가 달라져도 잘 알아채지 못한다. 애니메이션보다 나란히 놓은 정지 화면을 비교하기가 쉽다. 애니메이션을 쓰면 한 번에 담는 정보를 줄인다.
  • 분리 가능성(separability): 너비와 높이는 한 덩어리(면적)로 읽히기 쉽고, 위치와 색은 따로 읽힌다. 여러 채널을 한 표시에 겹칠 때 따로 읽히는 조합을 고른다.
  • 중복 인코딩(redundant encoding): 중요한 범주는 색과 모양을 함께 바꿔 두 경로로 찾게 한다. 색이 비슷한 범주도 구별되고, 흑백 인쇄와 색각 이상에도 견딘다. 반대로 데이터와 무관한 장식용 색·패턴은 없는 의미를 만든다.
  • 시각적 어수선함(clutter): 표시가 너무 많으면 묶거나(육각형 구간으로 집계하고 이상치만 남기기), 정렬해서 패턴이 드러나게 한다(아래 「겹친 점 풀기」).

질문으로 차트 고르기

차트 이름부터 고르면 데이터에 안 맞는 그림이 나오기 쉽다. "이 데이터에서 무엇을 보고 싶은가" 를 먼저 정하면 후보가 두세 개로 줄어든다.

질문기본 차트데이터가 많거나 복잡하면seaborn / matplotlib
항목별 크기는?막대점 도표, 히트맵barplot, barh, heatmap
값이 어떻게 퍼져 있나?히스토그램, 밀도ECDFhistplot, kdeplot, ecdfplot
여러 집단의 분포 비교는?박스, 바이올린스트립+지터, 융기선boxplot, violinplot, stripplot
전체 중 몇 퍼센트?파이, 누적 막대병렬 막대pie, bar(bottom=...)
범주 안의 범주 비율은?모자이크, 트리맵평행 집합statsmodels mosaic, squarify
두 변수는 같이 움직이나?산점도산점도 행렬, 상관 행렬scatterplot, pairplot, heatmap(df.corr())
같은 대상의 전후 비교는?경사 차트, 대각선 산점도-plot으로 선 연결
시간에 따라 어떻게 변하나?선 그래프이동 평균, LOESSlineplot, rolling().mean()

수량: 항목별 크기 비교

막대 도표는 범주마다 하나의 수치(브랜드별 판매량, 도시별 인구)를 비교할 때 쓴다.

  • 레이블이 길면 가로 막대로 돌린다. 레이블을 기울이면 공간은 아끼지만 읽기 어렵다.
  • 순서를 의미 있게 정한다. 자연스러운 순서(연령대)가 없으면 값 크기순으로 정렬한다. 알파벳순은 찾기는 쉽지만 요점이 안 보인다.
  • 묶은 막대는 한쪽 기준 비교는 쉽지만 다른 쪽 비교가 어렵다. 어느 비교가 중요한지 정하거나 범주별 작은 차트로 나눈다(면분할).
  • 누적 막대는 쌓은 합계가 의미 있을 때만 쓴다(객실 등급별 남녀 탑승객 → 등급별 총인원). 막대 안에 값을 직접 적으면 y축을 생략할 수도 있다.

막대는 0에서 시작해야 길이가 값에 비례한다(아래 「잉크 비례 원칙」). 값들이 60~80처럼 좁은 범위에 몰려 있으면 막대로는 차이가 안 보인다. 점 도표(dot plot) 는 길이가 아니라 위치로 값을 나타내므로 축을 데이터 범위로 좁혀도 왜곡이 없다. 항목 수와 시점 수가 모두 많으면(국가 × 연도별 인터넷 보급률) 히트맵이 값을 색으로 바꿔 전체 추세를 한 장에 보여 준다. 정확한 값 비교는 포기하는 대신이고, 행의 정렬 기준(최근 값 순, 임계값을 처음 넘은 연도 순)에 따라 드러나는 이야기가 달라진다.

분포: 값이 어떻게 퍼져 있나

차트장점주의
히스토그램직관적이다구간 폭에 따라 모양이 달라진다. 몇 가지 폭으로 그려 본다
밀도 도표(KDE)매끄러운 곡선, 곡선 아래 넓이가 1대역폭에 따라 모양이 바뀌고, 나이가 음수인 구간처럼 데이터가 없는 곳까지 곡선이 뻗을 수 있다
경험적 누적 분포(ECDF)모든 점을 그대로 쓰고 구간 폭 같은 선택이 없다읽는 법이 낯설다. y축을 비율(0~1)로 두면 "하위 50%가 몇 점 이하"를 바로 읽는다

히스토그램과 밀도 도표는 원데이터라기보다 데이터에 대한 해석이다. 여러 분포를 비교할 때는 다음 중 고른다.

차트언제
겹친 히스토그램두 집단까지. 쌓으면 막대 시작점이 헷갈리고, 반투명으로 겹치면 세 번째 범주처럼 보이는 색이 생긴다
겹친 밀도 도표두세 집단. 전체 분포를 회색 배경으로 깔고 집단별로 나눠 그리면 더 잘 읽힌다
연령 피라미드두 집단(남녀)의 히스토그램을 좌우로 맞댄다
평균 + 오차 막대간단하지만 분포 모양(쌍봉, 치우침)을 숨긴다
박스 도표중앙값, 사분위(Q1~Q3, 가운데 50%), 수염, 이상치를 간결하게. 집단이 많을 때 좋다
바이올린 도표박스보다 분포 모양을 잘 보여 준다. 데이터가 충분해야 매끄럽다
스트립 차트 + 지터점을 다 찍고 좌우로 살짝 흩뿌려 겹침을 푼다. 데이터가 적을 때 정직하다
시나 도표바이올린 모양 안에 지터한 점을 찍는다
융기선(ridgeline) 도표여러 밀도 곡선을 산등성이처럼 겹친다. 시간에 따른 분포 변화(연도별 영화 상영 시간)를 볼 때
import seaborn as sns
 
sns.histplot(df, x="age", bins=20)                     # 구간 수를 바꿔 가며 확인
sns.ecdfplot(df, x="score", stat="proportion")
sns.violinplot(df, x="group", y="value", inner="quart")
sns.stripplot(df, x="group", y="value", jitter=0.2, alpha=0.5)

비율: 전체 중 얼마인가

할 수 있는 것파이누적 막대병렬 막대
전체 대비 비율이 분명하다○○-
조각끼리 상대 비교가 쉽다--○
1/2, 1/4 같은 단순 분수가 잘 보인다○--
조각이 아주 적어도 보기 좋다○-○
조각이 많아도 된다--○
시간에 따른 비율 변화를 보여 준다-○○
  • 파이 여러 개로 연도별 점유율을 비교하면 추이가 거의 안 보인다. 각도는 길이보다 비교하기 어렵다.
  • 누적 막대에서 바닥과 꼭대기에 붙은 조각은 변화가 잘 보이지만 가운데 조각은 기준선이 움직여 비교가 어렵다. 조각이 두 개(남녀 성비)면 이 문제가 없다.
  • 연속 변수(나이)에 따른 비율 변화는 누적 밀도로 그릴 수 있다. 일부 범주가 급격히 변하면 범주마다 "이 범주 대 나머지"를 따로 그린다.

정당별 성비처럼 범주 안의 범주가 있는 데이터를 한 파이에 넣으면 같은 대상을 두 번 세어 합이 100%를 넘는 실수가 생긴다. 대신 가로 폭과 세로 높이로 두 범주의 비율을 함께 보이는 모자이크 도표, 사각형을 계층적으로 쪼개는 트리맵(크기 비교가 어려우니 숫자를 함께 적는다), 범주 축을 나란히 세우고 띠로 잇는 평행 집합(범주가 셋 이상일 때 강하고, 색칠 기준과 축 순서를 바꾸면 띠의 교차가 줄어든다)을 쓴다. 두 겹 도넛은 조각이 작아 레이블이 안 들어가고 공간 효율이 낮다.

관계: 두 변수는 같이 움직이나

차트쓰임
산점도점 하나가 관측 하나. 퍼진 모양으로 관계를 본다. 색으로 범주를 더하면 집단 비교도 된다
버블 차트점 크기로 세 번째 변수를 더한다. 위치와 크기를 동시에 읽어야 해서 혼란스럽다
산점도 행렬모든 변수 쌍의 산점도를 격자로. EDA 첫 단계에 좋다
상관 행렬(correlogram)상관계수(-1~1)를 색이나 원 크기로. 간결하지만 상관계수만으로는 관계의 모양을 모른다(앤스컴 콰르텟)

쌍 데이터(paired data) 는 같은 대상을 조건만 달리해 두 번 잰 데이터다(2000년·2020년 배출량). 대상이 많으면 x=전, y=후 산점도에 y=x 대각선을 긋고(선 위는 증가, 아래는 감소), 대상이 적으면 두 시점을 세로축 두 개에 놓고 선으로 잇는 경사 차트(slopegraph) 를 쓴다.

sns.pairplot(df, hue="species")
sns.heatmap(df.corr(numeric_only=True), cmap="RdBu_r", vmin=-1, vmax=1, annot=True)

시계열: 시간에 따라 어떻게 변하나

  • 시간 순서대로 점만 찍으면 흐름이 잘 안 느껴진다. 선으로 이으면 흐름이 드러난다. 선은 데이터가 아니라 추세를 따라가게 돕는 안내선이다.
  • 점이 많으면 선만 남긴다. 계열이 하나면 선 아래를 칠해 흐름을 강조할 수 있다.
  • 계열이 여럿이면 범례 대신 선 끝에 이름을 직접 붙인다.
  • 시간이 아니어도 순서가 있는 x(비료 투입량에 따른 수확량)라면 선 그래프를 쓴다.
추세 표현원리특징
이동 평균일정 구간의 평균을 한 칸씩 밀며 계산단순하다. 창 크기만큼 앞쪽 데이터가 비고, 창이 크면 반응이 늦다
LOESS구간마다 낮은 차수의 다항식을 국소적으로 적합더 매끄럽고 시계열이 아닌 산점도에도 쓴다
스플라인제어점 사이 구간을 곡선으로 적합종류와 매듭 수에 따라 결과가 달라진다
정해진 함수 적합직선, 지수 등 형식을 정하고 계수를 찾는다성장 법칙을 알 때. 지수 성장은 로그 축에서 직선이 된다
추세 제거(detrending)장기 추세를 빼고 남은 편차만 그린다큰 흐름에 가려진 지역별 차이가 드러난다
import numpy as np
 
ts["ma_30"] = ts["close"].rolling(30).mean()           # 30일 이동 평균
slope, intercept = np.polyfit(x, y, 1)                  # 선형 추세

그래프 디자인 원칙

차트 종류를 맞게 골라도 축 하나, 색 하나 때문에 메시지가 틀어질 수 있다. 문제 있는 차트는 심각도로 나눠 보면 고칠 순서가 잡힌다.

등급뜻예
조악함(ugly)내용은 맞지만 보기에 거슬린다어긋난 패널 정렬, 어울리지 않는 글꼴
모호함(bad)오해하게 만들 수 있다패널마다 다른 y축 범위, 의미 없는 색
틀림(wrong)수학적으로 사실과 다르다합이 135%인 파이, 0이 아닌 곳에서 시작한 막대

잉크 비례 원칙

값을 나타내려고 칠한 면적은 그 값에 비례해야 한다.

  • 막대와 면적 차트는 0에서 시작한다. 중위 소득 막대를 5만 달러에서 시작하면 작은 차이가 몇 배처럼 보인다.
  • 차이를 강조하고 싶으면 축을 자르지 말고 차이 자체를 그린다. "5년간 소득 변화량" 막대는 0에서 시작해도 차이가 선명하다. 주가라면 "고점 대비 하락률"을 그린다.
  • 칠하지 않은 선 그래프는 축을 0에서 시작하지 않아도 되지만, 축 범위가 변동 폭을 얼마나 과장하는지 의식한다.
  • 로그 축 막대는 0을 그릴 수 없어 시작점이 임의로 정해진다. 점으로 바꾸거나, 비율 데이터라면 기준값 1(어떤 대상 대비 배수)에서 막대를 시작한다.
  • 파이 조각과 트리맵의 면적은 값에 비례하므로 원칙에 맞다. 다만 사람이 면적보다 길이를 더 민감하게 비교해서, 같은 데이터를 막대로 그리면 차이가 더 크게 보인다.

겹친 점 풀기(오버플로팅)

점이 같은 자리에 쌓이면 데이터가 몇 개인지, 뒤에 무엇이 숨었는지 알 수 없다. 데이터가 많을 때뿐 아니라 반올림으로 같은 값이 많을 때도 생긴다.

방법원리한계
반투명겹친 곳이 진해진다몇 개가 겹쳤는지 정확히 모른다. 점이 수만 개면 진한 얼룩만 남는다
지터(jitter)점마다 위치를 살짝 흔든다너무 많이 흔들면 데이터가 왜곡된다
2차원 히스토그램 / 육각형 구간(hexbin)평면을 칸으로 나누고 칸마다 개수를 색으로개별 점은 사라지지만 수십만 점도 요약된다
등고선점 밀도를 추정해 등고선을 긋는다범주가 많고 서로 겹치면 읽을 수 없다. 그때는 범주별 패널로 나눈다
import matplotlib.pyplot as plt
import seaborn as sns
 
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
axes[0].scatter(x, y, alpha=0.2, s=8)                        # 반투명
axes[1].hexbin(x, y, gridsize=40, cmap="viridis", mincnt=1)  # 육각형 집계
sns.kdeplot(x=x, y=y, ax=axes[2], fill=True, levels=8)       # 등고선

범례보다 직접 레이블

  • 가능하면 범례를 없앤다. 선 끝, 밀도 곡선 옆, 점 무리 근처에 이름을 직접 쓴다. 그룹을 타원으로 감싸 이름을 다는 방법은 타원 자체가 무언가를 뜻하는 것처럼 오해될 수 있다.
  • 범례를 써야 한다면 범례 순서를 데이터 순서와 맞춘다. 선 그래프의 마지막 값이 위에서부터 A, B, C면 범례도 A, B, C로. 도구가 자동으로 정한 순서는 대개 이렇지 않다.
  • 연속 색 스케일은 축과 합칠 수 있다. 기온 x축 아래에 같은 색 띠를 깔면 범례가 따로 필요 없다.
  • 점선·쇄선으로 범주를 나누면 선 그래프가 산만해진다. 색을 먼저 쓴다.

제목, 축, 캡션

책·논문·보고서에서는 그림 아래 캡션의 첫 문장이 제목 역할을 하므로 그림 안에 제목을 넣지 않는다. 웹·슬라이드·SNS에 그림만 단독으로 실을 때는 그림 안에 제목을 넣는다. 축 레이블에는 변수 이름과 단위를 적고, 맥락만으로 분명한 레이블(범례 제목 "species"처럼)은 지운다. 다만 y축 레이블은 제목에서 짐작할 수 있어도 남기는 편이 안전하다.

표를 그릴 때

정확한 값을 찾아봐야 할 때는 차트보다 표가 낫다.

  1. 세로선을 넣지 않는다.
  2. 데이터 행 사이에 가로선을 넣지 않는다. 가로선은 머리글과 본문 경계, 표 위아래에만.
  3. 글자 열은 왼쪽 정렬, 숫자 열은 오른쪽 정렬하고 소수점 자릿수를 맞춘다.
  4. 한 글자짜리 열은 가운데 정렬한다.
  5. 머리글은 아래 데이터 열과 같은 정렬을 따른다.

여러 패널: 면분할과 복합 도표

  • 면분할(faceting): 변수 하나로 데이터를 쪼개 같은 형식의 작은 차트를 나란히 놓는다. 패널 순서를 논리적으로(연도순, 값 크기순) 정하고, 비교가 목적이면 축 범위를 통일한다. 패널마다 y축이 다르면 작은 변화가 큰 변화처럼 보인다.
  • 복합 도표: 전체 추세는 선 그래프, 상위 다섯 항목은 경사 차트처럼 서로 다른 차트를 묶어 큰 그림과 세부를 함께 보여 준다.
  • 묶은 패널끼리는 같은 범주에 같은 색과 같은 위치를 쓴다. 패널 정렬을 맞추고, 패널 번호(a, b, c)는 읽기를 방해하지 않는 위치에 본문 글꼴로 둔다.

맥락 요소: 격자, 테두리, 기준선

에드워드 터프티(Edward Tufte)의 데이터-잉크 비율은 전체 잉크 중 데이터를 전하는 잉크의 비율을 높이라는 원칙이다. 다만 비데이터 잉크를 무조건 지우면 레이블과 패널 경계까지 흐려져 오히려 읽기 어렵다. 목표는 타당한 범위 안에서 높이는 것이다. UI 전반에 이 원칙을 적용한 이야기는 UI 밀도에 있다.

  • 테두리와 격자는 연한 회색으로. 진하고 촘촘한 격자는 데이터를 묻는다.
  • 값을 읽는 방향의 격자만 남긴다. 세로 막대면 가로 격자만, 가로 막대면 세로 격자만.
  • 의미 있는 기준값(지수 100, 목표치, 0)이 있으면 기준선 하나를 긋는다. 격자 여러 줄보다 강력하다.
  • 쌍 데이터 산점도에는 격자보다 y=x 대각선이 낫다.
  • 다중 패널에서 비데이터 잉크를 다 빼면 패널 경계가 사라진다. 옅은 배경이나 가는 기준선으로 구획을 남긴다.
ax.grid(axis="y", color="0.85", linewidth=0.8)
ax.set_axisbelow(True)                 # 격자를 데이터 뒤로
for side in ("top", "right"):
    ax.spines[side].set_visible(False)
ax.axhline(100, color="0.3", linewidth=1)   # 기준선

피해야 할 것

  • 너무 작은 글자: 기본 설정의 축 글자는 문서나 슬라이드에 줄여 넣으면 읽을 수 없다. 글자만 키우면 점과 선이 상대적으로 작아지니 글자·점·선을 함께 키우고, 최종 크기로 줄여서 확인한다.
  • 선만 있는 그림: 윤곽선만 있는 막대·박스·밀도 곡선은 안팎 구분이 어렵다. 연한 색으로 채우고, 겹치는 밀도 곡선은 반투명으로 칠한다.
  • 3차원: 사람의 눈은 평면에 투영된 입체를 머릿속에서 복원하며 크기를 보정하고, 그 과정에서 값이 틀어진다.
3D 차트문제대안
3D 파이기울인 각도 때문에 앞쪽 조각이 커 보인다2D 파이나 막대
3D 막대벽에서 떨어진 막대가 실제보다 작게 읽히고 뒤 막대가 가려진다변수별로 2D 막대를 나눠 그린다
3D 산점도정지 화면으로는 점의 깊이를 알 수 없다2D 산점도 두 개로 나누거나, 세 번째 변수를 점 크기·색으로

3차원이 괜찮은 경우는 사용자가 직접 돌려 볼 수 있을 때, 천천히 회전하는 영상일 때, 지형이나 단백질 구조처럼 원래 3차원인 대상을 보여 줄 때다.

점검 목록

  • 칠한 막대·면적은 0에서 시작하나
  • 점이 겹쳐 숨은 데이터는 없나
  • 색은 5개 이하이고 각각 뜻이 있나, 색각 이상에서도 구별되나
  • 범례 대신 직접 레이블을 쓸 수 있나, 범례 순서가 데이터 순서와 같나
  • 축 레이블에 단위가 있나
  • 패널끼리 축 범위와 색 배정이 같나
  • 격자와 테두리가 데이터보다 눈에 띄지 않나
  • 최종 크기에서 글자가 읽히나
  • 3D나 선만 있는 표현을 쓰지 않았나

정리

  • 시각화는 데이터 열을 시각 채널에 대응시키는 매핑이다. 그래픽 문법의 일곱 요소로 차트를 분해해 설명한다.
  • 정량값의 정확한 비교는 위치와 길이로, 범주 구분은 색조와 모양으로 한다. 순서 있는 값은 한 방향 밝기 스케일, 기준점이 있으면 발산 스케일을 쓰고 무지개는 피한다.
  • 차트는 질문으로 고른다. 크기는 막대·점·히트맵, 분포는 히스토그램·박스·바이올린·ECDF, 비율은 파이·누적 막대·모자이크, 관계는 산점도·경사 차트, 시간은 선과 평활 곡선.
  • 칠한 면적은 값에 비례시키고, 겹친 점은 투명도·지터·집계로 풀고, 색은 적게, 레이블은 직접 단다.
  • 사람은 첫눈에 요지를 잡고 튀는 속성 하나에 끌리므로, 강조는 하나로 하고 맥락 요소는 옅게 둔다.

관련 노트: 시각화 설계 과정, 파이썬 데이터 분석 프로세스, 데이터의 위치 추정, 데이터 저널리즘, Jupyter Notebook, 개발자를 위한 시각 디자인 요령, 발표 자료 디자인

댓글

GitHub 계정으로 댓글을 남길 수 있어요.