次の折れ線グラフは、ウィキペディア(Wikipedia)の「折れ線グラフ」にあるモノです。
この記事では、この折れ線グラフと同じものを作成していきます。
以下では、この折れ線グラフを「ゴールの折れ線グラフ」と呼びます。
この記事を読めば、 折れ線グラフを作成できるようになります。
本記事は次の構成で進めていきます。
本記事の内容
- Pythonで折れ線グラフを作成するための環境
- とりあえず、Pythonで折れ線グラフを作成する
- Matplotlibで作成した折れ線グラフを調整する
- Matplotlibで作成したグラフの表示(折れ線以外)を調整する
- Pythonで折れ線グラフを作成する方法のまとめ
Pythonで折れ線グラフを作成するための環境
- Windows 10 Home (バージョン1909)※以下の説明は64bit前提
- Python 3.7.3
- NumPy 1.18.5
- Matplotlib 3.2.1
Pythonの上記ライブラリは、すべてインストールする必要があります。
インストールしていないライブラリは、以下のコマンドでインストールしてください。
pip install numpy pip install matplotlib
Matplotlibを日本語化対応する必要がある場合は、以下の記事をご覧ください。
作成したグラフにおいて、日本語が「□□□」と表示される場合に対応が必要です。
とりあえず、Pythonで折れ線グラフを作成する
「とりあえず」、Pythonで簡単に折れ線グラフを作成します。
モジュールを読み込む
折れ線グラフを作成するために必要なモジュールをimportします。
コードは以下。
import matplotlib.pyplot as plt
データを用意する
ウィキペディア日本語版の記事「折れ線グラフ」ページより。
下記は、「ある物体の速度をいくつかの時点で計測したデータ」の表です。
「ゴールの折れ線グラフ」のデータとなります。
経過時間(秒) | 速度(m/s) |
0 | 0 |
1 | 3 |
2 | 7 |
3 | 12 |
4 | 20 |
5 | 30 |
6 | 45 |
リスト型(list型)のデータを用意します。
14つのデータであるため、そのままコードに書きます。
もっと数の多いデータであれば、ファイルに保存して読み込む形を取ります。
# x軸のデータ:経過時間(秒) x = [0, 1, 2, 3, 4 ,5, 6] # y軸のデータ:経過時間(秒) y = [0, 3, 7, 12, 20 ,30, 45]
折れ線グラフを作成する
折れ線グラフを表示するのは、たったこれだけです。
この1行で最低限のグラフを作成できます。
# 折れ線グラフの描画 plt.plot(x, y)
グラフを画像ファイルに保存する
作成した折れ線グラフを画像ファイルに保存します。
facecolorは、背景色です。
何も指定しなければ、「白」となります。
# グラフを画像保存 plt.savefig("result.png", facecolor="white")
「とりあえず、Pythonで折れ線グラフを作成する」のまとめ
ここまでの処理をまとめると、以下のコードになります。
プログラムコードは、わずか5行です。(コメント除く)
import matplotlib.pyplot as plt # x軸のデータ:経過時間(秒) x = [0, 1, 2, 3, 4 ,5, 6] # y軸のデータ:経過時間(秒) y = [0, 3, 7, 12, 20 ,30, 45] # 折れ線グラフの描画 plt.plot(x, y) # グラフを画像保存 plt.savefig("result.png", facecolor="white")
このプログラムの実行結果が、以下のグラフです。
とりあえず、Pythonで折れ線グラフを作成できました。
簡単に作成できますね。
では、次以降でこの折れ線グラフをゴールの折れ線グラフに近づけていきます。
Matplotlibで作成した折れ線グラフを調整する
ゴールの折れ線グラフに近づけていくために、必要な項目を洗い出しましょう。
- 各点をマーカー「〇」で表示する
- 折れ線の線幅を変更する
- 折れ線の色を変更する
各点をマーカー「〇」で表示する
markerに「o」を設定します。
しかし、これだけではマーカーが白抜きされていません。
マーカーを白抜きにするため、markerfacecolorに「白」を設定します。
# 折れ線グラフの描画 plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF")
マーカーを変更した状態の結果は以下。
折れ線の線幅を変更する
折れ線の線を太くします。
そのためには、plotの引数にlinewidthを追加。
plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF", linewidth=1.2)
マーカーの線幅も同じに統一します。
plotの引数にmarkeredgewidthを追加。
linewidthとmarkeredgewidthには、同じ値を設定します。
plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF", linewidth=1.4, markeredgewidth=1.4)
この状態での結果は以下。
折れ線の色を変更する
plotの引数にcolorを追加。
plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF", linewidth=1.4, markeredgewidth=1.4, color="#4343FF")
この状態での結果は以下。
折れ線グラフの変更は、これで完了です。
次以降では、グラフ全体(折れ線以外)の調整を行っていきます。
Matplotlibで作成したグラフの表示(折れ線以外)を調整する
折れ線だけのことではなく、Matplotlibで作成したグラフすべてに関連する内容となります。
この内容の詳細に関連したことを以下の記事を説明しています。
そのため、本記事では詳しい説明を省きます。
詳細に関しては、上の記事をご覧ください。
それでは、微調整の説明を行っていきます。
画像サイズを合わせる
ゴールの折れ線グラフの画像サイズは、横1024px・縦749pxです。
対応するコードは以下。
# サイズ指定 fig = plt.figure(dpi=100, figsize=(10.24, 7.49))
x軸とy軸のラベルを設定する
ラベルを設定するコードは、以下。
# ラベル設定 plt.xlabel("Time(s)", fontsize=14) plt.ylabel("Speed(m/s)", fontsize=14)
余白を調整する
ゴールの折れ線グラフと同じような余白にします。
# 余白調整 plt.subplots_adjust(left=0.08, right=0.97, bottom=0.1, top=1.0)
x軸とy軸の目盛を設定する
最大値から自動的に最大目盛を決定する処理を書いています。
あくまで、今回のグラフ専用であり、汎用的に使えるわけではありません。
別に固定値でも良かったぐらいです。
# 目盛設定 # x軸の目盛に関する処理 x_scale_num = 1.0 x_max = (math.ceil(max(x) / x_scale_num) + 1 ) * x_scale_num xscale = np.arange(0, x_max, x_scale_num) plt.xlim(0, x_max) plt.xticks(xscale) # y軸の目盛に関する処理 y_scale_num = 10 y_max = (math.ceil(max(y) / y_scale_num) ) * y_scale_num yscale = np.arange(0, y_max, y_scale_num) plt.ylim(0, y_max) plt.yticks(yscale)
ポイントは、範囲と値です。
範囲とは、黄色の部分です。
値とは、赤線の部分です。
plt.xlim(0, x_max)により、x軸の範囲が決定しています。
x_maxの値は、7です。
plt.ylim(0, y_max)により、y軸の範囲が決定しています。
y_maxの値は、50です。
次は、値の説明です。
値とは、目盛の値が正確ですね。
plt.xticks(xscale)により、x軸の目盛が決定しています。
xscaleの値は、[0. 1. 2. 3. 4. 5. 6.]です。
plt.yticks(yscale)により、y軸の目盛が決定しています。
yscaleの値は、[ 0 10 20 30 40]です。
ある程度、考え方が分かったと思います。
では、次の赤線の「0」を非表示する方法を考えてください。
わかりましたか?
簡単ですね。
xscaleの値は、[1. 2. 3. 4. 5. 6.]に変更します。
コードは、次のような変更となります。
xscale = np.arange(0, x_max, x_scale_num)
↓
xscale = np.arange(1, x_max, x_scale_num)
では、もう一つ確認です。
x軸の数値を小数点で表示するにはどうすればよいでしょうか?
どうでしょうか?
xscaleの値を、[1.0 2.0 3.0 4.0 5.0 6.0]とすればよいのでしょうか?
なんと、それが違うのです。
新たなモジュールのimport。
from matplotlib.ticker import FormatStrFormatter
そして、次のコードを追加です。
# 軸関係の表示 ax = fig.add_subplot(111) # x軸の小数点表記 ax.xaxis.set_major_formatter(FormatStrFormatter("%.1f"))
正直、頭の中が「?」だと思います。
xscaleに指定した値は、表示の制御に関してだけです。
出す、出さないをコントロールしているだけということですね。
そして、表示されるモノ自体は、ax.xaxis.set_major_formatterでの制御となります。
グリッド表示
いろいろなコードの書き方が、あります。
試してみて、最も簡単だったのが以下。
ax.grid(b=True, which='major', color='gray', linestyle='-', linewidth=2.5, alpha=0.3) ax.grid(b=True, which='minor', color='gray', linestyle='-', linewidth=0.2, snap =False) ax.minorticks_on()
上と右の枠線を非表示にする
下図の黄色の部分を非表示にします。
対応するコードは以下。
# 上・右の枠線を非表示 plt.gca().spines['right'].set_visible(False) plt.gca().spines['top'].set_visible(False)
Pythonで折れ線グラフを作成する方法のまとめ
まず、ここまでの修正を取り込んだコードを表示します。
import math import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FormatStrFormatter # x軸のデータ:経過時間(秒) x = [0, 1, 2, 3, 4 ,5, 6] # y軸のデータ:経過時間(秒) y = [0, 3, 7, 12, 20 ,30, 45] # サイズ指定 fig = plt.figure(dpi=100, figsize=(10.24, 7.49)) # 軸関係の表示 ax = fig.add_subplot(111) # x軸の小数点表記 ax.xaxis.set_major_formatter(FormatStrFormatter("%.1f")) # ラベル設定 plt.xlabel("Time(s)", fontsize=14) plt.ylabel("Speed(m/s)", fontsize=14) # 目盛設定 # x軸の目盛に関する処理 x_scale_num = 1.0 x_max = (math.ceil(max(x) / x_scale_num) + 1 ) * x_scale_num xscale = np.arange(1, x_max, x_scale_num) xscale = np.round(xscale, 2) plt.xlim(0, x_max) plt.xticks(xscale) # y軸の目盛に関する処理 y_scale_num = 10 y_max = (math.ceil(max(y) / y_scale_num) ) * y_scale_num yscale = np.arange(0, y_max, y_scale_num) plt.ylim(0, y_max) plt.yticks(yscale) # グリッド表示 ax.grid(b=True, which='major', color='gray', linestyle='-', linewidth=2.5, alpha=0.3) ax.grid(b=True, which='minor', color='gray', linestyle='-', linewidth=0.2, snap =False) ax.minorticks_on() # 折れ線グラフの描画 plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF", linewidth=1.4, markeredgewidth=1.4, color="#4343FF") # 上・右の枠線を非表示 plt.gca().spines['right'].set_visible(False) plt.gca().spines['top'].set_visible(False) # 余白調整 plt.subplots_adjust(left=0.08, right=0.97, bottom=0.1, top=1.0) # グラフを画像保存 plt.savefig("result.png", facecolor="white")
この実行結果は以下。
全体的にサイズが足りないです。
文字サイズ、折れ線の幅をもっと大きくする必要がありますね。
それと、x軸・y軸のラベルの表示位置を変更が必要です。
位置を変更するコードは以下。
# x軸ラベル表示位置制御 ax.xaxis.set_label_coords(0.52, -0.1) # y軸ラベル表示位置制御 ax.yaxis.set_label_coords(-0.09, 0.5)
あとは、全体的にサイズを大きく変更します。移動もしています。
それに伴い、最終的に出来上がったコードは以下。
import math import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FormatStrFormatter # x軸のデータ:経過時間(秒) x = [0, 1, 2, 3, 4 ,5, 6] # y軸のデータ:経過時間(秒) y = [0, 3, 7, 12, 20 ,30, 45] # サイズ指定 fig = plt.figure(dpi=100, figsize=(10.24, 7.49)) # 軸関係の表示 ax = fig.add_subplot(111) # x軸の小数点表記 ax.xaxis.set_major_formatter(FormatStrFormatter("%.1f")) # x軸ラベル表示位置制御 ax.xaxis.set_label_coords(0.52, -0.1) # y軸ラベル表示位置制御 ax.yaxis.set_label_coords(-0.09, 0.5) # ラベル設定 plt.xlabel("Time(s)", fontsize=20) plt.ylabel("Speed(m/s)", fontsize=20) # 目盛設定 # x軸の目盛に関する処理 x_scale_num = 1.0 x_max = (math.ceil(max(x) / x_scale_num) + 1 ) * x_scale_num xscale = np.arange(1, x_max, x_scale_num) xscale = np.round(xscale, 2) plt.xlim(0, x_max) plt.xticks(xscale, fontsize=20) # y軸の目盛に関する処理 y_scale_num = 10 y_max = (math.ceil(max(y) / y_scale_num) ) * y_scale_num yscale = np.arange(0, y_max, y_scale_num) plt.ylim(0, y_max) plt.yticks(yscale, fontsize=20) # グリッド表示 ax.grid(b=True, which='major', color='gray', linestyle='-', linewidth=2.5, alpha=0.3) ax.grid(b=True, which='minor', color='gray', linestyle='-', linewidth=0.2, snap =False) ax.minorticks_on() # 折れ線グラフの描画 plt.plot(x, y, marker="o", markerfacecolor="#FFFFFF", linewidth=2.5, markeredgewidth=2.5, color="#4343FF", markersize=14) # 上・右の枠線を非表示 plt.gca().spines['right'].set_visible(False) plt.gca().spines['top'].set_visible(False) # 余白調整 plt.subplots_adjust(left=0.12, right=0.97, bottom=0.13, top=1.0) # グラフを画像保存 plt.savefig("result.png", facecolor="white")
そして、最終的な折れ線グラフは以下
細かいことを言えば、座標(0, 0)の点が半分以上が非表示になっています。
それ以外は、ほぼ完コピできたのではないでしょうか?