- 시각화에서 색은 매우 중요한 요소입니다.
- 중요 데이터를 강조하기 위해 특정 영역의 색을 다르게 지정하기도 합니다.
- HLS 색공간을 사용해 특정 데이터만 강조합니다.
1. 중요 데이터 강조
-
아래 그림은 데이터 시각화 교과서에 수록된 데이터 강조 사례입니다.
-
여러 항공사 중 Delta와 American만 강조되어 있습니다.
-
중요한 데이터만 유채색으로, 그렇지 않으면 무채색으로 처리하면 우리 눈에 잘 들어옵니다.

-
데이터를 강조하는 가장 간단하면서도 정석적인 방법입니다.
-
하지만 막상 코드로 구현하려면 다소 성가십니다. bar마다 다른 색을 지정해야 하기 때문입니다.
2. HLS color space
2.1. 유채색과 무채색
- 유채색과 무채색의 차이는 간단합니다.
- 색을 이루는 구성 요소, 명도(Lightness), 색상(Hue), 채도(Saturation) 중 명도만 있으면 무채색입니다.
- 조금 더 정확히 말하면, 채도가 0이 되어 색상이 드러나지 않으면 무채색이 됩니다.
- 채도를 아주 살짝 남기면 색상만 약하게 전달할 수 있습니다.

2.2. set_hls()

- 색 데이터와 함께 HLS 공간에서의 수정 내역을 입력받아 바뀐 색을 출력하는 함수를 만듭니다.
- 색을 제어하는
matplotlib.colors모듈과 함께 python 기본 라이브러리colorsys를 사용합니다.
1 | import matplotlib.colors as mcolors |
- 구성은 간단합니다.
- RGB 색공간에서 정의된 색을 색상, 명도, 채도 변화량과 함께 입력받고,
- HLS 공간으로 변환해서 원하는 변화를 적용하고, 다시 RGB 색공간으로 변환시켜
return합니다. mcolors.to_rgba()명령으로 색 이름을 처리했기 때문에 array-like, string, hex code를 모두 인식합니다.- Hue는 무한 순환하지만 Lightness와 Saturation은 그렇지 않습니다. 범위를 넘지 않도록 제어합니다.
- 만약 입력 색에 alpha 채널이 있어 불투명도가 지정되어 있다면, 이를 따로 떼었다가 마지막에 다시 붙입니다.

2.3. bar plot 적용
- 펭귄 데이터셋을 예제로 bar plot을 이렇게 강조해 봅니다.
- Adelie, Chinstrap, Gentoo 세 펭귄의 데이터 수를 seaborn의
countplot함수로 표현합니다.
1 | df_peng = sns.load_dataset("penguins") |

- Gentoo 데이터만 강조합시다.
- 우리의
set_hls()를 사용할 차례입니다. - 세 개의 bar 중 처음 두 개는 명도+0.5, 채도-0.3를 적용하고, Gentoo는 채도+0.2를 합니다.
1 | for i, p in enumerate(ax.patches): |

-
sns.countplot()에palette매개변수로 각 bar별 색을 따로 지정할 수도 있습니다. -
그러나 이 경우 bar가 많으면 일일이 입력하기 어렵고,
-
sorting 등으로 순서가 바뀌면 일일이 순서를 바꿔줘야 하고
-
회색을 쓰지 않고 색상을 살짝 남기려면 RGB 공간에서 적당한 색을 찾기가 어렵습니다.
-
하는 김에 한 단계 더 들어갑니다.
-
불필요한 spines와 ticks를 제거하고 데이터 값을 bar에 직접 박아 넣습니다.
1 | ax.spines[["top", "right", "bottom"]].set_visible(False) |

- 시각화 지침서에 나오는 모범 사례에 조금은 더 가까워진 듯 합니다.
2.4. KDE plot 적용
-
같은 책에는 이런 그림도 있습니다.
-
승객의 연령과 성별을 누적 분포로 그린 그림입니다.
-
bar plot보다 난이도가 조금 더 높게 느껴집니다.

-
이번에는 이런 그림에 도전합니다.
-
seaborn의kdeplot()을 사용해 Male과 Female이 아래에 위치한 누적 분포를 그립니다. -
윤곽선을 없애기 위해
linewidth=0을 입력하고, -
배색과 hue_order를 데이터가 위에서 아래로 쌓이는 순서대로 입력합니다.
1 | fig, axs = plt.subplots(ncols=2, figsize=(10, 4), constrained_layout=True, |

- ticklabels, label, title, spines, grid 등을 차례로 수정합니다.
- 불필요한 요소는 제거하고 필요한 요소는 추가합니다.
- 애초에
sns.kdeplot()안에legend=False를 입력하면 legend가 생기지 않습니다. - 그러나 일단 생성된 legend를 제거하려면
Axes.get_legend()로 접근해서.remove()를 실행해야 합니다.
1 | titles = ["male penguins", "female penguins"] |

-
xlabel을 두 Axes에 공통으로 추가합니다.
-
Figure 레벨에 붙이는 공통 Axes는
fig.supxlabel()을 사용합니다. -
예제 그림처럼 뒤쪽에 있는 회색 밀도함수에만 투명도를 0.7로 지정합니다.
-
seaborn에서 생성한 색칠된 KDE plot은 collection 객체로 지정됩니다.
-
Legend를 새로 만들 차례입니다.
-
Legend를 지정할 요소를 list로 모아
handles로 지정하고, -
이를 가리킬 이름들을
labels로 지정해 오른쪽 Axes 우측 상단에 추가합니다.
1 | # common xlabel |

- 여기까지 했으면 모두 완료입니다.
- 그런데 수컷과 암컷에 지정된 색을 바꿔보고 싶다면
set_hls()를 적용할 수 있습니다. dh로 색상을 바꾸고ds로 채도를 낮춥니다.- handles 변경 후에는 legend도 새로 만듭니다.
1 | # 성별 밀도 함수 객체 색상 변경 |
