8
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

データ可視化・視覚化Advent Calendar 2019

Day 3

「データ視覚化のデザイン #2」をmatplotlibで実装する

Last updated at Posted at 2019-12-03

データ視覚化のデザインって?

UXやUIを突き詰めたサービスで有名なTHE GUILDのGo Andoさんがnoteで公開した、データの視覚化のポイントをまとめたもの。

#1 は?

  • #1については以下を参照

注意事項

  • フォントについて、macでは動きますが他OSだと多分動かないので別のフォントを指定してください。
plt.rcParams['font.family'] = 'Hiragino Sans'  

の部分です。

8. 第2軸は使わない

picture_pc_35cbe51d3cf1f3331ad189ac806eae85.png

# ライブラリインポート
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.ticker import MultipleLocator


# データ
mau = [450,480,500,470,520,550,530,580,620,700,690,720]
g_rate = [0,8,0,-4,10,9,-6,12,4,12,-1,8]
g_rate = [one/100 for one in g_rate]
timeindex = pd.date_range('2019/1', periods=12, freq='MS')
mau = pd.Series(mau, index=timeindex, name='MAU(M)')
g_rate = pd.Series(g_rate,index=timeindex,name='前月成長率')

# pandasでのエラー回避用
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()

# フォント設定
plt.rcParams['font.family'] = 'Hiragino Sans'  
plt.rcParams['font.weight'] = 'heavy'

# 上下に分割
fig = plt.figure(figsize=(8,5))
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)

# 1. バーの色と幅を変更
ax1.plot(g_rate.index, g_rate,linewidth=5.,color="saddlebrown")
ax2.bar(mau.index, mau, width=20., color='darkorange', zorder=2, align='center')

# 2. y軸ラベルを表示、色、フォントサイズを指定
ax1.set_ylabel(g_rate.name,color="saddlebrown",fontsize=14,fontweight='bold')
ax2.set_ylabel(mau.name, color='gray',fontsize=14,fontweight='bold')

# 3. y軸のtick位置の変更
ax1.yaxis.set_major_locator(MultipleLocator(500))
ax2.yaxis.set_major_locator(MultipleLocator(500))

# 4. x軸y軸のtickを消す, 上のグラフに関してはx軸全て消す
ax1.tick_params(labelbottom="off",bottom=False, left=False) 
ax1.set_xticklabels([]) 
ax2.tick_params(bottom=False, left=False)

# 5. x軸y軸のtick labelの色を変更
ax1.tick_params(axis='y', colors='dimgray')
ax2.tick_params(axis='x', colors='dimgray')
ax2.tick_params(axis='y', colors='dimgray')

# 6. y軸のグリッドを表示、上のグラフに関しては色を黒に
ax1.grid(axis='y',color="black")
ax2.grid(axis='y')

# 7. 右枠を消す
ax1.spines['right'].set_visible(False)
ax2.spines['right'].set_visible(False)

# 8. 枠の色を変更
ax1.spines['bottom'].set_color('dimgray')
ax1.spines['top'].set_color('dimgray')
ax1.spines['left'].set_color('dimgray')
ax2.spines['bottom'].set_color('dimgray')
ax2.spines['top'].set_color('dimgray')
ax2.spines['left'].set_color('dimgray')

# 9. x軸のtick labelを月だけにする
# '%-m'はstrftimeのleading zeroなしmonth表記
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%-m')) 

# 10. x軸のtickの位置を毎月ごとにする
ax2.xaxis.set_major_locator(mdates.MonthLocator())
ax2.xaxis.set_tick_params(labelsize=12)

# 一度figをdrawしないとmajor tickのpositionが更新されない
fig.canvas.draw()

# 11. 縦軸の範囲指定
ax1.set_ylim(-0.20,0.20)
ax2.set_ylim(0,800)
    
# 12. 縦軸tickの変更
vals_1 = [-0.2,0,0.2]
ax1.set_yticks(vals_1)
ax1.set_yticklabels(['{:,.0%}'.format(x) for x in vals_1],color="saddlebrown",fontsize=12,fontweight='bold')
vals_2 = [0,400,800]
ax2.set_yticks(vals_2)
ax2.set_yticklabels(['{}'.format(x) for x in vals_2] ,fontsize=12,fontweight='bold')

# 13. ylabelを揃える
axs = [ax1,ax2]
fig.align_ylabels(axs)

temp_5.png

12.における縦軸を%にする方法についてはstackoverflowの回答を参考にした1

13.はmatplotlibの公式docを参考にした2

またyラベルについて、1文字ずつ改行することで縦書きにすることも出来るが、コードがダサいのでしなかった。
(スマートなやり方があれば教えて下さい)

9. 要素は最低限に減らす

picture_pc_a37bd978a068d0840f04250ca5b05a3a.png

# データ
shipment_n = pd.DataFrame([52217, 9113, 4078],
                           index=['iPhone', 'iPad', 'Mac'],
                           columns=['amount'])

fig, ax = plt.subplots(figsize=(6, 3))
ax.bar(shipment_n.index,shipment_n["amount"])

# 1. bottom以外の枠を消す
sides = ['left','right', 'top']
[ax.spines[side].set_visible(False) for side in sides] 

# 2. bottom枠の色をグレーに
ax.spines['bottom'].set_color("dimgray")

# 3. y軸のtickを消す
ax.tick_params(left=False, labelleft=False)

# 4. x軸のラベルサイズを大きく、色もグレーに
ax.tick_params(axis='x', labelsize='xx-large',color="dimgray",labelcolor="dimgray")

# 5. バーの上側に実際の値を表示
vmax = shipment_n['amount'].max()
for i, value in enumerate(shipment_n['amount']):
    ax.text(i, value+vmax*0.06, f'{value:,}', fontsize='xx-large', va='center', ha='center', color='C0')

tmp6.png

#4. はvmaxを使ってオフセットかけることにより実現しています。

10. キーメッセージを一番大きく書く

picture_pc_c0ccda82a2e6153a56d22b40e1f7d12b.png

# 色
ori_blue = "#3674b3"
ori_lightblue = "#b3daff"


# 1. 全体に色を塗る
plt.rcParams["axes.facecolor"] = (1,1,1,0)

# 2. 背景を青に
fig, ax = plt.subplots(figsize=(6, 4),facecolor=ori_blue)

# 3. タイトル
fig.suptitle("iPhoneが出荷量の8割を占める",color="white",size=24,fontweight='bold',ha='center')

# 4. 薄い青でプロット
ax.bar(shipment_n.index,shipment_n["amount"],color=ori_lightblue)

# 5. 説明を追加
ax.text(-0.4,shipment_n["amount"].max()*1.2,"図表: 2017 Appleの出荷デバイス数",color=ori_lightblue,fontsize=12)

#6. bottom以外のframeを削除
sides = ['left','right', 'top']
[ax.spines[side].set_visible(False) for side in sides] 

# 7. bottom frameの色設定
ax.spines['bottom'].set_color(ori_lightblue)

# 8. y軸の範囲設定
ax.set_ylim(0,80000)

# 9. y軸のtick label を消す
ax.tick_params(left=False, labelleft=False)
    
# 10. x軸のラベル設定
ax.tick_params(axis='x', labelsize='xx-large',color=ori_lightblue,labelcolor=ori_lightblue)

# 11. バーの上側に実際の値を表示
vmax = shipment_n['amount'].max()
for i, value in enumerate(shipment_n['amount']):
    ax.text( i,value+vmax*0.06, f'{value:,}', fontsize='xx-large', va='center', ha='center', color=ori_lightblue)

# 保存するとき
plt.savefig("savefig_with_facecolor.png",facecolor=fig.get_facecolor())

tmp8.png

色については、なんとなくで設定しています。
本家では背景の角が丸角になっていましたが、これは再現できませんでした。(結構調べても出てこなかった…)
またplt.savefig()で保存するときはfacecolor=で背景色を指定してやる必要があります3

  1. https://stackoverflow.com/questions/31357611/format-y-axis-as-percent

  2. https://matplotlib.org/3.1.1/gallery/pyplots/align_ylabels.html

  3. https://stackoverflow.com/questions/4804005/matplotlib-figure-facecolor-background-color

8
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?