Matplotlib で任意の多角形や領域を描画する場合、関数 plt.fill() を使うと簡単です。なお、matplotlib には matplotlib.patches.Polygon という高機能なライブラリがあり、これを使うといろいろな図形を描画することができます。本ページでは plt.fill() を説明します。
plt.fill(x, y)
x, y 座標のリストを渡すだけで、簡単に多角形を塗りつぶすことができます。
リスト : 多角形の描画 (1) import numpy as np import matplotlib.pyplot as plt x = [1, 6, 11, 8.5, 3.5] y = [10, 15, 10, 2, 2] plt.fill(x, y) plt.ylim(0, 16) plt.show()
五角形
リスト : 多角形の描画 (2)
import numpy as np
import matplotlib.pyplot as plt
x1 = [2, 4, 4, 2]
y1 = [15, 15, 1, 1]
x2 = [4, 6, 6, 4]
y2 = [15, 15, 1, 1]
x3 = [6, 8, 8, 6]
y3 = [15, 15, 1, 1]
x4 = [8, 10, 10, 8]
y4 = [15, 15, 1, 1]
for x, y in [(x1, y1), (x2, y2), (x3, y3), (x4, y4)]:
plt.fill(x, y)
plt.xlim(0, 12)
plt.ylim(0, 16)
plt.show()
四角形
リスト : 多角形の描画 (3)
import numpy as np
import matplotlib.pyplot as plt
x1 = [2, 4, 4, 2]
y1 = [15, 15, 1, 1]
x2 = [4, 6, 6, 4]
y2 = [15, 15, 1, 1]
x3 = [6, 8, 8, 6]
y3 = [15, 15, 1, 1]
x4 = [8, 10, 10, 8]
y4 = [15, 15, 1, 1]
x5 = [1, 6, 11, 8.5, 3.5]
y5 = [10, 15, 10, 2, 2]
for x, y in [(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x5, y5)]:
plt.fill(x, y, alpha = 0.3)
plt.xlim(0, 12)
plt.ylim(0, 16)
plt.show()
重ね合わせ
データを正多角形の上に図示したものを「レーダーチャート (radar chart)」といいます。Matplotlib の場合、レーダーチャートを描画する専用の関数は用意されていませんが、極座標グラフを利用してデータと角度を自分で計算すれば、レーダーチャートを描画することができます。
リスト : レーダーチャート
import numpy as np
import matplotlib.pyplot as plt
labels = list('ABCDE')
values = [7, 10, 7, 10, 5]
# 多角形を閉じるため、データの最後に最初の値を追加する
radar_values = values + [values[0]]
angles = np.linspace(0, 2 * np.pi, len(labels) + 1)
fig, ax = plt.subplots(subplot_kw=dict(polar=True))
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
# 線の描画と内側の塗りつぶし
ax.plot(angles, radar_values, color='blue', linewidth=2, linestyle='solid')
ax.fill(angles, radar_values, color='blue', alpha=0.25)
ax.set_thetagrids(angles[:-1] * 180 / np.pi, labels) # 角度を度数法に変換してラベル配置
ax.set_ylim(0, 12) # 目盛りの範囲を設定
ax.set_title('Radar chart')
plt.show()
レーダーチャート
リスト : レーダーチャート (重ね合わせ)
import numpy as np
import matplotlib.pyplot as plt
labels = list('ABCDE')
values1 = [7, 10, 7, 10, 5]
values2 = [8, 7, 10, 4, 10]
# 多角形を閉じるため、データの最後に最初の値を追加する
radar_values1 = values1 + [values1[0]]
radar_values2 = values2 + [values2[0]]
angles = np.linspace(0, 2 * np.pi, len(labels) + 1)
fig, ax = plt.subplots(subplot_kw=dict(polar=True))
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
# 線の描画と内側の塗りつぶし
ax.plot(angles, radar_values1, color='blue', linewidth=2, linestyle='solid')
ax.fill(angles, radar_values1, color='blue', alpha=0.25)
ax.plot(angles, radar_values2, color='red', linewidth=2, linestyle='solid')
ax.fill(angles, radar_values2, color='red', alpha=0.25)
ax.set_thetagrids(angles[:-1] * 180 / np.pi, labels) # 角度を度数法に変換してラベル配置
ax.set_ylim(0, 12) # 目盛りの範囲を設定
ax.set_title('Radar chart')
plt.show()
重ね合わせ
Matplotlib で塗りつぶしを行うには次の関数を使用します。
本ページでは fill_between() を説明します。この関数は、基準となる x と、上限 y1、下限 y2 を指定します。y2 を省略すると自動的に y=0 (X 軸) との間が塗られます。where=条件式 を指定すると、y1 と y2 が条件式を満たす領域を塗りつぶします。たとえば、y1 > y2 とすれば、y1 が y2 よりも大きい領域が塗りつぶされます。
リスト : 塗りつぶし (1) import numpy as np import matplotlib.pyplot as plt x = np.linspace(-2, 2, 100) y2 = x ** 3 - 9 * x y3 = x ** 4 - 10 * x ** 2 + 9 plt.plot(x, y2, label = 'x**3 - 9x') plt.plot(x, y3, label = 'x**4 - 10x + 9') plt.fill_between(x, y2, alpha=0.4) plt.fill_between(x, y3, -15, alpha=0.4) plt.legend() plt.show()
塗りつぶし (1)
リスト : 塗りつぶし (2) import numpy as np import matplotlib.pyplot as plt x = np.linspace(-2, 2, 100) y2 = x ** 3 - 9 * x y3 = x ** 4 - 10 * x ** 2 + 9 plt.plot(x, y2, label = 'x**3 - 9x') plt.plot(x, y3, label = 'x**4 - 10x + 9') plt.fill_between(x, y2, y3, alpha=0.4) plt.legend() plt.show()
塗りつぶし (2)
リスト : 塗りつぶし (3) import numpy as np import matplotlib.pyplot as plt x = np.linspace(-2, 2, 100) y2 = x ** 3 - 9 * x y3 = x ** 4 - 10 * x ** 2 + 9 plt.plot(x, y2, label = 'x**3 - 9x') plt.plot(x, y3, label = 'x**4 - 10x + 9') plt.fill_between(x, y2, y3, where=(y2 < y3), alpha=0.4) plt.legend() plt.show()
塗りつぶし (3)
Python の Pandas には、内部で Matplotlib をラップした便利な描画メソッド .plot() が用意されています。データフレーム (DataFrame) やシリーズ (Series) から、簡単にグラフを作成することができます。Pandas でグラフを描画する場合、大きく分けて 2 つの記述方法があります。
Pandas で描画できる主なグラフを以下に示します。
種類 kind メソッド 主な用途・特徴
-----------------------------------------------------------------------------------------------
折れ線グラフ 'line' .plot.line() デフォルト。時系列データや変化の推移を見る。
垂直棒グラフ 'bar' .plot.bar() 項目ごとの大小や数量を比較する。
水平棒グラフ 'barh' .plot.barh() 項目名が長い場合の数量比較に便利。
ヒストグラム 'hist' .plot.hist() データの分布やバラつき、頻度を確認する。
箱ひげ図 'box' .plot.box() データの最小値・中央値・四分位数などの統計的分布。
散布図 'scatter' .plot.scatter() 2 変数間の相関関係を調べる (DataFrameのみ)。
エリアチャート 'area' .plot.area() データの累積や推移の合計量を視覚化する。
円グラフ 'pie' .plot.pie() 全体に占める各項目の割合(シェア)を示す。
カーネル密度推定 'kde' .plot.kde() 滑らかな曲線でデータの確率密度を表す。
'density'
よく使う主要なオプションを以下に示します。
簡単な使用例を示します。
リスト : 折れ線グラフ
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 東京の平均気温
df = pd.DataFrame({
'avg': [7.1, 8.0, 9.6, 17.1, 20.0, 23.1, 28.7, 29.0, 26.6, 20.6, 13.7, 8.1],
'max': [11.8, 12.5, 14.8, 21.8, 24.8, 27.7, 33.5, 33.6, 30.9, 24.5, 17.8, 13.2],
'min': [2.9, 4.1, 5.1, 13.1, 15.6, 19.3, 25.0, 25.7, 23.5, 17.4, 10.2, 3.8]
}, index = range(1, 13))
df.plot(kind='line',
title='Average temperature in 2024',
marker='o', ls='-')
plt.show()
折れ線グラフ
リスト : ヒストグラム
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 身長
df = pd.DataFrame({
'Height': [
148.7, 149.5, 133.7, 157.9, 154.2, 147.8, 154.6, 159.1, 148.2, 153.1,
138.2, 138.7, 143.5, 153.2, 150.2, 157.3, 145.1, 157.2, 152.3, 148.3,
152.0, 146.0, 151.5, 139.4, 158.8, 147.6, 144.0, 145.8, 155.4, 155.5,
153.6, 138.5, 147.1, 149.6, 160.9, 148.9, 157.5, 155.1, 138.9, 153.0,
153.9, 150.9, 144.4, 160.3, 153.4, 163.0, 150.9, 153.3, 146.6, 153.3,
152.3, 153.3, 142.8, 149.0, 149.4, 156.5, 141.7, 146.2, 151.0, 156.5,
150.8, 141.0, 149.0, 163.2, 144.1, 147.1, 167.9, 155.3, 142.9, 148.7,
164.8, 154.1, 150.4, 154.2, 161.4, 155.0, 146.8, 154.2, 152.7, 149.7,
151.5, 154.5, 156.8, 150.3, 143.2, 149.5, 145.6, 140.4, 136.5, 146.9,
158.9, 144.4, 148.1, 155.5, 152.4, 153.3, 142.3, 155.3, 153.1, 152.3
]
})
df.plot(kind='hist', title='Frequency')
plt.show()
ヒストグラム
リスト : 散布図 (1)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# from datetime import datetime
df = pd.DataFrame({
'year': range(1975, 2022),
'temp': [
15.6, 15.0, 15.8, 16.1, 16.9, 15.4, 15.0, 16.0, 15.7, 14.9,
15.7, 15.2, 16.3, 15.4, 16.4, 17.0, 16.4, 16.0, 15.5, 16.9,
16.3, 15.8, 16.7, 16.7, 17.0, 16.9, 16.5, 16.7, 16.0, 17.3,
16.2, 16.4, 17.0, 16.4, 16.7, 16.9, 16.5, 16.3, 17.1, 16.6,
16.4, 16.4, 15.8, 16.8, 16.5, 16.5, 16.6
]
})
df.plot(kind = 'scatter',
x = 'year', y = 'temp', ylim = (14, 18),
title = 'Annual Average Temperature in Tokyo')
plt.show()
散布図 (1)
リスト : 散布図 (2)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 強い正の相関
data1 = [
[4.6, 5.5], [0.0, 1.7], [6.4, 7.2], [6.5, 8.3],
[4.4, 5.7], [1.1, 1.1], [2.8, 4.1], [5.1, 6.7],
[3.4, 5.0], [5.8, 6.6], [5.7, 6.3], [5.5, 5.6],
[7.9, 8.7], [3.0, 3.6], [6.8, 8.2], [6.2, 6.2],
[4.0, 5.0], [8.6, 9.5], [7.5, 8.9], [1.3, 2.6],
[6.3, 7.4], [3.1, 5.0], [6.1, 8.2], [5.3, 6.6],
[3.9, 5.1], [5.8, 7.0], [2.6, 3.5], [4.8, 6.3],
[2.2, 2.9], [5.3, 6.9]
]
# 強い負の相関
data2 = [
[6.1, 3.7], [3.9, 7.5], [8.6, 1.7], [5.9, 3.9],
[3.5, 5.5], [7.0, 2.4], [0.9, 9.8], [0.0, 10.2],
[5.2, 4.2], [3.5, 6.5], [6.9, 3.2], [4.3, 5.9],
[5.0, 5.9], [7.4, 3.3], [3.1, 6.6], [4.0, 6.2],
[6.9, 2.9], [4.8, 5.0], [10.6, 0.0], [4.7, 4.3],
[2.9, 7.6], [7.2, 2.2], [3.6, 6.0], [5.5, 4.3],
[5.5, 4.5], [6.9, 3.2], [5.8, 3.6], [4.8, 4.6],
[7.3, 2.5], [4.7, 5.4]
]
df = pd.DataFrame({
'x1': [x[0] for x in data1],
'y1': [x[1] for x in data1],
'x2': [x[0] for x in data2],
'y2': [x[1] for x in data2]
})
# グラフを重ね合わせる場合は、
# df.plot() の返り値を受け取り、
# それを引数 ax に渡す
ax = df.plot(kind='scatter', x='x1', y='y1')
df.plot(kind='scatter', x='x2', y='y2', c='red', ax=ax)
plt.title('Simple Scatter Plot')
plt.show()
散布図 (2)
積み上げ面グラフ (Stacked Area Chart) は、折れ線グラフの各線の下側を色付けし、それらを上に積み上げた形式のグラフです。時系列などの変化に沿って、全体の合計値の変化と、各カテゴリーが占める割合 (内訳) の両方を一目で確認することができます。
Matplotlib で積み上げ面グラフを描画するには関数 plt.stackplot() を使います。
plt.stackplot(x, y1, y2, ...)
引数 x は x 軸の値を格納した配列、引数 y1, ... は積み上げる y 軸のデータです。[y1, y2, ...] のようにリストにまとめて渡してもかまいません。
リスト : 積み上げ面グラフ
import numpy as np
import matplotlib.pyplot as plt
# データの準備
x = range(1, 7)
y = [[1, 7, 4, 5, 2, 3], [2, 8, 5, 2, 6, 5], [3, 9, 6, 1, 8, 7]]
# labels で凡例の名前を指定
plt.stackplot(x, y, labels = ['Group A', 'Group B', 'Group C'], alpha = 0.5)
plt.title('Stacked Area Chart Example')
plt.legend()
plt.show()
リスト : 積み上げ面グラフ (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
# データの準備
x = range(1, 7)
y = [[1, 7, 4, 5, 2, 3], [2, 8, 5, 2, 6, 5], [3, 9, 6, 1, 8, 7]]
fig, ax = plt.subplots()
# labels で凡例の名前を指定
ax.stackplot(x, y, labels = ['Group A', 'Group B', 'Group C'], alpha = 0.5)
ax.set_title('Stacked Area Chart Example')
ax.legend()
plt.show()
積み上げ面グラフ
Pandas の DataFrame を使うともっと簡単です。DataFrame のメソッド plot.area() はデフォルトで積み上げになります。
リスト : Pandas の DataFrame を使う場合
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# データの準備
data = {
'Group A': [1, 7, 4, 5, 2, 3],
'Group B': [2, 8, 5, 2, 6, 5],
'Group C': [3, 9, 6, 1, 8, 7]
}
df = pd.DataFrame(data, index = range(1, 7))
df.plot.area(alpha=0.5)
plt.title('Stacked Area Chart Example')
plt.show()
図は同じなので省略します。
グループ化棒グラフ (集合棒グラフ) は、複数の項目(系列)を一つのカテゴリごとに横に並べて比較するためのグラフです。たとえば、年度ごとの売上を商品 A, B, C のグループで比較する場合などに使われます。グループ化棒グラフは Pandas の DataFrame を使うと簡単に描画することができます。
簡単な例を示しましょう。次の表を見てください。
: A B C
-----+----------
2010 : 10 20 10
2015 : 15 15 15
2020 : 20 15 15
2025 : 25 10 20
上表は、とある会社の主力商品 A, B, C の年度ごとの売上高だとしましょう。これを DataFrame に変換する場合、列名を A, B, C とし、行名 (index) を 2010, 2015, 2020, 2025 とします。あとは、DataFrame のメソッド plot() を呼び出すだけです。このとき、引数 kind='bar' を指定します。プログラムは次のようになります。
リスト : グループ化棒グラフ (1)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
year = ['2010', '2015', '2020', '2025']
data = {
'A': [10, 15, 20, 25],
'B': [20, 15, 15, 10],
'C': [10, 15, 15, 20]
}
df = pd.DataFrame(data, index = year)
df.plot(kind="bar", width=0.8, rot=0)
plt.title('Grouped bar chart')
plt.show()
グループ化棒グラフ
デフォルトでは X 軸のラベルが斜めや縦になってしまうため、rot=0 を指定して水平にします。また、1 つのグループが占める全体の幅を width で調整することができます (デフォルトは 0.5)。値を大きくすると棒が太くなり、間隔が狭くなります。
積み上げ棒グラフとは、同じ項目内のデータを上に積み上げたグラフのことです。次の表を見てください。
: A B C
-----+----------
2010 : 10 20 10
2015 : 15 15 15
2020 : 20 15 15
2025 : 25 10 20
上表はグループ化棒グラフと同じデータです。単純な棒グラフの場合、個々の商品の売上高の推移はわかりますが、A, B, C の合計値は明確ではありません。これを積み上げ棒グラフで表す場合、Matplotlib では関数 bar() の引数 bottom を指定する方法と、DataFrame のメソッド plot(kind='bar') の引数 stacked に True を指定する方法の二通りがあります。
関数 bar() を使う場合、2 つ目以降のデータを描画する際に、bottom にそれまでに積み上がったデータの合計値 (下端の高さ) を指定します。プログラムは次のようになります。
リスト : 積み上げ棒グラフ
import matplotlib.pyplot as plt
import numpy as np
x = ['2010', '2015', '2020', '2025']
data_a = np.array([10, 15, 20, 25])
data_b = np.array([20, 15, 15, 10])
data_c = np.array([10, 15, 15, 20])
plt.bar(x, data_a, label='A')
plt.bar(x, data_b, bottom=data_a, label='B')
plt.bar(x, data_c, bottom=data_a + data_b, label='C')
plt.title('Stacked bar chart')
plt.legend()
plt.show()
積み上げ棒グラフ
リスト : 積み上げ棒グラフ (DataFrame 版)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
year = ['2010', '2015', '2020', '2025']
data = {
'A': [10, 15, 20, 25],
'B': [20, 15, 15, 10],
'C': [10, 15, 15, 20]
}
df = pd.DataFrame(data, index = year)
df.plot(kind="bar", stacked=True, rot=0, width=0.8)
plt.title('Stacked bar chart')
plt.show()
図は同じなので省略します。合計値でみると、売上高は右肩上がりであることが一目でわかります。
DataFrame のメソッド df.plot.hist() を使うと、グループ分けされたヒストグラムを簡単に作成することができます。
df.plot.hist(bins=数値, ...)
簡単なサンプルプログラムを示します。
リスト : グループ化ヒストグラム
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.DataFrame({
'A': np.random.randn(200),
'B': np.random.randn(200) + 2
})
df.plot.hist(bins=20, alpha=0.4)
plt.title('Grouped histogram')
plt.show()
グループ化ヒストグラム
stacked=True を指定すると積み上げヒストグラムになります。
階段グラフ (ステップチャート, Step Line Chart) は、データの値が変化するまで、前の値を水平に維持するグラフです。Matplotlib で階段グラフを描画するには関数 plt.step() を使います。
plt.step(x, y, where='style')
ステップチャートでは、「データ点の間で、どのタイミングで値を変化 (ステップアップ / ダウン) させるか」が重要です。where 引数を使って以下の 3 つのスタイルから選択します。
階段グラフでも、通常のプロットと同様のカスタマイズ (たとえば太さ lw = 2 や色 color = 'red' など) が可能です。また、マーカー marker = 'o' を追加すると、実際のデータポイントがどこにあるか分かりやすくなります。
リスト : 階段グラフ
import numpy as np
import matplotlib.pyplot as plt
x = range(1, 11)
y = np.array([2, 3, 5, 4, 6, 8, 7, 9, 10, 8])
plt.step(x, y, where='pre', label='pre', color='blue', marker='o')
plt.step(x, y + 5, where='post', label='post', color='green', marker='o')
plt.step(x, y + 10, where='mid', label='mid', color='red', marker='o')
plt.legend()
plt.title('Step Chart')
plt.show()
リスト : 階段グラフ (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
x = range(1, 11)
y = np.array([2, 3, 5, 4, 6, 8, 7, 9, 10, 8])
fig, ax = plt.subplots()
ax.step(x, y, where='pre', label='pre', color='blue', marker='o')
ax.step(x, y + 5, where='post', label='post', color='green', marker='o')
ax.step(x, y + 10, where='mid', label='mid', color='red', marker='o')
ax.legend()
ax.set_title('Step Chart')
plt.show()
ステップチャート
ヒートマップ (heatmap) は、数値データの大小を色の濃淡や色相で表現し、データの分布や強弱を一目で把握できるようにしたグラフです。Matplotlib でヒートマップを作成する場合、主に plt.imshow() または plt.pcolormesh() のいずれかを使用します。最もシンプルかつ描画が高速なのは、画像をプロットする関数である plt.imshow() を応用する方法です。
plt.imshow(data, cmap='viridis', interpolation='nearest')
行列 data を渡すと、値の大きさを色の濃淡で表現してくれます。cmap (カラーマップ)は、数値の大きさをどのような「色のグラデーション」で表現するかを指定するパラメータです。viridis, coolwarm, plasma, inferno, Blues などがあります。viridis は Matplotlib の標準的なカラーマップです。interpolation は境界線のぼかしを設定します。デフォルトでは滑らかに補間されてしまうため、格子状のヒートマップにするには 'nearest' を指定します。
colorbar(カラーバー)は、ヒートマップの色が「具体的にどの数値に対応しているか」を示す凡例 (スケール) です。Matplotlib の場合、MATLAB スタイルでは plt.colorbar() を使用し、oo-style では fig.colorbar() を使用して追加します。colorbar() は第 1 引数に imshow() の返り値を受け取りますが、plt.colorbar() の場合は省略しても動作します。
リスト : ヒートマップ (1)
import matplotlib.pyplot as plt
import numpy as np
# サンプルデータの作成
data = np.random.rand(20, 20)
# ヒートマップの描画
# interpolation='nearest' でぼかしを無くし、格子の形をはっきりさせる
plt.imshow(data, cmap='viridis', interpolation='nearest')
# カラーバーと各種ラベルの設定
plt.colorbar(label='Value Scale')
plt.title('Basic Heatmap using Matplotlib')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
リスト : ヒートマップ (オブジェクト指向スタイル)
import matplotlib.pyplot as plt
import numpy as np
# サンプルデータの作成
data = np.random.rand(20, 20)
fig, ax = plt.subplots()
# ヒートマップの描画
im = ax.imshow(data, cmap='viridis', interpolation='nearest')
# カラーバーと各種ラベルの設定
fig.colorbar(im, label='Value Scale') # fig のメソッド colorbar() を呼び出す
# 第 1 引数に ax.imshow() の返り値を渡す
ax.set_title('Basic Heatmap using Matplotlib')
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
# 表示
plt.show()
ヒートマップ (1)
関数の値 (2 変数関数 z = f(x, y) の結果など) をヒートマップで表示する場合、格子状の座標データ (メッシュ) を作成し、それを関数に代入して値を出力するという手順を踏みます。この場合、先ほど紹介した imshow() よりも、座標 (x, y) を正確に指定できる plt.pcolormesh() を使うのがおすすめです。座標データの作成は、NumPy の関数 meshgrid() を使うと簡単です。説明は拙作のページ NumPy 超入門: meshgrid をお読みくださいませ。
リスト : ヒートマップ (2)
import numpy as np
import matplotlib.pyplot as plt
# X軸、Y軸の範囲を定義
x = np.linspace(-5, 5, 200)
y = np.linspace(-10, 10, 200)
# 2 次元の格子点を作成
xs, ys = np.meshgrid(x, y)
# 表示したい「関数」を定義して計算
zs = np.sqrt(xs ** 2 + ys ** 2)
# ヒートマップの描画
# shading='auto' を指定すると境界が綺麗に描画される
mesh = plt.pcolormesh(xs, ys, zs, cmap='inferno', shading='auto')
# 装飾
plt.colorbar(mesh, label='Function Value (Z)')
plt.title('Heatmap of z = sqrt(x ** 2 + y ** 2)')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()
リスト : ヒートマップ (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
# X軸、Y軸の範囲を定義
x = np.linspace(-5, 5, 200)
y = np.linspace(-10, 10, 200)
# 2 次元の格子点を作成
xs, ys = np.meshgrid(x, y)
# 表示したい「関数」を定義して計算
zs = np.sqrt(xs ** 2 + ys ** 2)
fig, ax = plt.subplots()
# ヒートマップの描画
# shading='auto' を指定すると境界が綺麗に描画される
mesh = ax.pcolormesh(xs, ys, zs, cmap='inferno', shading='auto')
# 装飾
fig.colorbar(mesh, label='Function Value (Z)')
ax.set_title('Heatmap of z = sqrt(x ** 2 + y ** 2)')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
plt.show()
ヒートマップ (2)
2 次元ヒストグラム (2D Histogram) とは、2 つの数値データの分布 (相関) をヒートマップのような「格子状の区切り」と「色の濃淡」で表現するグラフです。通常のヒストグラムが 1 つのデータのばらつきを見るのに対し、2 次元ヒストグラムは「x 軸と y 軸の組み合わせがどのエリアに集中しているか」を視覚化するのに適しています。
Matplotlib で 2 次元ヒストグラムを描画するには、関数 hist2d(x, y) を使用するのが一般的です。2 つの配列 (x と y) を渡すだけで、データの密度を色で表現したヒストグラムが作成されます。主なオプションを以下にに示します。
hist2d() を実行すると、グラフが描画されるだけでなく、計算された統計データが返されます。
counts, xedges, yedges, im = ax.hist2d(x, y)
簡単な例を示しましょう。
リスト : 2 次元ヒストグラム
import numpy as np
import matplotlib.pyplot as plt
# サンプルデータの作成
np.random.seed(42)
x = np.random.randn(10000)
y = np.random.randn(10000)
# 2次元ヒストグラムの描画
plt.hist2d(x, y, bins=20, cmap='viridis', cmin=1)
# カラーバーの追加と表示
plt.colorbar(label='Counts')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('2D Histogram Example')
plt.show()
リスト : 2 次元ヒストグラム (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
# サンプルデータの作成
np.random.seed(42)
x = np.random.randn(10000)
y = np.random.randn(10000)
fig, ax = plt.subplots()
# 2次元ヒストグラムの描画
_, _, _, im = ax.hist2d(x, y, bins=20, cmap='viridis', cmin=1)
# カラーバーの追加と表示
fig.colorbar(im, label='Counts')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_title('2D Histogram Example')
plt.show()
2D ヒストグラム
Matplotlib を使用して等高線図を描くには、主に関数 contour() または関数 contourf() を使用します。contour() は線のみ、contourf() は塗りつぶしを行います。基本的な使い方はヒートマップ (2) で使用した pcolormesh() と同じです。
リスト : 等高線図 (1)
import numpy as np
import matplotlib.pyplot as plt
# データの準備 (x, y の範囲を決めて格子点を作成)
x = np.linspace(-6, 6, 100)
y = np.linspace(0, 12, 100)
xs, ys = np.meshgrid(x, y)
# 高さ (z 軸) の関数を定義
zs = np.sin(xs) + np.cos(ys)
c = plt.contour(xs, ys, zs)
plt.colorbar(c, label='Function Value (z)')
plt.title('Contour of z = sin(x) + cos(y)')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()
リスト : 等高線図 (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
# データの準備 (x, y の範囲を決めて格子点を作成)
x = np.linspace(-6, 6, 100)
y = np.linspace(0, 12, 100)
xs, ys = np.meshgrid(x, y)
# 高さ(Z 軸) の関数を定義
zs = np.sin(xs) + np.cos(ys)
fig, ax = plt.subplots()
c = ax.contour(xs, ys, zs)
fig.colorbar(c, label='Function Value (z)')
ax.set_title('Contour of z = sin(x) + cos(y)')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
plt.show()
等高線図 (1)
リスト : 等高線図 (2)
import numpy as np
import matplotlib.pyplot as plt
# データの準備 (x, y の範囲を決めて格子点を作成)
x = np.linspace(-6, 6, 100)
y = np.linspace(0, 12, 100)
xs, ys = np.meshgrid(x, y)
# 高さ (z 軸) の関数を定義
zs = np.sin(xs) + np.cos(ys)
c = plt.contourf(xs, ys, zs)
plt.colorbar(c, label='Function Value (z)')
plt.title('Contourf of z = sin(x) + cos(y)')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()
リスト : 等高線図 (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
# データの準備(x, yの範囲を決めて格子点を作成)
x = np.linspace(-6, 6, 100)
y = np.linspace(0, 12, 100)
xs, ys = np.meshgrid(x, y)
# 高さ(Z軸)の関数を定義(例:数式から計算)
zs = np.sin(xs) + np.cos(ys)
fig, ax = plt.subplots()
c = ax.contourf(xs, ys, zs)
fig.colorbar(c, label='Function Value (z)')
ax.set_title('Contourf of z = sin(x) + cos(y)')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
plt.show()
等高線図 (2)
主な属性を以下に示します。
c = plt.contour(xs, ys, zs, levels=5) plt.clabel(c, inline=True, fontsize=10, fmt='%.1f') # 小数点第1位まで表示
リスト : 等高線図 (2)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
xs, ys = np.meshgrid(x, y)
zs = xs ** 2 + ys ** 2
c = plt.contour(xs, ys, zs)
plt.clabel(c, inline=True, fontsize=10)
plt.colorbar(c, label='Function Value (z)')
plt.title('Contour of z = x ** 2 + y ** 2')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()
リスト : 等高線図 (オブジェクト指向スタイル)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
xs, ys = np.meshgrid(x, y)
zs = xs ** 2 + ys ** 2
fig, ax = plt.subplots()
c = ax.contour(xs, ys, zs)
ax.clabel(c, inline=True, fontsize=10)
fig.colorbar(c, label='Function Value (z)')
ax.set_title('Contour of z = x ** 2 + y ** 2')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
plt.show()
等高線図 (2)
もしも、円が歪んで楕円になる場合、MATLAB スタイルでは plt.gca().set_aspect('equal') を、oo-style では ax.set_aspect('equal') を追加します。これで x 軸と y 軸の単位長さが等しくなります。
Matplotlib で 3 次元のグラフを描画する場合、サブプロットを呼び出すとき projection='3d' を指定して 3 次元用の座標軸 (Axes) を作成します。具体的には次のようプログラムします。
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
または
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
3 次元折れ線グラフ (3D Line Plot) を描画するには、メソッド ax.plot() に 3 つの引数 x, y, z を渡します。3 次元の散布図はメソッド ax.scatter(x, y, z) を使うと簡単です。引数 x, y, z は各座標の値を格納した配列です。
リスト : 3D Line Plot
import numpy as np
import matplotlib.pyplot as plt
z = np.linspace(0, 10 * np.pi, 500)
x = np.sin(z)
y = np.cos(z)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot(x, y, z, lw=2)
ax.set_title('3D Line Plot')
plt.show()
3D Line Plot
リスト : 3D Scatter Plot
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(50)
y = np.random.rand(50)
z = np.random.rand(50)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(x, y, z)
ax.set_title('3D Scatter Plot')
plt.show()
3D Scatter Plot
Matplotlib で 3 次元曲面を描画するには、主に以下のメソッドを使用します。
引数の仕様は contour() と同じです。ようするに、contour() のかわりに上記関数を使うと、3 次元曲面を表示することができます。
リスト : 3 次元の曲面 (1)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
xs, ys = np.meshgrid(x, y)
zs = np.sqrt(xs ** 2 + ys ** 2)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(xs, ys, zs)
ax.set_title('3D Surface')
plt.show()
3D Surface
リスト : 3 次元の曲面 (2)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
xs, ys = np.meshgrid(x, y)
zs = np.sqrt(xs ** 2 + ys ** 2)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_wireframe(xs, ys, zs, rstride=4, cstride=4)
ax.set_title('3D Wire Frame')
plt.show()
3D Wireframe
リスト : 3 次元の曲面 (3)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-6, 6, 30)
y = np.linspace(0, 12, 30)
xs, ys = np.meshgrid(x, y)
zs = np.sin(xs) + np.cos(ys)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(xs, ys, zs, cmap='viridis')
ax.set_title('3D Surface')
plt.show()
3 次元の曲面
Matplotlib で複数のグラフを並べて表示するには、1 つのキャンバスに複数の領域を作る関数 plt.subplots() を使うのが簡単です。行数と列数を指定してそれぞれの領域にデータを描画します。
fig, axes = plt.subplots(nrows = 数値, ncols = 数値)
縦の行数 (nrows) と横の列数 (ncols) を指定し、全体を管理する fig と各グラフ領域の配列 axes を同時に取得します。nrows または ncols のどちらかを省略した場合、axes は 1 次元配列、それ以外は 2 次元配列になります。1 次元配列の場合、axes[i] で i 番目の領域を指定します。2 次元配列の場合、axes[i, j] のように i 行目, j 列目を指定して、個別の領域に plot() でグラフを描画することができます。なお、行数と列数は subplots(1, 3) のように数値を直接指定してもかまいません。
plt.tight_layout()
グラフのタイトルや軸のラベルが重ならないよう、余白を自動でキレイに調整します。この関数は plt.show() の前に実行してください。
簡単な実行例を示します。
リスト : グラフを並べて表示 (1)
import matplotlib.pyplot as plt
import numpy as np
height = [
148.7, 149.5, 133.7, 157.9, 154.2, 147.8, 154.6, 159.1, 148.2, 153.1,
138.2, 138.7, 143.5, 153.2, 150.2, 157.3, 145.1, 157.2, 152.3, 148.3,
152.0, 146.0, 151.5, 139.4, 158.8, 147.6, 144.0, 145.8, 155.4, 155.5,
153.6, 138.5, 147.1, 149.6, 160.9, 148.9, 157.5, 155.1, 138.9, 153.0,
153.9, 150.9, 144.4, 160.3, 153.4, 163.0, 150.9, 153.3, 146.6, 153.3,
152.3, 153.3, 142.8, 149.0, 149.4, 156.5, 141.7, 146.2, 151.0, 156.5,
150.8, 141.0, 149.0, 163.2, 144.1, 147.1, 167.9, 155.3, 142.9, 148.7,
164.8, 154.1, 150.4, 154.2, 161.4, 155.0, 146.8, 154.2, 152.7, 149.7,
151.5, 154.5, 156.8, 150.3, 143.2, 149.5, 145.6, 140.4, 136.5, 146.9,
158.9, 144.4, 148.1, 155.5, 152.4, 153.3, 142.3, 155.3, 153.1, 152.3
]
fig, ax = plt.subplots(ncols=2, figsize=(6, 4)) # plt.subplots(1, 2, ...) でもよい
ax[0].hist(height, label='Frequency', edgecolor='black')
ax[0].set_title('Frequency')
ax[0].legend()
ax[1].hist(height, label='cumulative', cumulative=True, edgecolor='black')
ax[1].set_title('cumulative')
ax[1].legend()
plt.show()
グラフを並べて表示 (1)
リスト : グラフを並べて表示 (2)
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-np.pi, np.pi, 100)
# 2 行 2 列のサブプロットを作成
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
axes[0, 0].plot(x, np.sin(x), color='blue')
axes[0, 0].set_title('Sine Wave')
axes[0, 0].grid(True)
axes[0, 1].plot(x, np.cos(x), color='red')
axes[0, 1].set_title('Cosine Wave')
axes[0, 1].grid(True)
axes[1, 0].plot(x, x, color='green')
axes[1, 0].set_title('y = x')
axes[1, 0].grid(True)
y = x ** 2
axes[1, 1].plot(x, y, color='black')
axes[1, 1].set_title('y = x ** 2')
axes[1, 1].grid(True)
# レイアウトの自動調整
plt.tight_layout()
plt.show()
グラフを並べて表示 (2)
もっと複雑なレイアウト、たとえば、異なる大きさのグラフを配置する場合、メソッド subplot_mosaic() を使用するのが簡単でわかりやすいと思います。subplot_mosaic() は Matplotlib 3.4 から追加された機能で、グラフの配置をテキストアートのように定義できます。
fig, axd = plt.subplot_mosaic(layout, ...)
レイアウトは文字 (文字列のリスト) で定義します。
# 'A' は 2 ブロック分の高さを持ち、右側に 'B' と 'C' が縦に並ぶ
layout = [
['A', 'B'],
['A', 'C']
]
グラフを配置せず、あえて空白にしたい場所にはピリオド '.' を配置します。返り値の axd は辞書型です。axd['A'].plot(...) で A の領域にグラフを描画することができます。
主なオプションを以下に示します。
簡単な使用例を示しましょう。
リスト : グラフを並べて表示する (3)
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# 月平均気温
ys1 = [7.1, 8.0, 9.6, 17.1, 20.0, 23.1, 28.7, 29.0, 26.6, 20.6, 13.7, 8.1]
# 月平均最高気温
ys2 = [11.8, 12.5, 14.8, 21.8, 24.8, 27.7, 33.5, 33.6, 30.9, 24.5, 17.8, 13.2]
# 月平均最低気温
ys3 = [2.9, 4.1, 5.1, 13.1, 15.6, 19.3, 25.0, 25.7, 23.5, 17.4, 10.2, 3.8]
height = [
... 省略 ...
]
layout = [
['A', 'B'],
['A', 'C']
]
fig, axd = plt.subplot_mosaic(layout, figsize=(8, 5), layout="tight")
# 月
x = range(1, 13)
axd['A'].plot(x, ys1, lw=2, marker = 'o', label = "avg")
axd['A'].plot(x, ys2, lw=2, marker = 'o', label = "max")
axd['A'].plot(x, ys3, lw=2, marker = 'o', label = "min")
axd['A'].legend()
axd['A'].set_title('Line Chart')
axd['B'].hist(height, bins=8, color='skyblue', edgecolor='blue')
axd['B'].set_title('Histogram')
axd['C'].scatter(np.random.rand(40), np.random.rand(40), color='green')
axd['C'].set_title('Scatter Chart')
plt.show()
グラフを並べて表示 (3)
もう一つ、簡単な例を示しましょう。周辺分布付き散布図は、2 変数の相関関係を示す散布図と、それぞれの変数の単独の分布を示すグラフ (ヒストグラムなど) を 1 つに組み合わせたグラフです。Python のライブラリ Seaborn ではジョイントプロットと呼ばれています。Seaborn はあとで説明します。データ全体の相関を見つつ、各項目がどのようにバラついているか (偏りや分布の形状) を同時に把握できるのが特徴です。
subplot_mosaic() を使うと、周辺分布付き散布図は簡単に作成することができます。
リスト : 周辺分布付き散布図
import matplotlib.pyplot as plt
import numpy as np
#import seaborn as sns
np.random.seed(42)
x = np.random.randn(500)
y = np.random.randn(500)
layout = [
['A', 'A', 'A', '.'],
['B', 'B', 'B', 'C'],
['B', 'B', 'B', 'C'],
['B', 'B', 'B', 'C'],
]
fig, axd = plt.subplot_mosaic(layout, figsize=(8, 6), layout="tight")
axd['A'].hist(x, edgecolor='black')
axd['B'].scatter(x, y)
axd['C'].hist(y, orientation='horizontal', edgecolor='black')
plt.show()
周辺分布付き散布図