3. seaborn figure-level function
- seaborn의 핵심기능, 강력한 명령입니다.
- 4부 중 세 번째 시간입니다.
- matplotlib으로는 매우 수고스러울 일을 줄여줍니다.
- 그러나 손대기 어렵기도 합니다. 이유와 해결방법을 알아봅시다.
-
지난 글에서 matplotlib과 친한 함수를 알아봤습니다.
- 이런 axex 반환 함수를
axes-level함수, - 반대로 그림 전체를 반환하는 함수를
figure-level함수라고 합니다.
- 이런 axex 반환 함수를
-
아래 노란 부분이
figure-level함수입니다.

-
반환 형식
return type이 왜 이렇게 깔끔하지 않은지는 뒤에 보겠습니다. -
figure-level함수는 복잡한 그림을 한 번에 편하게 그려줍니다.
3.1. figure-level 편리함 맛보기: FacetGrid()
-
seaborn에 내장된 penguins dataset에는 이런 데이터가 있습니다.
- bill_length_mm : 부리 길이
- bill_depth_mm : 부리 위아래 두께
- species : 펭귄 종
- sex : 성별
- island : 서식지
-
이 데이터를 산점도로 한번에 나타내고자 합니다.
- X축 : bill_length_mm
- Y축 : bill_depth_mm
- 색상 : species
- X방향 axes : island
- Y방향 axes : sex
-
matplotlib 코드는 이렇습니다.
1 | fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 8), sharex=True, sharey=True) |

-
따로 꾸민 것도 없는데 매우 번잡합니다.
- 인자별로 몇가지인지를 알아내야 합니다.
- 결측치 처리가 필요합니다. 안하면 에러납니다.
- 색상별로 따로 그려야 합니다.
-
그런데 seaborn을 사용하면 세 줄 만에 끝납니다.
1 | g = sns.FacetGrid(penguins, row="sex", col="island", hue="species") |

-
FacetGrid()로 만든 공간을.map()으로 채웁니다.- 데이터셋 이름, 변수 이름, 그리는 방식 외에 다른 내용이 없습니다.
- 인자가 여럿인 관계를 보기에 아주 좋습니다.
-
밀도 함수
density plot로 바꾸는 것도 간단합니다. -
위 코드에서
sns.scatterplot만sns.kdeplot으로 넣으면 됩니다.
1 | g = sns.FacetGrid(penguins, row="sex", col="island", hue="species") |

figure-level함수는 복잡한 그림을 간단히 그릴 때 매우 강력합니다.- 이 그림들을 matplotlib으로 그리려면 얼마나 막막할까요.

3.2. figure-level 꾸미기: FacetGrid()
-
이번엔
figure-level그림을 꾸며 보겠습니다.kdeplot위에 추세선을 겹쳐 그립니다.
- 추세선이 중간에 안끊기면 좋겠습니다.
- 신뢰구간은 80% 수준으로 그리고 싶습니다.
- xlabel을 "Bill Length (mm)"로 바꾸고
- ylabel을 "Bill Depth (mm)"로 바꿉니다.
-
공식 홈페이지의 설명에 힘입어 해냈습니다.
1 | g = sns.FacetGrid(penguins, row="sex", col="island", hue="species") |

-
한 단계 더 꾸며보도록 합시다.
- xlabel, ylabel 글자를 키우고 싶습니다.
- 추세선의 신뢰구간 80%를 적어두고 싶습니다.
- axes마다 붙어 있는 title을 정리하고 싶습니다.
-
첫 단계에서 막혔습니다.

-
xlabel, ylabel을 수정할 때
set_axis_labels()를 사용했습니다.- 공식 홈페이지의
FacetGrid()부분 가이드를 따른 것입니다. - 그런데
set_axis_labels()에 대한 설명이 더 이상 없습니다.
- 공식 홈페이지의
-
혹시나, matplotlib 명령어를 넣어봅니다.
-
fontdict=를 적용합니다.
1 | g = sns.FacetGrid(penguins, row="sex", col="island", hue="species") |

figure-level그림의 세부 설정은 도움말 찾기도 어렵습니다.- 매뉴얼에 없는 내용을 상상해서 넣어야 합니다.
- 아직은 공식 홈페이지가 충만하지 않습니다.
- 소스코드를 뜯어봐서 기능을 확인하거나
- matplotlib 명령어를 숙지하고 대응시켜 시도해야 합니다.
3.3. figure-level의 장단점
-
공식 튜토리얼에 정리된 장단점은 이렇습니다.

-
하나씩 짚어보겠습니다.
-
(1) 데이터 변수에 따른 축공간 생성
- matplotlib에서 변수 갯수를 세어야 했던 것에 비해서 편리합니다.
- seaborn에 구현된 그림을 제어하는 인자 수가 확실히 적습니다.
- 번거롭더라도 axes에 직접 접근해서 matplotlib 명령을 쓰는 게 낫습니다.
-
(2) 그림 밖 범례 생성
- 그림 밖에 붙는 것은 다행입니다.
- 그러나 통제가 안되어 심각한 갈증을 유발합니다.
-
(3) figure-level 수정 & (4) figure size를 조정하는 인자가 다름
- 장점보다 단점이 크다고 생각됩니다.
- 더 쉬운 명령어를 제공한다고 해도 결국은 또 다른 문법입니다.
- matplotlib 명령어만 해도 정신이 없는데 말이죠.
-
지금까지의 경험으로 이런 결론이 나옵니다.
- “figure-level의 가성비는 그리자마자, 손을 더 대기 전이 가장 높다.”
- 새로운 명령어는 새로운 혼돈입니다.
- 시각화만 붙잡고 있을 게 아니라 통계분석, 머신러닝도 해야 하거든요.
3.4. figure-level그림이 손대기 어려운 이유
-
seaborn 코드를 뜯어보면 클래스 구조는 이렇습니다.

-
multi-plot grids는 Grid 클래스를 상속받는 가족입니다.
FacetGrid(),PairGrid(),ClusterGrid입니다.JointGrid()는 Grid를 상속받지 않습니다.- Grid로 만든 공간에 목적에 맞는 그림을 채웁니다.
relplot(),displot(),catplot(),lmplot()은 1x1FacetGrid()로 출력됩니다.
-
그리고 Grid 클래스는
figure의 wrapper입니다.- 정확히는
matplotlib.pyplot.subplots()의 wrapper입니다. - 따라서
figure,axes에 적용되는 matplotlib 명령이 안통합니다. - 그래서
set_axis_labels같은 자체 명령어를 탑재하고 있습니다. - 하지만 보셨다시피 도움말이 충분치 않습니다.
- 정확히는
3.5. figure-level 그림을 꾸미는 방법
-
한마디로, seaborn 제공 함수는 한계가 큽니다.
- 기능 자체도 많이 빠져있고
- 있는 기능도 문서화가 덜 됐습니다.
- 이걸 믿고 쓰긴 어렵습니다.
-
하지만 대안이 있습니다.
- seaborn 그림을 matplotlib 그림으로 간주합니다.
figure-level객체 안으로 한 걸음 들어갑니다.- 그리고
figure와axes를 직접 건드립니다.
-
개흉 심장마사지를 상상하시면 됩니다.
-
가슴을 열고 직접 심장을 마사지하는 겁니다.

-
그러면, 풀지 못했던 난제도 이렇게 풀립니다.
1 | g = sns.FacetGrid(penguins, row="sex", col="island", hue="species", margin_titles=True, despine=False) |

- 외웁시다.
figure-level함수는 matplotlib과 못 섞는다.figure-level함수는figure와axes를 한번 더 감싸고 있다.figure-level함수를 수정하려면 후벼 파는 과정이 필요하다.