Pythonで折れ線グラフを作成する方法【Matplotlib】

Pythonで折れ線グラフを作成する方法【Matplotlib】 プログラミング

次の折れ線グラフは、ウィキペディア(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)
00
13
27
312
420
530
645

リスト型(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」を非表示する方法を考えてください。

x軸の「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軸の数値を小数点で表示するにはどうすればよいでしょうか?

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)の点が半分以上が非表示になっています。
それ以外は、ほぼ完コピできたのではないでしょうか?

タイトルとURLをコピーしました