#mynavi(Python覚え書き) #setlinebreak(on); * 目次 [#o6e637f2] #contents - 参考 -- https://matplotlib.org/ -- [[Matplotlib が PC で追加のフォントをインストールしなくても日本語を表示できるようになった:https://qiita.com/yniji/items/2f0fbe0a52e3e067c23c]] -- [[早く知っておきたかったmatplotlibの基礎知識、あるいは見た目の調整が捗るArtistの話:https://qiita.com/skotaro/items/08dc0b8c5704c94eafb9]] - 関連 -- [[Python]] -- [[Python覚え書き]] -- [[numpy入門]] -- [[pandas入門]] -- [[Jupyter Notebook]] * 概要 [#ubd317a3] #html(<div style="padding-left:10px">) Pythonのグラフ描画ライブラリ Matplotlib の覚え書き。 #html(</div>) * インストール [#na833a68] #html(<div style="padding-left:10px">) #myterm2(){{ pip install matplotlib }} #html(</div>) * 使い方 [#r8b777f2] #html(<div style="padding-left:10px">) ** 日本語を描画する場合 [#z3d884bf] #html(<div style="padding-left: 10px;">) 日本語が文字化けする場合、フォント一覧から日本語表示可能なフォントを選んで font.family に設定する。 #mycode2(){{ import matplotlib import re [f.name for f in matplotlib.font_manager.fontManager.ttflist if re.match('.*Gothic.*', f.name)] }} 結果 確認結果 #mycode3(){{ ['Apple SD Gothic Neo', 'Franklin Gothic Medium', 'Franklin Gothic Book', 'Hiragino Maru Gothic Pro', 'AppleGothic', 'MS PGothic', 'MS Gothic', 'HGMaruGothicMPRO', 'Franklin Gothic Medium', 'HGGothicE', 'Noto Sans Gothic', 'Franklin Gothic Book'] }} フィントを設定 #mycode2(){{ import matplotlib.pyplot as plt plt.rcParams['font.family'] = 'Hiragino Maru Gothic Pro' }} // plt.rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'Noto Sans CJK JP'] 日本語表示可能なフォントがない場合は、以下のURLよりIPAフォントの「4書体パック」をダウンロード 及び 解凍。 https://ipafont.ipa.go.jp/old/ipafont/download.html 解凍してできた ttf を以下のディレクトリに配置する。 #mycode2(){{ import os import matplotlib print(os.path.join(matplotlib.get_data_path(), "fonts")) }} あとは上記と同じ用に rcParams でフォントを設定するだけ。 設定するフォント名は、先程ダウンロードしたファイルの README に書いてある。 Readme_IPAfont00303.txt #mycode2(){{ : IPA Font (IPA Fonts 4 fonts package) IPAfont00303.zip |--Readme Readme_IPAfont00303.txt |--IPA Font License Agreement v1.0 IPA_Font_License_Agreement_v1.0.txt |--IPAGothic ipag.ttf |--IPAPGothic ipagp.ttf |--IPAMincho ipam.ttf |--IPAPMincho ipamp.ttf : }} うまく表示されない場合はキャッシュを削除して jupyter notebook を再起動。 キャッシュディレクトリの確認 #mycode2(){{ matplotlib.get_cachedir() }} キャッシュの削除 #myterm2(){{ mv ~/.matplotlib ~/.matplotlib_BAK mv ~/.cache/matplotlib ~/.cache/matplotlib_BAK # こっちもかも }} #html(</div>) ** 線グラフの描画 [#zacf5ffd] #html(<div style="padding-left: 10px;">) https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html #mycode2(){{ import matplotlib.pyplot as plt import numpy as np #plt.rcParams['font.family'] = 'Hiragino Maru Gothic Pro' x = np.arange(10) y = x**2 plt.plot(x, y, c="green") plt.xlim(-1, 11) plt.ylim(-10, 100) plt.xlabel("X軸") plt.ylabel("Y軸") plt.show() }} #html(</div>) ** 散布図の描画 [#qde44fee] #html(<div style="padding-left: 10px;">) https://matplotlib.org/api/_as_gen/matplotlib.pyplot.scatter.html #mycode2(){{ import matplotlib.pyplot as plt import numpy as np np.random.seed() x = np.random.uniform(1, 100, 20) y = x + np.random.uniform(-10, 10, x.shape[0]) plt.scatter(x, y, c="red", marker="x") plt.ylim(-20,120) plt.xlim(-20,120) plt.show() }} #html(</div>) ** ヒストグラムの描画 [#k14c4a4d] #html(<div style="padding-left: 10px;">) https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html #mycode2(){{ import matplotlib.pyplot as plt x = np.array([42, 32, 44, 43, 36, 14, 22, 35, 45]) plt.hist(x, range=[0, 50], bins=10) plt.grid(True) plt.show() }} *** ヒストグラムの正規化 [#u0d1dcdb] #html(<div style="padding-left: 10px;">) %%normed=1%% density=True を指定するとヒストグラムが正規化される。(binの面積の合計は1.0となる) // μ = 0, σ2 = 1 である標準正規分布(1次元)のグラフを描いてみる。 #mycode2(){{ bins_num = 10 # 階級の数 data_num = 1000 normal_data = np.random.normal(0, 1.0, data_num) plt.hist(normal_data, bins=bins_num, density=True) plt.grid(True) plt.show() }} //# y軸のメモリを再計算() //ax.yaxis.set_ticklabels(["{:0.2f}".format(i / (sum(hist_values) / data_num)) for i in ax.yaxis.get_ticklocs()]) 目盛りを密度(パーセンテージ)で描画したい場合は、weight を調整するか、目盛りを再計算する。 #mycode2(){{ hist_weight = np.zeros(len(normal_data)) + 1 / len(normal_data) * 100 plt.hist(normal_data, bins=bins_num, weights=hist_weight) }} #html(</div>) #html(</div>) ** 目盛りの設定 [#q7ebc060] #html(<div style="padding-left: 10px;">) xticks または yticks で目盛りラベルを設定する事ができる。 ※figureの場合は set_xticks または set_yticks。 #mycode2(){{ bins_num = 10 data_num = 1000 normal_data = np.random.normal(0, 1.0, data_num) plt.hist(normal_data, bins=bins_num, density=True) plt.yticks([0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) # Y軸メモリを設定 plt.grid(True) plt.show() }} #html(</div>) ** グリッドの描画 [#od6e450a] #html(<div style="padding-left: 10px;">) #mycode2(){{ plt.grid(True) }} #html(</div>) ** グラフを重ねる [#if40bf38] #html(<div style="padding-left: 10px;">) 複数回 plot する事で、複数のグラフを描画する事ができる。 また、plot 時に label を指定しつつ、plt.legend を呼ぶことで凡例を表示する事ができる。 #mycode2(){{ data1 = np.random.normal(0, 1.0, 100) data2 = np.random.normal(0, 1.0, 100) plt.plot(data1, label="data1") plt.plot(data2, label="data2") plt.legend() plt.grid(True) plt.show() }} #html(</div>) ** 凡例の設定 [#he6c19ec] #html(<div style="padding-left: 10px;">) https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html #mycode2(){{ # フォントサイズ plt.legend(fontsize=10) # 影付き plt.legend(shadow=True) # 凡例の位置を指定 plt.legend(loc='upper right') #plt.legend(loc='lower left') # 図に対する相対的な位置指定 plt.legend(bbox_to_anchor=(1, 1)) }} #html(</div>) ** 線の設定 [#p609ce4d] #html(<div style="padding-left: 10px;">) #TODO #html(</div>) ** 任意の位置に線を引く [#hd97127f] #html(<div style="padding-left: 10px;">) #TODO #html(</div>) ** 任意の位置に文字を書く [#db59fdb4] #html(<div style="padding-left: 10px;">) #TODO #html(</div>) ** 領域を分割して複数のグラフを描く [#ia539f4d] #html(<div style="padding-left: 10px;">) #mycode2(){{ from matplotlib import pyplot as plt data = [20, 37, 41, 25, 31, 28, 32, 44, 29, 23] # 日本語フォントを利用可能にしておく plt.rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'Noto Sans CJK JP'] fig = plt.figure(figsize=(15, 5)) # グラフ1 ax1 = fig.add_subplot(1, 2, 1) ax1.plot(data, color="#ef1234") ax1.set_title("線グラフ") # グラフ2 ax2 = fig.add_subplot(1, 2, 2) ax2.hist(data, bins=15) ax2.set_title("ヒストグラム") plt.show() }} #html(</div>) #html(</div>) // 使い方 END * サンプル [#hf0becef] #html(<div style="padding-left: 10px">) サーバーのロードアベレージの時系列データをグラフ描画してみる。 サンプルデータ &ref(sample_loadaverage.csv); sample.py #mycode2(){{ import io import numpy as np import pandas as pd from matplotlib import pyplot as plt import base64 def main(): df = pd.read_csv("sample_loadaverage.csv") # 日本語フォントを利用可能にしておく plt.rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'Noto Sans CJK JP'] plt.title("2019-08-01", size = 10, color = "black") plt.suptitle("Load Average", size = 12, color = "black") plt.xticks(np.arange(0, 144, 6), np.arange(0, 24)) plt.xlabel("時刻") plt.ylabel("ロードアベレージ") plt.plot(df["datetime"], df["load-average01"]) # そのまま描画(jupyter notebook 等の場合) plt.show() # ファイルに出力 plt.savefig("sample_loadaverage.png") # 画像データを取得 buff = io.BytesIO() plt.savefig(buff, format="png") plt.close() # 画像データをbase64エンコードしてHTMLに出力. with open("sample_loadaverage.html", "w") as f: encoded_image = base64.b64encode(buff.getvalue()).decode("utf-8") f.write("<!doctype html>") f.write("<html>") f.write("<meta charset='utf-8'>") f.write("<img src='data:image/png;base64," + encoded_image + "' />") f.write("</html>") if __name__ == "__main__": main() }} ** 結果 [#o8edbe1f] &ref(sample_loadaverage.png,nolink); #html(</div>)