더 이상 tistory 블로그를 운영하지 않습니다. glanceyes.github.io에서 새롭게 시작합니다.

새소식

Data Science/데이터 시각화

Matplotlib 모듈로 그린 Chart에서 Color 사용하기

  • -

 

2022년 2월 3일(목)부터 4일(금)까지 네이버 부스트캠프(boostcamp) AI Tech 강의를 들으면서 개인적으로 중요하다고 생각되거나 짚고 넘어가야 할 핵심 내용들만 간단하게 메모한 내용입니다. 틀리거나 설명이 부족한 내용이 있을 수 있으며, 이는 학습을 진행하면서 꾸준히 내용을 수정하거나 추가해 나갈 예정입니다.

 

 

Color in Chart

시각화에서의 Color

색이 중요한 이유

위치와 색은 구분을 위한 가장 효과적인 채널이다.

공통적으로 사람들이 색에 관해 가지는 느낌은 다르므로 색을 어떻게 하느냐에 따라 전하고자 하는 인사이트가 달라질 수 있다.

심미적으로 화려한 것은 분명히 매력적이지만, 하지만 화려함보다는 독자에게 원하는 인사이트를 전달하는 게 가장 중요하다.

색을 통해 전하고 싶은 내용을 모두 전달했는지, 그 과정에서 오해는 없는지 고려해야 한다.

 

색이 가지는 의미

어떤 물질, 물체, 단체 등에 관해 일반적으로 가지는 통념, 관념, 성질 등이 있는데, 색을 고를 때도 이에 적합한 색상을 골라야 한다.

 

 

Color Palette

색을 적재적소에 쓰기 위해서 사용하는 것이다.

 

범주형 (Categorical)

Discrete, Qualitative 등 다양한 이름으로 불린다.

독립된 색상으로 구성되어 있어서 범주형 변수에 사용한다.

너무 많은 색상을 사용한 것이 아니라 채도, 명도가 비슷한 것들끼리 묶은 것이어서 각각의 범주가 색의 차이로 구분되는 것이 특징이다.

  • One Color
    • 전체적인 분포를 보기에 유용하다.
  • Categorical
    • 이산적인 개별 값에 적합하다.
  • Diverge
  • Sequential
    • Gradient로 표현하면 같은 값에 대해서도 다른 가중치를 주는 효과가 있다.
    • Principle of Propotional Ink에 위배될 수 있다.

 

연속형 (Sequential)

정렬된 값을 가지는 순서형, 연속형 변수에 적합하다.

연속적인 색상을 사용하여 값을 표현한다.

어두운 배경에서는 밝은 색이, 밝은 배경에서는 어두운 색이 큰 값을 표현한다.

색상은 단일 색조로 표현하는 것이 좋고, 균일한 색상 변화가 중요하다.

예) github commit log

 

발산형 (Diverge)

연속형과 유사하지만 중앙을 기준으로 발산한다.

상반된 값이나 서로 다른 두 개의 Feature를 표현하는 데 적절하다.

양 끝으로 갈수록 색이 진해지며, 중앙의 색은 양쪽의 점에서 편향되지 않아야 한다.

 

 

색의 다른 용도

강조와 색상 대비

데이터에서 다름을 보이기 위해 Highlighting을 할 수 있다.

강조를 위한 방법 중 하나로서 색상 대비(Color Contrast)를 사용한다.

  • 명도 대비
    • 밝은 색과 어두운 색을 배치하면 밝은 색은 더 밝게, 어두운 색은 더 어둡게 보인다.
  • 색상 대비
    • 가까운 색은 차이가 더 크게 보인다.
    • 파랑과 보라를 가까이 배치하면 보라는 더 빨갛게 보이고, 빨강과 노라를 가까이 배치하면 보라는 더 파랗게 보인다.
  • 채도 대비
    • 채도 차이로 인해 더 선명해 보인다.
  • 보색 대비
    • 정반대 색상을 사용하면 더 선명해 보인다.

 

색각 이상

삼원색 중에서 특정 색을 감지 못하면 색맹이고, 부분적 인지 이상이 있으면 색약이다.

색 인지가 중요한 분야에서는 이에 대한 고려가 필수적이다.

예) magma, plasma 등

 

 

HSL

Hue(색조)

  • 빨강, 파랑, 초록 등 색상으로 인식하는 부분
  • 빨강에서 보라까지 있는 스펙트럼에서 0-360으로 표현

 

Saturate(채도)

  • 무채색과의 차이
  • 선명도라고 볼 수 있다. (선명하다와 탁하다.)
  • 채도가 낮다는 것은 색이 흐릿하고 회색과 가깝다는 걸 의미한다.

 

Lightness(광도)

  • 색상의 밝기
  • 색이 연하거나 진함을 나타낼 수 있다.
  • 광도가 높다는 것은 색이 흰색에 가깝다는 걸 의미한다.

 

 

Color Map 사용 예시

범주형 색상

일반적으로 tab10과 Set2가 가장 많이 사용되고, 더 많은 색은 위에서 언급한 R colormap을 사용하는 게 좋다.

from matplotlib.colors import ListedColormap

qualitative_cm_list = ['Pastel1', 'Pastel2', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', 'tab10']

fig, axes = plt.subplots(2, 4, figsize=(20, 8))
axes = axes.flatten()

student_sub = student.sample(100)

for idx, cm in enumerate(qualitative_cm_list):    
    pcm = axes[idx].scatter(student_sub['math score'], student_sub['reading score'],
                     c=student_sub['color'], cmap=ListedColormap(plt.cm.get_cmap(cm).colors[:5])
                     ) # color map에 대해서는 color가 아니라 c로 전달해야 한다.
    cbar = fig.colorbar(pcm, ax=axes[idx], ticks=range(5))
    # 오른쪽에 색상 구분에 대한 표를 추가할 수 있다.
    cbar.ax.set_yticklabels(groups)
    axes[idx].set_title(cm)
    
plt.show()

1644931600217

 

 

연속형 색상

주로 2차원 시각화 방법인 Heatmap, Contour Plot에서 사용한다.

imshow()를 사용하면 이미지 정보를 2D Array로 받아서 색상을 표현할 수 있다.

im = np.arange(100).reshape(10, 10)
fig, ax = plt.subplots(figsize=(10, 10))
ax.imshow(im)
plt.show()

1644931609779

 

 

발산형 색상

어떤 색과 어떤 값을 중심으로 삼을 것인지가 중요하며, 기준값이 있는 데이터에 대하여 적합하다.

TwoSlopeNorm()은 어떤 기준점을 바탕으로 각 한쪽씩 정규화를 진행하는 것이다.

from matplotlib.colors import TwoSlopeNorm
offset = TwoSlopeNorm(vmin=0, vcenter=student['reading score'].mean(), vmax=100)

print(student['reading score'].mean())
print(offset([0, 10, 20, 30, 70, 100]))

'''
출력
69.169
[0.         0.07228672 0.14457344 0.21686015 0.5134767  1.        ]
'''

 

from matplotlib.colors import TwoSlopeNorm

diverging_cm_list = ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
            'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']

fig, axes = plt.subplots(3, 4, figsize=(20, 15))
axes = axes.flatten()
# 2차원 데이터를 1차원 데이터로 만들어서 loop를 돌기 쉽도록 하기 위함이다.

offset = TwoSlopeNorm(vmin=0, vcenter=student['reading score'].mean(), vmax=100)

print(student['reading score'].mean())
print(offset([0, 10, 20, 30, 70, 100]))

student_sub = student.sample(100)

for idx, cm in enumerate(diverging_cm_list):    
    pcm = axes[idx].scatter(student['math score'], student['reading score'],
                            c=offset(student['math score']), 
                            cmap=cm,
                     )
    cbar = fig.colorbar(pcm, ax=axes[idx], 
                        ticks=[0, 0.5, 1], 
                        orientation='horizontal'
                       )
    cbar.ax.set_xticklabels([0, student['math score'].mean(), 100])
    axes[idx].set_title(cm)
    
plt.show()

1644931616801

 

 

Color로 특정 Feature 강조하기

fig = plt.figure(figsize=(18, 15))
groups = student['race/ethnicity'].value_counts().sort_index()

ax_bar = fig.add_subplot(2, 1, 1)
ax_bar.bar(groups.index, groups, width=0.5)

ax_s1 = fig.add_subplot(2, 3, 4)
ax_s2 = fig.add_subplot(2, 3, 5)
ax_s3 = fig.add_subplot(2, 3, 6)

ax_s1.scatter(student['math score'], student['reading score'])
ax_s2.scatter(student['math score'], student['writing score'])
ax_s3.scatter(student['writing score'], student['reading score'])

for ax in [ax_s1, ax_s2, ax_s3]:
    ax.set_xlim(-2, 105)
    ax.set_ylim(-2, 105)

plt.show()

1644931624675

 

명도 대비

a_color, nota_color = 'black', 'lightgray'

colors = student['race/ethnicity'].apply(lambda x : a_color if x =='group A' else nota_color)
color_bars = [a_color] + [nota_color]*4

1644931666001

 

 

채도 대비

a_color, nota_color = 'orange', 'lightgray'

colors = student['race/ethnicity'].apply(lambda x : a_color if x =='group A' else nota_color)
color_bars = [a_color] + [nota_color]*4

1644931672292

 

 

보색 대비

a_color, nota_color = 'tomato', 'lightgreen'

colors = student['race/ethnicity'].apply(lambda x : a_color if x =='group A' else nota_color)
color_bars = [a_color] + [nota_color]*4

1644931679284

 

Contents

글 주소를 복사했습니다

부족한 글 끝까지 읽어주셔서 감사합니다.
보충할 내용이 있으면 언제든지 댓글 남겨주세요.