データ視覚化のデザインって?
UXやUIを突き詰めたサービスで有名なTHE GUILDのGo Andoさんがnoteで公開した、データの視覚化のポイントをまとめたもの。
#1 は?
- #1については以下を参照
注意事項
- フォントについて、macでは動きますが他OSだと多分動かないので別のフォントを指定してください。
plt.rcParams['font.family'] = 'Hiragino Sans'
の部分です。
8. 第2軸は使わない
# ライブラリインポート
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)
12.における縦軸を%にする方法についてはstackoverflowの回答を参考にした1。
13.はmatplotlibの公式docを参考にした2。
またyラベルについて、1文字ずつ改行することで縦書きにすることも出来るが、コードがダサいのでしなかった。
(スマートなやり方があれば教えて下さい)
9. 要素は最低限に減らす
# データ
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')
#4. はvmaxを使ってオフセットかけることにより実現しています。
10. キーメッセージを一番大きく書く
# 色
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())
色については、なんとなくで設定しています。
本家では背景の角が丸角になっていましたが、これは再現できませんでした。(結構調べても出てこなかった…)
またplt.savefig()で保存するときはfacecolor=で背景色を指定してやる必要があります3。