サイトアイコン アマチュア無線局JS2IIU

【matplotlib】colormapでデータを見やすく可視化しよう!(見本帳あり)

こんにちは、JS2IIUです。
Matplotlibでグラフを作成する際、データの値を色で表現したい場合があります。そんな時に役立つのが colormap です。colormapは、数値と色を対応づけるもので、データの分布や変化を視覚的に表現するのに非常に役立ちます。

例えば、気温の分布を地図上に表示する場合、低い気温を青色、高い気温を赤色で表示することで、直感的に気温の分布を理解することができます。

colormapの種類

Matplotlibには、様々なcolormapが用意されています。大きく分けて、以下の種類があります。

colormapの選択

colormapは、データの性質や可視化の目的に合わせて適切なものを選択する必要があります。

例えば、連続的な値の変化を表現する場合には、Sequentialなcolormapが適しています。また、正負の値を異なる色で表現する場合には、Divergingなcolormapが適しています。

colormapの選択に迷った場合は、以下のサイトを参考にしてみてください。

Perceptually Uniform Sequential

Sequential

Sequential (2)

Diverging

Cyclic

Qualitative

Miscellaneous

colormapを使ってみよう

それでは、実際にcolormapを使ってグラフを作成してみましょう。今回は、身長、体重、年齢のデータを使って、年齢を色で表現した散布図を作成します。

サンプルプログラム

Python
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# サンプルデータの作成
np.random.seed(0)
data = {
    'Height': np.random.normal(170, 10, 100),
    'Weight': np.random.normal(60, 10, 100),
    'Age': np.random.randint(20, 60, 100)
}
df = pd.DataFrame(data)

# colormap list
cmaps = [
    ('Perceptually Uniform Sequential',
     ['viridis', 'plasma', 'inferno', 'magma', 'cividis']),
    ('Sequential',
     ['Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
      'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
      'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
    ('Sequential (2)',
     ['binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
      'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
      'hot', 'afmhot', 'gist_heat', 'copper']),
    ('Diverging',
     ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
      'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
    ('Cyclic', ['twilight', 'twilight_shifted', 'hsv']),
    ('Qualitative',
     ['Pastel1', 'Pastel2', 'Paired', 'Accent',
      'Dark2', 'Set1', 'Set2', 'Set3',
      'tab10', 'tab20', 'tab20b', 'tab20c']),
    ('Miscellaneous',
     ['flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
      'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
      'gist_rainbow', 'rainbow', 'jet', 'turbo', 'nipy_spectral',
      'gist_ncar'])
]

for i in range(len(cmaps)):
    n_row = len(cmaps[i][1]) // 3
    if len(cmaps[i][1]) % 3 != 0:
        n_row += 1
    n_col = 3

    # グラフの大きさを調整
    fig, axes = plt.subplots(n_row, n_col, figsize=(n_col * 4, n_row * 4))

    # If axes is 1-dimensional, convert it to 2-dimensional
    if n_row == 1:
        axes = axes.reshape(1, -1)  # Reshape to (1, n_col)

    for j in range(len(cmaps[i][1])):
        cmap = cmaps[i][1][j]
        ax = axes[j // n_col, j % n_col]
        scatter = ax.scatter(df['Height'], df['Weight'], c=df['Age'], cmap=cmap)
        ax.set_title(f'{cmaps[i][0]} - {cmap}')
        ax.set_xlabel('Height')
        ax.set_ylabel('Weight')
        ax.grid(True)

        # カラーバーを追加
        fig.colorbar(scatter, ax=ax)

    plt.tight_layout()
    plt.savefig(f'{cmaps[i][0]}.png')

プログラムの解説

RuntimeWarningが出る場合

上記のサンプルプログラムを実行すると、次のようなメッセージが表示される場合があります。

Bash
RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.

この警告は、Matplotlibで多くのfigureを作成し、明示的に閉じずにそのままにしているために発生しています。Matplotlibは、plt.figure() で作成されたfigureをメモリに保持し続けるため、多くのfigureを開いたままにするとメモリを大量に消費する可能性があります。

今回のプログラムでは、colormapの種類ごとに複数の画像ファイルを出力しています。その際に、 plt.figure() で作成されたfigureがループ内で繰り返し作成され、明示的に閉じられていないため、警告が発生していると考えられます。

修正案としては、 plt.close() を使用して、figureを明示的に閉じるようにします。具体的には、 plt.savefig() の後に plt.close() を追加します。

修正後のサンプルプログラムは以下のとおりです。

Python
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# サンプルデータの作成
np.random.seed(0)
data = {
    'Height': np.random.normal(170, 10, 100),
    'Weight': np.random.normal(60, 10, 100),
    'Age': np.random.randint(20, 60, 100)
}
df = pd.DataFrame(data)

# colormap list
cmaps = [
    ('Perceptually Uniform Sequential',
     ['viridis', 'plasma', 'inferno', 'magma', 'cividis']),
    ('Sequential',
     ['Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
      'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
      'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
    ('Sequential (2)',
     ['binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
      'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
      'hot', 'afmhot', 'gist_heat', 'copper']),
    ('Diverging',
     ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
      'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
    ('Cyclic', ['twilight', 'twilight_shifted', 'hsv']),
    ('Qualitative',
     ['Pastel1', 'Pastel2', 'Paired', 'Accent',
      'Dark2', 'Set1', 'Set2', 'Set3',
      'tab10', 'tab20', 'tab20b', 'tab20c']),
    ('Miscellaneous',
     ['flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
      'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
      'gist_rainbow', 'rainbow', 'jet', 'turbo', 'nipy_spectral',
      'gist_ncar'])
]

for i in range(len(cmaps)):
    n_row = len(cmaps[i][1]) // 3
    if len(cmaps[i][1]) % 3 != 0:
        n_row += 1
    n_col = 3

    # グラフの大きさを調整
    fig, axes = plt.subplots(n_row, n_col, figsize=(n_col * 4, n_row * 4))

    # If axes is 1-dimensional, convert it to 2-dimensional
    if n_row == 1:
        axes = axes.reshape(1, -1)  # Reshape to (1, n_col)

    for j in range(len(cmaps[i][1])):
        cmap = cmaps[i][1][j]
        ax = axes[j // n_col, j % n_col]
        scatter = ax.scatter(df['Height'], df['Weight'], c=df['Age'], cmap=cmap)
        ax.set_title(f'{cmaps[i][0]} - {cmap}')
        ax.set_xlabel('Height')
        ax.set_ylabel('Weight')
        ax.grid(True)

        # カラーバーを追加
        fig.colorbar(scatter, ax=ax)

    plt.tight_layout()
    plt.savefig(f'{cmaps[i][0]}.png')

    # figureを明示的に閉じる
    plt.close()

まとめ

colormapは、データを色で表現することで、データの分布や変化を視覚的に表現するのに役立ちます。Matplotlibには、様々なcolormapが用意されているので、データの性質や可視化の目的に合わせて適切なものを選択しましょう。

最後まで読んでいただきありがとうございました。

モバイルバージョンを終了