pythonでexcelっぽい図を作図できるのか
みなさんご存知excelは優秀な表計算ソフトです。一般的な事務用途でしたら最も普及しているアプリケーションですし、マクロを組み合わせたら統計解析なんかもチョチョイのチョイです。ですが、excelでデフォルトで出力される図ってなんというか、見た目がスタイリッシュではないですよね。報告資料などにexcelの図をそのまま貼り付けるのではなく、試行錯誤して調整するか、IgorとかMatlabなどといった他のアプリケーションを使って描画するのではないかと思います。
今回はそこをあえてpythonを使ってどこまでexcelのデフォルトの散布図をコピーできるかというのに挑戦しました。結構pythonを使ったplotの練習になります。
描画データ
描画データはxに対して簡単な3つの関数を用意しました。
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
are = x + 5
kore = 2x
sore = (x/2)^2
excelで描画してみるとこんな感じです。
さて、これをptythonで完コピしましょう。
pyhtonでの描画完コピ前
pythonのデフォルトのプログラムと描画はこんな感じです。
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
are = x + 5
kore = x*2
sore = (x/2)**2
fig, ax = plt.subplots()
plt.plot(x, are)
plt.plot(x, kore)
plt.plot(x, sore)
plt.show()
シンプルですね。
pyhtonでの描画完コピ後
先に結果をお見せします。
import matplotlib.pyplot as plt
import numpy as np
#font
plt.rcParams["font.family"] = 'Yu Gothic'
x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
are = x + 5
kore = x*2
sore = (x/2)**2
#color
orange = np.array([254, 117, 0])/255
blue = np.array([66, 106, 199])/255
gray = np.array([165, 165, 165])/255
text_color = np.array([89, 89, 89])/255
line_color = np.array([217, 217, 217])/255
#plot
fig, ax = plt.subplots(figsize=(7.2, 4.1), edgecolor=line_color, linewidth=0.7)
plt.plot(x, are, "o", label="are", color = blue, markersize=7.5, clip_on=False)
plt.plot(x, kore, "o", label="kore", color = orange, markersize=7.5, clip_on=False)
plt.plot(x, sore, "o", label="sore", color = gray, markersize=7.5, clip_on=False)
plt.ylim([0, 25])
plt.xlim([0, 10])
plt.subplots_adjust(left=0.07, right=0.95, bottom=0.2, top=0.85)
#tick
ax.set_yticks([0, 5, 10, 15, 20, 25])
ax.get_xaxis().set_tick_params(pad=10)
ax.get_yaxis().set_tick_params(pad=10)
ax.tick_params(axis='x', colors=text_color, labelsize=12)
ax.tick_params(axis='y', colors=text_color, labelsize=12)
#grid
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['bottom'].set_visible(False)
plt.gca().spines['left'].set_visible(False)
plt.tick_params(bottom=False, left=False, right=False, top=False)
ax.grid(which = "major", axis = "x", color = line_color, linestyle = "-", linewidth = 1.5)
ax.grid(which = "major", axis = "y", color = line_color, linestyle = "-", linewidth = 1.5)
#title
plt.title('Chart Title', fontsize=18, color = text_color, pad=20)
#legend
plt.legend(bbox_to_anchor=(0.485, -0.3), loc='lower center', frameon=False, labelcolor=text_color, fontsize=11, handletextpad=-0.4, ncol=3, columnspacing=0.1)
plt.show()
いい線行っていると思うんですがいかがでしょうか。ここからちょっと解説します。
font
excelのデフォルトのフォントが遊ゴチックみたいなのでYu Gothicを指定しています。うまく反映されていない気もします。
color
マーカーだったり線だったりの色を指定しています。それぞれの値はMacのDigital Color Meterを使って読み取りました。excelの図の黒って少し淡いですよね。測ってみると文字がRGBで[89, 89, 89]、罫線が[217, 217, 217]だったのでそれぞれ指定しています。pyhonのexcelもデフォルトの一本目のプロットが青っぽくて似ている色なんですが、測ってみるとpythonのデフォルトの青が[31, 118, 179]でexcelのデフォルトの青が[254, 117, 0]になっていますので、それも指定しています。そして、pythonのplotのcolorをRGBで指定する際、0から1までの値で指定するのでそれぞれ255で割ることで規格化してます。
plot
clip_on=Falseという指定をしています。これをしないとpythonでは、罫線上の点が切れてしまいます。
tick
pythonの軸の数値はexcelに比べて少し軸に近いです。ax.get_xaxis().set_tick_params(pad=10)の指定で軸からの距離を指定することができます。
grid
まずplt.gca().spines['right'].set_visible(False)で枠線を消します。plt.tick_params(bottom=False, left=False, right=False, top=False)で軸の目盛線も消します。最後にax.grid()で淡いグリッド線を導入します。
title
タイトルも少し近いです。こちらもtickと同様にpadの指定で軸からの距離を指定します。
legend
凡例は位置と間隔の調整が必要です。bbox_to_anchorとlocで位置合わせをしました。あとは間隔ですが、pythonではexcelに比べてかなり広く間隔をとっています。ncol=3で横並びにしたのちにhandletextpadとcolumnspacingで間隔を狭めました。
まとめ
最後にexcelのデフォルトの図とpythonで完コピした図を並ベてみます。どちらがどっちか判別できますか?より完コピできる設定をご存知の方はコメントいただけると幸いです。