- 착시를 줄여주는 축과 격자를 설정하는 방법입니다.
- matplotlib에서는
Axes.spines와Axes.grid객체를 통해 제어합니다.
Claus Wilke, “데이터 시각화 교과서”, 영문판(Free)
Colin Ware “데이터 시각화, 인지과학을 만나다”
White Paper-Principles of Data Visualization-What we see in a Visual
1. 착시
우리 눈은 사물을 있는 그대로 보지 않습니다.
- 주변과 견주어보기도 하고, 우리가 알고 있는 지식에 비추어 보기도 합니다.
- 이런 과정에서 있는 그대로 보지 못하는 착시가 발생합니다.
착시는 생물학적 이유로 발생하기도 하는데, 예로 Mach Bands가 있습니다.
- 선이 점점 두꺼워지다 다른 선과 닿는 순간 경계 지점에 그림자가 보입니다.
- 측면 억제
lateral inhibition라는 현상이 있습니다. 경계를 명확히 인지하기 위해 이렇게 진화한 것으로 생각되는데, 자극을 강하게 받은 신경 세포는 이웃한 신경세포에 억제성 신경전달 물질을 전달해서 활성화를 억제합니다. - 그렇기 때문에 같은 색이라고 해도 다른 색과 접한 부분은 다르게 인식됩니다.
- 참고로, 이 현상을 밝힌 마하
Ernst Mach는 초음속에 대한 연구를 한 그 마하입니다.

- 한편으로 인지 방식에 의해 일어나기도 합니다.
- 우리는 배경에 비추어 물체를 인식하고 크기를 판단하기 때문입니다.
- 폰조 착시
Ponzo Illusion가 대표입니다. - 철길 그림 위의 두 막대기는 멀리 있는 것이 길어보입니다.

착시는 누구나 겪는 일이지만, 간단히 벗어날 수 있습니다.
- 이미 위 그림에서 선들이 닿기 전 배경선이 보일 때,
- 그리고 철길 위에 빨간 보조선을 그었을 때
- 우리는 착시에서 벗어나는 경험을 했습니다.
matplotlib에서는
spines와grid의 도움을 받을 수 있습니다.
2. 윤곽선 spines
matplotlib: matplotlib.spines
matplotlib: Source code for matplotlib.spines
matplotlib: Spines
matplotlib: Dropped spines
matplotlib: Spine Placement Demo
matplotlib: Centered spines with arrows
matplotlib에서 부르는 이름은 조금 낯설지만 생각해보면 은근 직관적입니다.
- 제가 축공간이라고 부르는, 그림이 그려지는 공간은
axes이고 - 눈금이 붙는 부분의 이름은
spines입니다.
- 제가 축공간이라고 부르는, 그림이 그려지는 공간은
데이터 시각화 교과서에는 spine에 대한 언급이 별로 없습니다.
- 보여주고자 하는 데이터의 종류에 따라 다르고
- 특히 그림의 종류에 따라 적절히 변형되어 사용되고 있습니다.
- 원하는 형식으로 연출할 수 있도록 이번 글은 기능 위주로 작성하겠습니다.

- matplotlib의 object oriented interface에서, spine은
ax.spines로 제어됩니다. - 지난 글에 있는 코드를 그대로 활용하고,
ax.spines활용에 집중하기 위해 시각화 코드를 함수로 만들어 버립니다.
1 | def plot_example(ax, zorder=0): |
- object oriented 방식은 이런 식의 호출이 가능합니다.
1 | fig, ax = plt.subplots() |

spines의 정체를 확인해봅시다.
1 | type(ax.spines) |

OrderedDict객체입니다.dictionary의 일종이네요.- 그럼 key와 value는 어떤 것들일까요?
1 | for k, v in ax.spines.items(): |

- key는
"left", "right", "bottom", "top"이네요. 네 개의 테두리입니다. - value가 뭔지 잘 모르겠습니다. 다시 정체를 파악해봅니다.
1 | ax.spines.values() |

matplotlib.spines.Spine객체입니다.- 공식문서에 따르면
Spine은Patch의 subclass이고 set_patch_circle,set_patch_arc가 호출되면 원이나 호를 그리기도 한답니다.- 선을 그리는
set_patch_line이 기본값입니다.
- 공식문서에 따르면
2.1. spine 숨기기 : .set_visible(False)
- 위 그림에서 맨 아래만 남기고 왼쪽, 위쪽, 오른쪽 spines를 지워보겠습니다.
set_visible(False)명령을 사용하면 됩니다.
1 | fig, ax = plt.subplots() |

- 사족을 하나 붙이면,
set_visible()은 spine에만 적용되는 명령이 아닙니다.- General Artist Properties라고 해서 모든 객체에 적용 가능한 명령입니다.
- 위 예시에선 spine에 사용했을 뿐입니다.
- 이전 글에서 설명했듯 bar 객체에도 적용 가능합니다.
2.2. spine 범위 지정하기 : .set_bounds(min, max)
- spine을 일부 영역만 보여주고 싶을 수 있습니다.
- 왼쪽 spine을 안보이게 하는 대신 가운데만 그려봅시다.
set_bounds(min, max)를 사용합니다.
1 | fig, ax = plt.subplots() |

2.3. spine 위치 지정하기 : .set_position((direction, distance))
matplotlib.spines
matplotlib.axes.Axes.set_position
matplotlib: Spine placement demo
matplotlib: Centered spines with arrows
지난번 글에서 이런 그림을 그렸습니다.
가로와 세로축을 원래 위치에서 밖으로 살짝 밀어서 공간을 확보하고 여유를 연출했습니다.

set_position((direction, distance))을 사용해서 할 수 있습니다.먼저,
get_position()을 사용해서spines["left"]가 어떻게 설정돼있나 보겠습니다.
1 | ax.spines["left"].get_position() |

- 밖으로(“outward”) 0만큼 나가있다고 합니다.
set_position(("outward", 10))을 설정해서 조금 간격을 띄워보겠습니다.
1 | fig, ax = plt.subplots() |

- “outward”를 넣을 수 있으니 거꾸로 할 때는 “inward”를 쓰면 될 것 같습니다.
- 그렇지 않습니다. 대신 거리를 음수로 넣으면 됩니다.
- “outward” 대신 “axes”, “data”를 넣을 수 있고, 의미는 다음과 같습니다.
1 | fig, ax = plt.subplots(ncols=3, figsize=(15, 3)) |

- “axes”와 “data”도 음수를 함께 사용할 수 있습니다.
- 이 기능을 이용하면 수학시간에 많이 보던 형태의 그래프를 그릴 수 있습니다.
1 | ## data |

- 자주 사용할 것들은 이렇게 간단히 사용할 수 있습니다.
set_position(("axes", 0.5"))대신set_position("center")set_position(("data", 0.0"))대신set_position("zero")
3. 격자grid
spines를 적절히 잡아주면 데이터를 읽기 좋아집니다.
그러나 데이터간 크기를 더 잘 비교하려면, 그림에 grid를 깔아주면 더 좋습니다.
.grid(True)메소드로 격자를 그릴 수 있습니다.axis={“both”, “x”, “y”} 인자로 방향을 지정합니다.
1 | fig, ax = plt.subplots(ncols=3, figsize=(15, 3)) |
3.1. major and minor ticks
- grid는 major와 minor tick을 구분하여 그릴 수 있습니다.
- 먼저, major와 minor tick을 설정합니다.
1 | from matplotlib.ticker import (MultipleLocator, AutoMinorLocator) |
3.2. major grid only
- major와 minor ticks가 구분되면, 한쪽을 선택해서 그릴 수 있습니다.
- major와 minor grid를 구분해서 지정할 수 있습니다.
- 따라서, 색상이나 선 스타일 등을 구분해서 변화시키기 좋습니다.
1 | fig, ax = plt.subplots(ncols=3, figsize=(15, 3)) |
- 최종적으로 다음과 같은 결과물을 얻을 수 있습니다.
- 불필요한 spine을 제거해서 시선 분산을 막고,
- grid를 추가해서 데이터들을 옆에 있는 숫자들과 비교하기 좋게 했습니다.
1 | fig, ax = plt.subplots() |
