HOWTO · Matplotlib

Matplotlib で散布図の点を線で結ぶ方法

Matplotlib の散布図の点を `plot()` でデータ順に接続し、線のスタイルを設定し、`zorder` でどのレイヤーが前面に表示されるかを制御します。

このページの内容

散布図の点をデータ順に接続するには、同じ x と y の値を scatter() と plot() に渡し、最後に show() を呼び出して図を表示します。scatter() はマーカーを独立したコレクションとして描画し、plot() は指定された順序で点を結ぶパスを描画し、show() は完成した図を表示します。

このチュートリアルの例はすべて Matplotlib 3.11.2 と Python 3.12 で実行・検証済みであり、以下の各図は直上の例を実際に描画した出力です。

scatter() と plot() で散布図の点をデータ順に接続する

両方の関数に同じ座標列を渡します。plot() は指定された順序で各ペアを接続するため、列の順序がそのままパスを決定します。Matplotlib は点を x 座標でソートしません。各 x 値を対応する y 値とペアにしてください。最初の x 値は最初の y 値と、2 番目は 2 番目と対応します。観測を x でソートする場合は、2 つのリストを独立にソートするのではなく、それらの観測と一緒に y 値も並べ替えてください。

これは、データがルート、時系列、その他順序に意味のある列を表す場合に重要です。たとえば、x 値が 1 から 3 に進んでから 2 に戻ると、パスは右へ進んでから左へ戻ります。軌跡としてはそれが正しい場合があります。代わりに左から右へ進む曲線が目的であれば、先にペアになった観測をソートしてください。隣り合う観測が同じ x 値を共有する場合、線に垂直な区間が含まれることもありますが、plot() はそれらを指定された順序で結びます。

この例では、1 組の座標を使ってマーカーと接続線を重ねます。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 1, 3, 2]

plt.scatter(x, y)
plt.plot(x, y)
plt.xlabel("x")
plt.ylabel("y")
plt.show()

(1, 2)、(2, 1)、(3, 3)、(4, 2) の 4 つの散布図の点が、データ順に実線で結ばれている図。

同じ x と y の入力を使うことで、マーカーと線の位置が揃います。2 つのレイヤーがずれて見える場合は、どちらか一方の列だけが片方の呼び出しのために変換や並べ替えをされていないか確認してください。表に格納されたデータについては、両方の列を同じ行から同じ順序で選択してください。この例は pyplot インターフェースを使うため、別の figure 変数は不要です。オブジェクト指向インターフェースでは、fig, ax = plt.subplots() で figure と axes を作成し、その axes に対して ax.scatter(...) と ax.plot(...) を呼び出します。

plot() で線とマーカーのスタイルを設定する

plot() が描くパスのスタイルは linestyle と color で設定します。次の例では、マーカー用に別の scatter() レイヤーを維持し、接続パスを青い破線として描きます。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 1, 3, 2]

plt.scatter(x, y, color="blue")
plt.plot(x, y, linestyle="--", color="blue")
plt.xlabel("x")
plt.ylabel("y")
plt.show()

同じ 4 つの点が青い破線で結ばれ、各点に青いマーカーが付いた図。

scatter() と plot() を分けて呼び出すと、点のコレクションと接続パスを独立に制御できます。線に触れることなくマーカーのサイズや色を変更できるため、パスを視覚的にシンプルに保ちながら点を強調したい場合に便利です。両方の呼び出しに同じ座標列を渡し、各マーカーが線の対応する点の上に来るようにしてください。

単一の plot() 呼び出しでも、"xb-" のような書式文字列で両方のレイヤーを一度に描けます。ここで x はマーカーの形状、b は青、- は実線を選択します。書式文字列は 1 回の呼び出しで全部を描く場合にコンパクトです。一方、color、marker、linestyle といったキーワード引数は、マーカーのサイズ、線の太さ、透明度などの他のプロパティが必要な場合に明確です。どちらの方法を選んでも、show() はスタイルとレイヤーのすべての呼び出しの後に置いてください。図はそれらの要素が追加された後に初めて表示されるためです。

zorder でどちらのレイヤーを前面に表示するかを制御する

zorder が高い要素は、低い要素の上に描画されます。これは描画順序を変えるだけで、座標やパスは変わりません。この設定は、太い線がマーカーを横切って中心を隠してしまう場合や、密集したマーカーの上で線を見える状態に保ちたい場合に重要です。

次の例では線を意図的に太くし、マーカーに高い zorder を与えることで、線が下を通る場所でも各丸マーカーが欠けずに残ります。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 1, 3, 2]

plt.plot(x, y, linewidth=6, zorder=2)
plt.scatter(x, y, s=120, zorder=3)
plt.xlabel("x")
plt.ylabel("y")
plt.show()

4 つの点を結ぶ太い線と、各点で線の上に描かれた大きめの丸マーカー。

マーカーを線の上に置くには、上記のように scatter() に zorder=3、plot() に zorder=2 という具合に、散布コレクションに大きい方の値を与えます。線をマーカーの上に置くには、値を入れ替えます。意図する順序を表すには 2 つの値の差を控えめにし、重なりを明確にしたい場合は両方の要素に zorder を設定してください。同じ比較は、後から追加する他のプロット要素にも当てはまります。zorder が最も高い要素が他の要素の上に描画されます。

サイズ不一致エラーを避けるために x と y の長さを合わせる

どちらの関数も値を位置ごとに対応付けるため、2 つの列の長さは同じでなければなりません。長さが異なると、呼び出しは ValueError を発生させ、図は描画されません。この例では、最後の y 値を誤って落としています。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 1, 3]

plt.scatter(x, y)
plt.plot(x, y)
plt.show()

実行すると、scatter() の呼び出しで次のエラーが発生します。

ValueError: x and y must be the same size

同じ入力で plot() だけを呼び出した場合も、同じ問題を別の言い回しで失敗します: ValueError: x and y must have same first dimension, but have shapes (4,) and (3,)。このエラーを修正するには、不足している観測、または余分な観測を見つけ、2 つの列が再び同じ点を表すようにします。プロット前に len(x) と len(y) を比較すると、どちら側が短いかが分かります。データが表から来る場合は、行を一度だけフィルタリングし、フィルタ済みの行から両方の列を取得してください。各列を別々にフィルタリングすると、長さがずれてしまいます。

2 つの空の列は別のケースです。これらは受け入れられ、エラーなく空の axes を生成します。したがって、図が空になるのは通常、長さの不一致ではなく、入力データが空だったことが原因です。