이 글의 결과물은 쥬피터에서 아래와 같은 그래프를 그리는 것이다.
이쁘게 그린다고 적어놓긴 했지만, 실제로 다루는 내용은 다음과 같다.
- 수직, 수평 막대 그래프 위에 값 표시(annotation)하기
- 수직, 수평 막대 그래프 안에 값 표시하기
- 그래프 figure 박스 제거
pandas 데이터프레임으로 그래프를 그리는 방법은, matplotlib.pyplpot
, pandas.plot()
, seaborn
등이 있지만, 여기서는 pandas.plot()
을 기본으로 사용한다.
수직, 수평 막대 그래프 위에 값 표시(annotation)하기
아래 그래프부터 그려보자.
먼저 데이터 프레임부터 보면,
print(df)
년 2017 2018
성별
F 1789522 2655864
M 2852440 4467147
이를 기본적으로 df.plot()
으로 그리면, 아래와 같이 그려진다.
df.plot(kind='bar')
plt.show()
색도 줘보고, 제목도 달아주자.
ax = df.plot(kind='bar', title="년도별 연령대 이용량 변화", rot=0, colors=['slateblue', 'darkslateblue'])
plt.show()
이제 막대 그래프 위에 값을 주자. 아래 코드를 추가한다.
for p in ax.patches:
left, bottom, width, height = p.get_bbox().bounds
ax.annotate("%.1f m"%(height/1e6), (left+width/2, height*1.01), ha='center')
하나씩 살펴보면,
ax.patches
는 ax가 가르키는 그래프에서, 막대들을 담고있는 리스트다.
현재 그래프에는 막대가 4개이므로, 4번의 반복문을 돌 것이고, 그때마다,p
는 각 막대에 대한 정보를 가리킨다.p.get_bbox().bounds
는 말 그대로 해당 막대그래프의 정보를 나타낸다.
왼쪽, 아래, 막대그래프의 폭, 높이에 대한 정보를 담는다.
살짝 살펴보면 아래와 같다. 각 튜플의 왼쪽부터, 왼쪽, 아래, 막대그래프의 폭, 높이임을 알 수 있다.
for p in ax.patches:
print(p.get_bbox().bounds)
(-0.25, 0.0, 0.25, 1789522.0)
(0.75, 0.0, 0.25, 2852440.0)
(0.0, 0.0, 0.25, 2655864.0)
(1.0, 0.0, 0.25, 4467147.0)
ax.annotate(s, xy, *args, **kwargs)
는 그래프 안에 특정 위치에 문자열을 찍어준다.s
인자에 문자열을 넣어주면된다.xy
에는 튜플로 문자열이 들어갈 (x, y) 위치를 넣어주면 된다.- 위 코드에서는
(left+width/2, height*1.01)
를 주었는데, 잘 해석해보면,x
는 현재 막대그래프의 가운데 위치y
는 현재 막대그래프의 높이 위치임을 알 수 있다.y*1.01
은 막대그래프의 높이보다 조금 더 높게(0.01
더 높게) 일종의 마진을 준 것이다. 바꿔도 상관없다.
ha
는 짐작할 수 있듯이,horizontal align
이다. 이를center
로 둬야, 중심축이 가운데로 온다.
결과적으로 다음과 같이 나온다.
수평 그래프도 위에 ax.annotate()
를 잘 생각해보면 된다.
아래와 같은 데이터프레임이 있다고 하자.
print(df)
성별
F 48.411922
M 56.607922
이를 위의 코드를 응용하여 그리면,
ax = df.plot(kind='barh', title="17년 대비 18년도 이용 증가율(%)", rot=0, colors=['red', 'blue'])
for p in ax.patches:
x, y, width, height = p.get_bbox().bounds
ax.text(width*1.01, y+height/2, "%.1f %%"%(width), va='center')
값 표시가 그래프 박스에 걸려, 보기가 싫다.
그래프 박스를 지워버리면 훨씬 깔끔하고 보기좋은데, plt.box(False)
를 추가하자.
plt.sca(ax)
plt.box(False)
훨씬 보기 좋아졌다.
수직, 수평 막대 그래프 안에 값 표시(annotation)하기
이번엔 아래와 같이 막대 그래프 안에다가 값을 넣어볼 것이다.
다음과 같은 데이터프레임이 있다고 하자.
print(df)
연령대코드 ~10대 20대 30대 40대 50대 60대 70대~
년
2017 0.026147 0.483220 0.261169 0.148048 0.058440 0.015461 0.007515
2018 0.018715 0.480448 0.262697 0.149113 0.067326 0.015917 0.005784
기본적인 틀은 수직 막대그래프와 다르지 않다.ax.annotate()
에 xy
값만 조금 달라지는데, 어떻게 달라지는지 잘 보자.
ax = df.plot(kind='barh', stacked=True, title="년도별 연령대 이용비율(%)", rot=0)
for p in ax.patches:
left, bottom, width, height = p.get_bbox().bounds
ax.annotate("%.1f"%(width*100), xy=(left+width/2, bottom+height/2), ha='center', va='center')
plt.box(False)
plt.show()
xy=(left+width/2, bottom+height/2), ha='center', va='center'
가 핵심이다.
left+width/2
는 현재 막대 그래프의 가운데 x위치,bottom+height/2
는 y위치값을 갖는다.ha=center
,va=center
로, 현재 막대 그래프의 축을 수평, 수직 가운데로 정렬한다.
수직도 이와 비슷하다.
for p in ax.patches:
left, bottom, width, height = p.get_bbox().bounds
ax.annotate("%.1f"%(height*100), xy=(left+width/2, bottom+height/2), ha='center', va='center')
plt.sca(ax)
plt.box(False)
xy=(left+width/2, bottom+height/2), ha='center', va='center'
의 의미를 잘 해석해보면 된다.
'데이터와 함께 탱고를 > 데이터 시각화' 카테고리의 다른 글
matplotlib.pyplot 좀 더 복잡한 레이아웃 1 (0) | 2019.10.02 |
---|---|
이제는 matplotlib 말고, Plotly 를 쓰자. (7) | 2019.08.17 |
pyplot 그래프의 범주박스 위치 변경하기 (0) | 2019.06.14 |
folium 의 plugins 패키지 샘플 살펴보기 2 (0) | 2019.06.03 |
folium 의 plugins 패키지 샘플 살펴보기 (7) | 2019.05.25 |