はい、承知いたしました。Python Matplotlibの初心者向けの使い方に関する詳細な記事を、約5000語のボリュームで記述し、直接表示します。
初心者必見!Python Matplotlibの使い方をわかりやすく紹介
はじめに
データ分析や機械学習の世界では、データを「見て理解する」ことが非常に重要です。大量の数値をただ眺めるだけでは、そこに隠されたパターンや傾向、異常値などを見つけ出すのは困難です。そこで力を発揮するのが「データ可視化」です。データをグラフや図として表現することで、直感的に、そして効率的にデータを理解することができます。
Pythonにはデータ可視化のための優れたライブラリがいくつか存在しますが、その中でも最も古く、最も広く使われているのが Matplotlib です。Matplotlibは、静的なグラフ、インタラクティブなグラフ、さらにはアニメーションまで、多種多様な形式のグラフを作成できる強力なツールです。その機能は非常に豊富で、最初は少し overwhelming(圧倒される)に感じるかもしれません。しかし、基本から順を追って学べば、誰でも自由にグラフを作成できるようになります。
この記事は、Pythonを使ったデータ分析を始めたばかりの方、特にMatplotlibを初めて触る方を対象としています。Matplotlibで最もよく使われる基本的なグラフの種類から、グラフの見た目をカスタマイズする方法、複数のグラフを配置する方法まで、実際のコード例を交えながらわかりやすく解説していきます。この記事を読むことで、あなたも Matplotlib を使って効果的なデータ可視化ができるようになるでしょう。
さあ、Matplotlibの世界へ飛び込んでみましょう!
Matplotlibのインストールと基本的な準備
Matplotlibを使うためには、まずお使いのPython環境にインストールする必要があります。ほとんどの場合、以下のコマンドをターミナルやコマンドプロンプトで実行するだけで簡単にインストールできます。
bash
pip install matplotlib
AnacondaなどのPythonディストリビューションを使っている場合は、すでにインストールされているか、または以下のコマンドでインストールできます。
bash
conda install matplotlib
インストールが完了したら、PythonスクリプトやJupyter NotebookなどでMatplotlibを使い始めることができます。Matplotlibの多くの機能は pyplot
というモジュールにまとめられています。このモジュールをインポートするのが一般的です。慣習として plt
というエイリアス(別名)をつけてインポートすることが多いです。
python
import matplotlib.pyplot as plt
これでMatplotlibを使う準備ができました。
Matplotlibでグラフを描画する基本的な流れは非常にシンプルです。
- データの準備: グラフにしたいデータをPythonのリストやNumPy配列などで準備します。
- プロット:
pyplot
モジュール(または後述するAxesオブジェクト)の関数を使って、データをプロットします。例えば、線グラフならplt.plot()
、散布図ならplt.scatter()
を使います。 - 表示:
plt.show()
関数を呼び出すことで、作成したグラフが表示されます。Jupyter Notebookなどでは、plt.show()
を書かなくても最後のプロットコマンドの後に自動的に表示される設定になっていることが多いですが、スクリプトとして実行する場合は必須です。
簡単な例を見てみましょう。
“`python
必要なライブラリをインポート
import matplotlib.pyplot as plt
データの準備
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
線グラフをプロット
plt.plot(x, y)
グラフを表示
plt.show()
“`
このコードを実行すると、xが1から5、yが2から10の点を結んだ直線が表示されます。
最も基本的なプロットの種類
Matplotlibでは様々な種類のグラフを作成できます。ここでは、データ分析で特によく使われるいくつかの基本的なグラフを紹介します。
1. 線グラフ (Line Plot)
線グラフは、連続的なデータの変化やトレンドを示すのに適しています。時間経過による変化や、ある数値が別の数値によってどのように変化するかを見る際によく使われます。
plt.plot()
関数を使って描画します。引数には、x軸の値とy軸の値をリストやNumPy配列で渡します。
“`python
import matplotlib.pyplot as plt
import numpy as np # numpyを使うとデータ準備が楽になることが多いです
時間経過に見立てたデータ
time = np.arange(0, 10, 0.1) # 0から10まで0.1刻みの数値
temperature = 20 + 5 * np.sin(time * np.pi / 2) # 変化する温度データ
plt.plot(time, temperature)
plt.xlabel(‘時間 (Hour)’) # x軸ラベル
plt.ylabel(‘温度 (°C)’) # y軸ラベル
plt.title(‘時間の経過による温度変化’) # タイトル
plt.grid(True) # グリッドを表示
plt.show()
“`
線のカスタマイズ
plt.plot()
関数には、線の色、スタイル、太さなどを指定するための引数があります。
color
: 線の色(例:'r'
赤,'b'
青,'g'
緑,'k'
黒,'#FF5733'
HTMLカラーコードなど)linestyle
: 線のスタイル(例:'-'
実線,'--'
破線,'-.'
一点鎖線,':'
点線)linewidth
: 線の太さ(デフォルトは1.5)marker
: 各データ点のマーカー(例:'o'
丸,'x'
バツ,'*'
アスタリスク,'.'
点)markersize
: マーカーのサイズ
“`python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100) # 0から10まで100等分した値
y1 = np.sin(x)
y2 = np.cos(x)
複数の線を同じグラフに描画
plt.plot(x, y1, label=’sin(x)’, color=’blue’, linestyle=’–‘, linewidth=2)
plt.plot(x, y2, label=’cos(x)’, color=’red’, linestyle=’-‘, linewidth=1, marker=’o’, markersize=4)
plt.xlabel(‘X軸’)
plt.ylabel(‘Y軸’)
plt.title(‘サインとコサインのグラフ’)
plt.legend() # 凡例を表示 (label引数を指定している場合)
plt.grid(True)
plt.show()
“`
このように、複数の plt.plot()
を続けて呼び出すことで、同じグラフ領域に複数の線を重ねて描画できます。label
引数に線の名前を指定し、plt.legend()
を呼び出すと、どの線がどのデータを表しているかを示す凡例が表示されます。
2. 散布図 (Scatter Plot)
散布図は、2つの異なる変数間の関係性を個々の点の集合として示すのに適しています。点のばらつきや集まり方から、相関関係の有無や程度を視覚的に捉えることができます。
plt.scatter()
関数を使って描画します。引数には、x座標の配列とy座標の配列を渡します。
“`python
import matplotlib.pyplot as plt
import numpy as np
ランダムなデータの生成
np.random.seed(0) # 乱数を固定
x = np.random.rand(50) * 10 # 0から10までのランダムな値50個
y = np.random.rand(50) * 10 # 0から10までのランダムな値50個
plt.scatter(x, y)
plt.xlabel(‘X値’)
plt.ylabel(‘Y値’)
plt.title(‘ランダムな散布図’)
plt.show()
“`
点のカスタマイズ
plt.scatter()
関数も、点の見た目をカスタマイズするための様々な引数を持っています。
s
: 点のサイズ(数値または配列で指定)c
: 点の色(色名、HTMLカラーコード、または配列で指定)marker
: 点の形状(例:'o'
丸,'x'
バツ,'^'
三角など)alpha
: 点の透明度(0.0から1.0までの数値)
特に s
や c
にデータの配列を渡すことで、点のサイズや色を別の変数の値に応じて変化させることができます。これは、3つ目や4つ目の変数(次元)を同時に表現するのに役立ちます。
“`python
import matplotlib.pyplot as plt
import numpy as np
ランダムなデータの生成
np.random.seed(0)
n_samples = 100
x = np.random.rand(n_samples) * 10
y = np.random.rand(n_samples) * 10
sizes = np.random.rand(n_samples) * 500 # 点のサイズをランダムに変化
colors = np.random.rand(n_samples) # 点の色をランダムに変化 (カラーマップによって色が決まる)
plt.scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’viridis’) # cmapで色のスタイルを指定
plt.xlabel(‘X値’)
plt.ylabel(‘Y値’)
plt.title(‘カスタマイズされた散布図’)
plt.colorbar(label=’カラーバーの値’) # cに数値配列を指定した場合、カラーバーを表示できる
plt.show()
“`
cmap
は Color Map の略で、c
に数値配列を渡したときに、その数値がどのような色に対応するかを定義します。’viridis’ はよく使われるカラーマップの一つです。
3. 棒グラフ (Bar Chart)
棒グラフは、カテゴリごとの数量や比率を比較するのに適しています。項目間の大小関係を視覚的に捉えやすいグラフです。
plt.bar()
関数で縦棒グラフ、plt.barh()
関数で横棒グラフを描画します。
“`python
import matplotlib.pyplot as plt
データの準備
categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]
values = [25, 40, 30, 35, 50]
縦棒グラフ
plt.figure(figsize=(8, 6)) # グラフのサイズを指定
plt.bar(categories, values, color=’skyblue’)
plt.xlabel(‘カテゴリ’)
plt.ylabel(‘値’)
plt.title(‘カテゴリごとの値’)
plt.ylim(0, 60) # Y軸の範囲を指定
plt.show()
横棒グラフ (Y軸とX軸が入れ替わることに注意)
plt.figure(figsize=(8, 6))
plt.barh(categories, values, color=’lightgreen’)
plt.xlabel(‘値’) # 横棒グラフではX軸が値になる
plt.ylabel(‘カテゴリ’) # 横棒グラフではY軸がカテゴリになる
plt.title(‘カテゴリごとの値 (横棒グラフ)’)
plt.xlim(0, 60) # X軸の範囲を指定
plt.show()
“`
複数の棒グラフ
複数の系列のデータを比較する場合、棒を並べたり積み上げたりして表示することができます。
並列棒グラフ: 複数の plt.bar()
を呼び出し、棒の位置をずらして描画します。棒の幅 (width
引数) を調整する必要があります。
“`python
import matplotlib.pyplot as plt
import numpy as np
labels = [‘G1’, ‘G2’, ‘G3’, ‘G4’, ‘G5’]
men_means = [20, 35, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]
x = np.arange(len(labels)) # ラベルの位置
width = 0.35 # 棒の幅
fig, ax = plt.subplots(figsize=(10, 7)) # オブジェクト指向スタイルでFigureとAxesを作成
rects1 = ax.bar(x – width/2, men_means, width, label=’男性’)
rects2 = ax.bar(x + width/2, women_means, width, label=’女性’)
軸ラベル、タイトル、目盛りの設定
ax.set_xlabel(‘グループ’)
ax.set_ylabel(‘平均点’)
ax.set_title(‘グループごとの男女別平均点’)
ax.set_xticks(x) # X軸の目盛りの位置を設定
ax.set_xticklabels(labels) # X軸の目盛りのラベルを設定
ax.legend()
オプション: 棒の上に値を表示
def autolabel(rects):
“””Attach a text label above each bar in rects, displaying its height.”””
for rect in rects:
height = rect.get_height()
ax.annotate(‘{}’.format(height),
xy=(rect.get_x() + rect.get_width() / 2, height),
xytext=(0, 3), # 3 points vertical offset
textcoords=”offset points”,
ha=’center’, va=’bottom’)
autolabel(rects1)
autolabel(rects2)
fig.tight_layout() # レイアウトを自動調整
plt.show()
“`
積み上げ棒グラフ: 2番目以降の棒グラフを描画する際に、bottom
引数に前の棒グラフの高さを指定します。
“`python
import matplotlib.pyplot as plt
import numpy as np
labels = [‘G1’, ‘G2’, ‘G3’, ‘G4’, ‘G5’]
men_means = [20, 35, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]
x = np.arange(len(labels))
width = 0.35
fig, ax = plt.subplots(figsize=(10, 7))
最初の系列 (男性)
rects1 = ax.bar(x, men_means, width, label=’男性’)
2番目の系列 (女性) – bottomに男性の値を指定して積み上げる
rects2 = ax.bar(x, women_means, width, bottom=men_means, label=’女性’)
ax.set_xlabel(‘グループ’)
ax.set_ylabel(‘合計点’)
ax.set_title(‘グループごとの男女別積み上げ合計点’)
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()
オプション: 積み上げ棒グラフの上に値を表示 (合計や各要素の値など)
各要素の値
def autolabel_stacked(rects):
for rect in rects:
height = rect.get_height()
ax.annotate(‘{}’.format(height),
xy=(rect.get_x() + rect.get_width() / 2, rect.get_y() + height/2), # Y座標を中心にする
xytext=(0, 0),
textcoords=”offset points”,
ha=’center’, va=’center’)
autolabel_stacked(rects1)
autolabel_stacked(rects2)
fig.tight_layout()
plt.show()
“`
4. ヒストグラム (Histogram)
ヒストグラムは、数値データの分布を把握するためのグラフです。データをいくつかの区間(ビン)に分け、各区間に含まれるデータの数を棒の高さで示します。
plt.hist()
関数を使って描画します。引数には、分布を見たい数値データの配列を渡します。
“`python
import matplotlib.pyplot as plt
import numpy as np
正規分布に従うランダムなデータ1000個
data = np.random.randn(1000)
plt.hist(data, bins=30, color=’lightblue’, edgecolor=’black’) # binsでビンの数を指定
plt.xlabel(‘値’)
plt.ylabel(‘度数’)
plt.title(‘データのヒストグラム’)
plt.grid(axis=’y’, alpha=0.75) # Y軸方向にグリッドを表示
plt.show()
“`
ヒストグラムのオプション
bins
: ビンの数を指定します。数値で指定するとその数のビンに分けられます。配列で指定すると、ビンの境界を指定できます。range
: ヒストグラムを作成するデータの範囲を指定します。density
:True
にすると、度数ではなく確率密度が表示されます(棒の面積の合計が1になります)。cumulative
:True
にすると、累積度数または累積確率密度が表示されます。
“`python
import matplotlib.pyplot as plt
import numpy as np
data1 = np.random.normal(0, 1, 1000) # 平均0, 標準偏差1の正規分布
data2 = np.random.normal(3, 1.5, 1000) # 平均3, 標準偏差1.5の正規分布
複数のヒストグラムを重ねて表示
plt.hist(data1, bins=40, alpha=0.7, label=’データ1′, color=’skyblue’)
plt.hist(data2, bins=40, alpha=0.7, label=’データ2′, color=’lightcoral’) # alphaで透明度を設定すると重なりが見やすい
plt.xlabel(‘値’)
plt.ylabel(‘度数’)
plt.title(‘複数のデータのヒストグラム’)
plt.legend()
plt.grid(axis=’y’, alpha=0.5)
plt.show()
密度表示のヒストグラム
plt.hist(data1, bins=40, density=True, alpha=0.7, label=’データ1 (密度)’, color=’skyblue’)
plt.hist(data2, bins=40, density=True, alpha=0.7, label=’データ2 (密度)’, color=’lightcoral’)
plt.xlabel(‘値’)
plt.ylabel(‘確率密度’)
plt.title(‘データの確率密度ヒストグラム’)
plt.legend()
plt.grid(axis=’y’, alpha=0.5)
plt.show()
“`
5. 円グラフ (Pie Chart)
円グラフは、全体に対する各項目の割合を示すのに適しています。合計が100%となるような構成比を示す場合によく使われます。
plt.pie()
関数を使って描画します。引数には、各項目の大きさを表す数値のリストや配列を渡します。
“`python
import matplotlib.pyplot as plt
データの準備
sizes = [15, 30, 45, 10] # 各項目の割合 (合計は任意、Matplotlibが正規化してくれる)
labels = [‘Apple’, ‘Banana’, ‘Cherry’, ‘Date’] # 各項目のラベル
colors = [‘gold’, ‘yellowgreen’, ‘lightcoral’, ‘lightskyblue’] # 各項目の色
explode = (0, 0.1, 0, 0) # 2番目の要素 (Banana) を少し切り出す
plt.figure(figsize=(8, 8)) # 円を正円に近づけるためにfigsizeを正方形にする
plt.pie(sizes, explode=explode, labels=labels, colors=colors,
autopct=’%1.1f%%’, shadow=True, startangle=140) # autopctで割合の表示形式を指定
plt.axis(‘equal’) # アスペクト比を等しくすることで円を正円にする
plt.title(‘フルーツの割合’)
plt.show()
“`
円グラフのオプション
labels
: 各項目に対応するラベルのリストcolors
: 各項目に対応する色のリストautopct
: 各項目の割合を表示するための書式文字列(例:'%1.1f%%'
は小数点以下1桁のパーセント表示)explode
: 各項目を円の中心からどのくらい離すかを指定する数値のリストshadow
:True
にすると影を追加します。startangle
: 最初の項目を描画し始める角度を指定します(デフォルトは0、真東から時計回り)。wedgeprops
: 各扇形のプロパティ(線の色、幅など)を指定できます。例:dict(width=0.7)
でドーナツグラフになります。
“`python
import matplotlib.pyplot as plt
ドーナツグラフの例
sizes = [15, 30, 45, 10]
labels = [‘Apple’, ‘Banana’, ‘Cherry’, ‘Date’]
colors = [‘gold’, ‘yellowgreen’, ‘lightcoral’, ‘lightskyblue’]
plt.figure(figsize=(8, 8))
wedgeprops = {‘width’: 0.4, ‘edgecolor’: ‘white’} # 幅0.4の扇形、白い境界線
plt.pie(sizes, labels=labels, colors=colors, autopct=’%1.1f%%’,
startangle=90, wedgeprops=wedgeprops) # startangle=90で真上から開始
plt.axis(‘equal’)
plt.title(‘フルーツの割合 (ドーナツグラフ)’)
中心にテキストを追加することも可能 (任意)
center_circle = plt.Circle((0,0), 0.3, color=’white’) # 中心に白い円を描画
fig = plt.gcf() # 現在のFigureを取得
fig.gca().add_artist(center_circle) # 現在のAxesに円を追加
plt.show()
“`
グラフの構成要素とカスタマイズ
Matplotlibでより高度なグラフを作成し、見た目を整えるためには、グラフを構成する主要な要素とその操作方法を理解することが重要です。
Matplotlibのグラフは、大きく分けて以下の2つの階層的なオブジェクトから構成されます。
- Figure (図): グラフを描画するウィンドウ全体、または画像のキャンバス全体を表します。このFigureの中に、1つ以上のAxesが含まれます。
- Axes (座標軸): 実際にデータがプロットされる個々のグラフ領域(プロットエリア)を表します。X軸、Y軸、データ点、線、タイトル、ラベル、凡例などはすべてこのAxesオブジェクトに属します。混乱しやすいですが、Axesは単数形でも複数の軸を含むグラフ領域全体を指します。
基本的な plt.plot()
や plt.scatter()
などの関数は、内部で現在のFigureとAxesを自動的に作成または取得して操作しています。これを pyplotスタイル (またはステートベースインターフェース) と呼びます。
一方、MatplotlibではFigureオブジェクトとAxesオブジェクトを明示的に作成し、それらのオブジェクトのメソッドを呼び出してグラフを作成する オブジェクト指向スタイル が推奨されています。オブジェクト指向スタイルを使うと、複数のグラフを管理したり、グラフの細かい部分を制御したりする際に、より柔軟で明確なコードを書くことができます。
オブジェクト指向スタイルでFigureとAxesを作成するには、plt.subplots()
関数が便利です。
“`python
import matplotlib.pyplot as plt
1つのFigureに1つのAxesを作成
fig, ax = plt.subplots()
Axesオブジェクトに対してプロット関数や設定メソッドを呼び出す
ax.plot([1, 2, 3], [1, 4, 9])
ax.set_xlabel(‘X-axis’)
ax.set_ylabel(‘Y-axis’)
ax.set_title(‘Example Plot (Object-Oriented Style)’)
plt.show()
“`
これまでの例で plt.xlabel()
や plt.title()
を使ってきましたが、これらは内部で現在のAxesオブジェクトを取得して設定を行っています。オブジェクト指向スタイルでは ax.set_xlabel()
や ax.set_title()
のように、Axesオブジェクトのメソッドを直接呼び出します。
タイトル、ラベル、凡例の設定
グラフのタイトル、軸ラベル、凡例は、グラフが何を示しているのかを理解するために不可欠な要素です。
- タイトル:
- Figure全体のタイトル:
fig.suptitle('Overall Title')
またはplt.suptitle('Overall Title')
- 各Axesのタイトル:
ax.set_title('Axes Title')
またはplt.title('Axes Title')
(pyplotスタイル)
- Figure全体のタイトル:
- 軸ラベル:
- X軸ラベル:
ax.set_xlabel('X Label')
またはplt.xlabel('X Label')
- Y軸ラベル:
ax.set_ylabel('Y Label')
またはplt.ylabel('Y Label')
- X軸ラベル:
- 凡例 (Legend):
- 各プロット関数(
ax.plot()
,ax.scatter()
など)にlabel='Data Name'
引数を指定します。 ax.legend()
またはplt.legend()
を呼び出すことで凡例が表示されます。
- 各プロット関数(
“`python
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 6)) # FigureとAxesを作成
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
Axesオブジェクトを使ってプロット。labelを指定。
ax.plot(x, y1, label=’Sine Wave’)
ax.plot(x, y2, label=’Cosine Wave’)
Axesオブジェクトを使ってタイトル、ラベルを設定
ax.set_title(‘Sine and Cosine Waves’)
ax.set_xlabel(‘X Value’)
ax.set_ylabel(‘Y Value’)
凡例を表示
ax.legend()
plt.show()
“`
凡例の位置は ax.legend()
の loc
引数で指定できます。例えば 'upper right'
, 'upper left'
, 'lower right'
, 'lower left'
, 'best'
(最適な位置を自動選択) などがあります。
“`python
… 上記のコードに続けて …
凡例の位置を変更
ax.legend(loc=’lower right’)
… plt.show()
“`
軸の範囲と目盛り
グラフの表示範囲や目盛りを調整することで、データの特定の範囲を強調したり、グラフをより読みやすくしたりできます。
- 軸の範囲:
- X軸の範囲:
ax.set_xlim(min_val, max_val)
またはplt.xlim(min_val, max_val)
- Y軸の範囲:
ax.set_ylim(min_val, max_val)
またはplt.ylim(min_val, max_val)
- X軸の範囲:
- 目盛り:
- 目盛りの位置:
ax.set_xticks(list_of_ticks)
またはplt.xticks(list_of_ticks)
- 目盛りのラベル:
ax.set_xticklabels(list_of_labels)
またはplt.xticklabels(list_of_labels)
(目盛りの位置と対応させる) - Y軸も同様に
set_yticks
,set_yticklabels
を使います。
- 目盛りの位置:
- グリッド:
- グリッドの表示:
ax.grid(True)
またはplt.grid(True)
- グリッドの軸やスタイルを指定:
ax.grid(axis='y', linestyle='--', alpha=0.6)
(axis=’x’ or ‘y’ or ‘both’)
- グリッドの表示:
“`python
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y)
Y軸の範囲を狭める
ax.set_ylim(-0.5, 0.5)
X軸の目盛りを0から10まで2刻みで設定
ax.set_xticks(np.arange(0, 11, 2))
Y軸の目盛りを-0.5から0.5まで0.1刻みで設定
ax.set_yticks(np.arange(-0.5, 0.6, 0.1))
グリッドを表示
ax.grid(True, linestyle=’:’, alpha=0.6)
ax.set_title(‘Sine Wave with Customized Axes’)
ax.set_xlabel(‘X Value’)
ax.set_ylabel(‘Y Value’)
plt.show()
“`
テキストと注釈の追加
グラフ内の特定の場所にテキストを追加したり、注釈付きの矢印を引いたりすることで、グラフの特定のポイントを解説できます。
- テキストの追加:
ax.text(x, y, 'text', ...)
またはplt.text(x, y, 'text', ...)
x
,y
: テキストを配置する座標'text'
: 表示する文字列- オプション:
fontsize
,color
,ha
(水平方向の配置: ‘left’, ‘center’, ‘right’),va
(垂直方向の配置: ‘top’, ‘center’, ‘bottom’) など
- 注釈の追加:
ax.annotate('text', xy=(arrow_end_x, arrow_end_y), xytext=(text_start_x, text_start_y), arrowprops=dict(...))
またはplt.annotate(...)
'text'
: 注釈の文字列xy
: 矢印の先端の座標xytext
: テキストの開始位置の座標arrowprops
: 矢印のスタイルを指定する辞書(例:arrowprops=dict(facecolor='black', shrink=0.05)
)
“`python
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y)
特定の点にテキストを追加
ax.text(np.pi, np.sin(np.pi), ‘sin(pi)=0′, fontsize=12, color=’red’,
horizontalalignment=’center’, verticalalignment=’bottom’) # 中央揃え、下端揃え
極大値に注釈を追加
max_y = np.max(y)
max_x = x[np.argmax(y)] # yが最大になるxの値を取得
ax.annotate(‘Local Max’, xy=(max_x, max_y), xytext=(max_x + 1, max_y + 0.2),
arrowprops=dict(facecolor=’black’, shrink=0.05),
fontsize=12, color=’darkgreen’)
ax.set_title(‘Sine Wave with Text and Annotation’)
ax.set_xlabel(‘X Value’)
ax.set_ylabel(‘Y Value’)
ax.grid(True)
plt.show()
“`
複数のプロットを配置する
1つのFigureの中に複数のグラフ(Axes)を並べて表示したい場合があります。これは、異なる種類のデータを比較したり、同じデータを異なる視点から見たりする際に便利です。
plt.subplots(nrows, ncols)
関数を使うと、指定した行数 (nrows
) と列数 (ncols
) でAxesのグリッドを作成し、それらを格納したNumPy配列とFigureオブジェクトを返してくれます。
“`python
import matplotlib.pyplot as plt
import numpy as np
2行2列のグリッドに4つのAxesを作成
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8)) # figsizeでFigure全体のサイズを指定
axesはNumPy配列なので、インデックスでアクセスできる
axes[0, 0]: 1行1列目
axes[0, 1]: 1行2列目
axes[1, 0]: 2行1列目
axes[1, 1]: 2行2列目
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = x**2
y4 = np.exp(-x)
各Axesに異なるグラフを描画
axes[0, 0].plot(x, y1)
axes[0, 0].set_title(‘Sine’)
axes[0, 1].scatter(x, y2, s=5)
axes[0, 1].set_title(‘Cosine (Scatter)’)
axes[1, 0].plot(x, y3, color=’red’)
axes[1, 0].set_title(‘x^2’)
axes[1, 1].plot(x, y4, color=’green’, linestyle=’–‘)
axes[1, 1].set_title(‘exp(-x)’)
レイアウトの調整
fig.suptitle(‘Multiple Subplots Example’) # Figure全体のタイトル
plt.tight_layout(rect=[0, 0, 1, 0.95]) # Figureタイトルとサブプロットが重ならないように調整 (rectで領域を指定)
または plt.tight_layout() # サブプロット間のスペースを自動調整 (Figureタイトルと重なる可能性あり)
plt.show()
“`
plt.subplots()
で作成された axes
はNumPy配列なので、ループ処理と組み合わせることで、大量のサブプロットを効率的に作成することも可能です。
例えば、3つの異なるデータのヒストグラムを横に並べる場合:
“`python
import matplotlib.pyplot as plt
import numpy as np
data1 = np.random.normal(0, 1, 500)
data2 = np.random.normal(3, 1.5, 500)
data3 = np.random.normal(-2, 0.8, 500)
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 5)) # 1行3列
all_data = [data1, data2, data3]
titles = [‘Data 1 (N(0,1))’, ‘Data 2 (N(3, 1.5))’, ‘Data 3 (N(-2, 0.8))’]
colors = [‘skyblue’, ‘lightcoral’, ‘lightgreen’]
for i, ax in enumerate(axes): # axesはNumPy配列なのでイテレートできる
ax.hist(all_data[i], bins=30, color=colors[i], edgecolor=’black’, alpha=0.7)
ax.set_title(titles[i])
ax.set_xlabel(‘Value’)
ax.set_ylabel(‘Frequency’)
ax.grid(axis=’y’, alpha=0.5)
fig.suptitle(‘Histograms of Three Different Datasets’)
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.show()
“`
このように、オブジェクト指向スタイル (fig, ax = plt.subplots(...)
の形式) を使うことで、複数のグラフやグラフの各要素をより柔軟に操作できます。慣れてきたら、pyplotスタイルからオブジェクト指向スタイルに移行することをおすすめします。
データの準備 (NumPy/Pandasとの連携)
実際のデータ分析では、PythonのリストよりもNumPy配列やPandas DataFrameとしてデータを扱うことがほとんどです。Matplotlibはこれらのライブラリと非常に親和性が高く、シームレスに連携できます。
NumPy配列を使う
NumPyは高速な数値計算ライブラリで、配列(ndarray)を扱います。Matplotlibのプロット関数は、リストだけでなくNumPy配列も引数として受け取ることができます。
“`python
import matplotlib.pyplot as plt
import numpy as np
NumPy配列でデータを準備
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])
plt.plot(x, y, marker=’o’)
plt.xlabel(‘X’)
plt.ylabel(‘Y’)
plt.title(‘Plot using NumPy Arrays’)
plt.show()
“`
NumPyを使うと、データの生成や操作が非常に簡単になります。例えば、上記でも使った np.linspace
, np.arange
, np.random.rand
, np.sin
などの関数は、NumPy配列を返すため、そのままMatplotlibの関数に渡すことができます。
Pandas DataFrameを使う
Pandasはデータ分析に特化したライブラリで、表形式のデータ(DataFrame)や時系列データ(Series)を効率的に扱えます。PandasオブジェクトをMatplotlibの関数に渡すと、カラム名などが自動的にラベルとして使われることがあり、非常に便利です。また、Pandas自体がMatplotlibを内部的に利用したプロット機能(.plot()
メソッド)を持っています。
“`python
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
Pandas DataFrameでデータを準備
data = {‘Category’: [‘A’, ‘B’, ‘C’, ‘D’],
‘Value1’: [10, 25, 15, 20],
‘Value2’: [12, 20, 18, 22]}
df = pd.DataFrame(data)
print(df)
DataFrameのカラムを指定してプロット
plt.figure(figsize=(8, 6))
plt.bar(df[‘Category’], df[‘Value1′], label=’Value1′, color=’skyblue’, width=0.4)
複数の系列を並列に表示する場合は、位置をずらすなどの工夫が必要(上記棒グラフの並列表示例を参照)
この例では、Value1だけをシンプルに表示
plt.xlabel(‘Category’)
plt.ylabel(‘Value’)
plt.title(‘Bar Plot from Pandas DataFrame’)
plt.show()
DataFrameの.plot() メソッドを使うとさらに簡単に描画できる
デフォルトは線グラフ
df.plot(x=’Category’, y=’Value1′, kind=’line’, marker=’o’, title=’Line Plot (Pandas .plot())’)
plt.ylabel(‘Value’)
plt.grid(True)
plt.show()
棒グラフを描画する場合
df.plot(x=’Category’, y=[‘Value1’, ‘Value2′], kind=’bar’, figsize=(10, 6), title=’Bar Plot (Pandas .plot())’)
plt.ylabel(‘Value’)
plt.xticks(rotation=0) # X軸のラベルを回転させない
plt.show()
散布図を描画する場合
df_scatter = pd.DataFrame({‘X’: np.random.rand(50)10, ‘Y’: np.random.rand(50)10, ‘Size’: np.random.rand(50)*500, ‘Color’: np.random.rand(50)})
df_scatter.plot(kind=’scatter’, x=’X’, y=’Y’, s=df_scatter[‘Size’], c=df_scatter[‘Color’], alpha=0.7, cmap=’viridis’, figsize=(8, 6), title=’Scatter Plot (Pandas .plot())’)
plt.colorbar(label=’Color Value’)
plt.show()
“`
Pandasの .plot()
メソッドは、Matplotlibの機能をラップしており、DataFrameのカラム名を直接指定して簡単に各種グラフを描画できます。データ分析のワークフローでは、まずPandasでデータを整形し、その後 .plot()
メソッドで素早く概観を把握し、必要に応じてMatplotlibを直接使って詳細なカスタマイズを行う、という流れが一般的です。
グラフの保存
作成したグラフをファイルとして保存したい場合は、plt.savefig()
関数を使います。Jupyter Notebookなどで画像として表示するだけでなく、レポートに貼り付けたり、プレゼンテーションに使ったりする際に必要になります。
“`python
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title(‘Sine Wave’)
plt.xlabel(‘X Value’)
plt.ylabel(‘Y Value’)
plt.grid(True)
グラフをファイルに保存
plt.savefig(‘sine_wave.png’) # PNG形式で保存
plt.savefig(‘sine_wave.pdf’) # PDF形式で保存
plt.savefig(‘sine_wave.svg’) # SVG形式で保存 (ベクター画像)
plt.show() # グラフを画面に表示する (保存後でも良い)
“`
plt.savefig()
の最初の引数にファイル名を指定します。拡張子によって保存形式が自動的に判断されますが、format
引数で明示的に指定することも可能です。
保存時のオプション
dpi
: 解像度を指定します。特にPNGやJPGなどのラスター形式で、高画質な画像を保存したい場合に重要です(例:dpi=300
)。デフォルトはFigureオブジェクトの設定によって異なります。bbox_inches
: 保存する際の余白を調整します。'tight'
を指定すると、グラフの周りの余白を最小限に抑えてくれます。タイトルやラベルが切れるのを防ぐためにもよく使われます。transparent
:True
にすると、背景を透明にして保存できます。PNG形式などで役立ちます。
“`python
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(6, 4))
x = np.arange(5)
y = [10, 15, 12, 18, 14]
ax.bar(x, y)
ax.set_title(‘Sample Bar Plot’)
ax.set_xlabel(‘Category’)
ax.set_ylabel(‘Value’)
高解像度で、余白をタイトにして保存
plt.savefig(‘sample_bar_plot_highres.png’, dpi=300, bbox_inches=’tight’)
背景を透明にしてPDFで保存
plt.savefig(‘sample_bar_plot_transparent.pdf’, transparent=True)
plt.show()
“`
plt.savefig()
は plt.show()
を呼び出す前に実行しても後に実行しても構いません。ただし、plt.show()
を呼び出した後にグラフが閉じられてしまう環境(例: スクリプトとして実行した場合)では、保存処理が正常に行われないことがあるため、通常は plt.show()
の前に plt.savefig()
を記述するのが安全です。Jupyter Notebookなどでは plt.show()
はグラフを表示するだけで閉じないのでどちらでも構いません。
より進んだカスタマイズとテクニック
Matplotlibは非常に多機能であり、ここでは紹介しきれないほど多くのカスタマイズオプションや高度なテクニックがあります。ここでは、いくつか知っておくと便利な応用的な使い方を紹介します。
スタイルの適用
Matplotlibには、あらかじめ定義されたグラフのスタイルがいくつか用意されています。これを使うと、手軽にグラフの見た目を変更できます。
plt.style.use()
関数を使ってスタイルを適用します。利用可能なスタイルは plt.style.available
で確認できます。
“`python
import matplotlib.pyplot as plt
import numpy as np
利用可能なスタイルを確認
print(plt.style.available)
‘seaborn-v0_8-darkgrid’ スタイルを適用
plt.style.use(‘seaborn-v0_8-darkgrid’)
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title(‘Sine Wave (Seaborn Style)’)
plt.xlabel(‘X Value’)
plt.ylabel(‘Y Value’)
styleにgridが含まれていればplt.grid()は不要な場合がある
plt.show()
別のスタイルを試す
plt.style.use(‘ggplot’)
plt.plot(x, y)
plt.title(‘Sine Wave (ggplot Style)’)
plt.xlabel(‘X Value’)
plt.ylabel(‘Y Value’)
plt.show()
デフォルトスタイルに戻す
plt.style.use(‘default’)
“`
スタイルを適用すると、線の色、太さ、グリッドの表示、フォントなどが一括で変更されます。データ分析の初期段階で様々なスタイルを試して、データの見え方を比較するのに便利です。
日本語表示の問題と解決策
Matplotlibのデフォルト設定では、日本語のタイトルやラベルが正しく表示されず、「豆腐」(□)になってしまうことがあります。これは、デフォルトで設定されているフォントが日本語グリフを含んでいないためです。
これを解決するには、日本語を表示できるフォントを明示的に指定する必要があります。使用できるフォントはOSや環境によって異なりますが、一般的には以下のような手順で設定します。
- 利用可能なフォントの確認: Matplotlibが認識しているフォントを確認します。
- 日本語フォントの指定: 日本語を含むフォント名を指定します。
“`python
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm # フォントマネージャーをインポート
Matplotlibのキャッシュをクリア (フォント設定変更後に必要になることがある)
import matplotlib
matplotlib.font_manager._rebuild()
利用可能なフォントをリストアップ (時間がかかる場合があります)
font_list = fm.findSystemFonts(fontpaths=None, fontext=’ttf’)
print([fm.FontProperties(fname=font).get_name() for font in font_list])
日本語フォントの指定 (OSによって適切なフォント名は異なります)
例: Windowsの場合 ‘Meiryo UI’ や ‘Yu Gothic’ など
例: macOSの場合 ‘Hiragino Maru Gothic ProN’ や ‘Hiragino Kaku Gothic ProN’ など
例: Linuxの場合 ‘DejaVu Sans’ や ‘IPAGothic’ など (フォントがインストールされている前提)
ここでは例として、よく使われるフォント名をいくつか試せるように記述
ご自身の環境で利用可能なフォント名に置き換えてください
jp_font_name = ‘IPA Gothic’ # 例: IPAexGothic なども
または ‘Meiryo’ (Windows), ‘Hiragino Gothic Pro N’ (macOS) など
rcParamsを使って全体フォントを設定
plt.rcParams[‘font.family’] = jp_font_name
plt.rcParams[‘axes.unicode_minus’] = False # 負の符号(マイナス)をUnicode文字で表示しない
テストプロット
plt.plot([1, 2, 3], [1, 4, 2])
plt.title(‘日本語タイトル’)
plt.xlabel(‘日本語X軸’)
plt.ylabel(‘日本語Y軸’)
凡例に日本語を含める場合もrcParams設定で表示可能
plt.plot([1, 2, 3], [3, 2, 1], label=’日本語データ’)
plt.legend()
plt.show()
“`
注意点:
- 指定したフォント名が環境に存在しない場合、エラーになったり、やはり豆腐になったりします。利用可能なフォント名を正確に確認してください。
- 一度
plt.rcParams
を変更すると、それ以降のすべてのグラフに適用されます。一時的に変更したい場合は、with plt.rc_context({'font.family': '...' }):
のようにコンテキストマネージャーを使うか、プロット後に設定を元に戻す必要があります。 axes.unicode_minus = False
は、負の数値のマイナス記号が豆腐になるのを防ぐための設定です。
日本語対応に関しては、Japanize-matplotlib
というライブラリを使うと、rcParamsの設定などを気にせず、インポートするだけで日本語表示を有効にできる場合があります。
bash
pip install japanize-matplotlib
“`python
import matplotlib.pyplot as plt
import japanize_matplotlib # この行を追加するだけで日本語対応
plt.plot([1, 2, 3], [1, 4, 2])
plt.title(‘日本語タイトル’)
plt.xlabel(‘日本語X軸’)
plt.ylabel(‘日本語Y軸’)
plt.legend([‘日本語データ’])
plt.show()
“`
こちらは非常に手軽な方法ですが、特定の環境やMatplotlibのバージョンによってはうまく動作しない可能性もあります。まずは plt.rcParams
でフォント指定する方法を理解しておくと、より確実に対応できるでしょう。
カラーマップ (Colormap)
散布図やヒストグラムの例でも少し触れましたが、カラーマップはデータの値を色にマッピングするために使われます。特に、数値の大小を色の濃淡や種類の違いで表現する際に効果的です。
cmap
引数でカラーマップ名を指定します。利用可能なカラーマップは Matplotlib のドキュメントで確認できます(https://matplotlib.org/stable/tutorials/colors/colormaps.html)。
“`python
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1)
x = np.random.rand(100) * 10
y = np.random.rand(100) * 10
sizes = np.random.rand(100) * 500
colors = np.random.rand(100) # 色をマッピングする数値データ
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
異なるカラーマップで散布図を描画
axes[0].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’viridis’)
axes[0].set_title(‘Colormap: viridis’)
fig.colorbar(axes[0].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’viridis’), ax=axes[0])
axes[1].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’plasma’)
axes[1].set_title(‘Colormap: plasma’)
fig.colorbar(axes[1].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’plasma’), ax=axes[1])
axes[2].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’coolwarm’) # 発散型のカラーマップ
axes[2].set_title(‘Colormap: coolwarm’)
fig.colorbar(axes[2].scatter(x, y, s=sizes, c=colors, alpha=0.7, cmap=’coolwarm’), ax=axes[2])
fig.suptitle(‘Scatter Plot with Different Colormaps’, y=1.02)
plt.tight_layout()
plt.show()
“`
カラーマップには、連続的なデータの変化に適したシーケンシャルなもの(viridis, plasma, jetなど)、中央値を基準にした発散に適したダイバージングなもの(coolwarm, seismicなど)、カテゴリ分けに適したQualitativeなものなどがあります。データの性質に応じて適切なカラーマップを選択することが重要です。
まとめ
この記事では、Pythonのデータ可視化ライブラリ Matplotlib の基本的な使い方から応用的なテクニックまでを幅広く解説しました。
- 導入: Matplotlibのインストール方法と、
import matplotlib.pyplot as plt
というおまじない。plt.plot()
とplt.show()
の基本フロー。 - 基本プロット: 線グラフ、散布図、棒グラフ、ヒストグラム、円グラフといった、データ分析で頻繁に利用される基本的なグラフの種類とそれぞれの描き方。
- カスタマイズ: タイトル、軸ラベル、凡例、軸の範囲や目盛りの設定方法。
plt.text()
やplt.annotate()
を使ったテキストや注釈の追加。 - FigureとAxes: Matplotlibの基本的なオブジェクトであるFigureとAxesの関係を理解し、オブジェクト指向スタイルによるグラフ作成の利点。
- 複数プロット:
plt.subplots()
を使って1つのFigure内に複数のAxesを配置する方法。 - データ連携: NumPy配列やPandas DataFrameといった、実データ分析でよく使うデータ構造とMatplotlibとの連携。Pandasの
.plot()
メソッドの手軽さ。 - 保存: 作成したグラフをファイルに保存する方法と、
dpi
,bbox_inches
,transparent
といった便利なオプション。 - 応用:
plt.style.use()
によるスタイルの適用、日本語表示の問題とその解決策、カラーマップの利用方法。
Matplotlibはその機能の豊富さゆえに学習コストが少し高いと感じられるかもしれませんが、この記事で紹介した基本を押さえれば、ほとんどのデータ可視化タスクに対応できるようになります。
データ可視化は、単にグラフを作るだけでなく、データから意味やストーリーを引き出し、それを他者に効果的に伝えるための重要なスキルです。Matplotlibを使いこなすことで、あなたのデータ分析能力は格段に向上するでしょう。
さらに深く学びたい場合は、Matplotlibの公式ドキュメントが最も信頼できる情報源です。また、データ可視化のより洗練された見た目や統計グラフに特化したSeabornなどのライブラリもMatplotlibを基盤としており、併せて学ぶことでさらに表現の幅が広がります。
この記事が、あなたのMatplotlib学習の助けとなり、データ可視化の楽しさを発見するきっかけとなれば幸いです。ぜひ、色々なデータを準備して、実際に手を動かしながら様々なグラフ作成に挑戦してみてください!