14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【matplotlib】2次元ヒートマップを3次元で表示する方法

Last updated at Posted at 2021-12-30

概要

matplotlibで作成した2次元ヒートマップをmatplotlibで3次元で表示する方法を紹介します。
また、番外編ですがPlotlyを使い、インタラクティブな3次元のグラフを作成する方法も紹介します。
Google Colabで作成したコードは、こちらにあります。

手順

  1. 各種インポートします。(各モジュールの実行時のversionは、Google Colab内で作成したコードにあります。)
  2. 2次元ヒートマップに使う2次元配列を用意します。
  3. 2次元配列をimshowを使い、2次元ヒートマップで表示します。
  4. matplotlibのAxes3Dを使い、3次元で表示します。
  5. (番外編)Plotlyを使い、matplotlibで作ったグラフをインタラクティブな3次元のグラフで表示します。

1. 各種インポート

各種インポート
import numpy as np
from matplotlib.image import imread
import matplotlib.pyplot as plt
import matplotlib.colors
from mpl_toolkits.mplot3d import Axes3D
import plotly.graph_objects as go

各モジュールの実行時のversionは、Google Colab内で作成したコードこちらにあります。

2. 2次元ヒートマップに使う2次元配列を用意

適当なサンプルの2次元配列を用意します。

サンプルとして使う、2次元ヒートマップ用の2次元配列
def func(x, y):
    z = 0.01*(x*np.sin(0.1*x) + y*np.cos(0.1*y))
    return z

y_shape, x_shape = (50, 100)
image = np.empty((y_shape, x_shape))
for y in range(y_shape):
    for x in range(x_shape):
        image[y][x] = func(x, y)

3. matplotlibのimshowを使い、2次元ヒートマップで表示

2次元ヒートマップで表示
fig = plt.figure(figsize=(8, 4))
ax = fig.add_subplot(111)
color = ax.imshow(image, cmap='CMRmap', origin='lower')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.colorbar(color, shrink=0.8, label='z')
plt.show()

出力結果
Unknown-31.png

4. matplotlibのAxes3Dで3次元で表示

x軸とy軸の縮尺を統一するために、共通の軸の範囲ax.set_xlim(0, np.max(image.shape))
ax.set_ylim(0, np.max(image.shape))を使います。

2次元ヒートマップを3次元で表示
fig = plt.figure(figsize=(13, 10))
ax = fig.add_subplot(111, projection='3d')
# 格子点を生成
y, x = np.mgrid[:image.shape[0], :image.shape[1]]
color = ax.plot_surface(x, y, image, cmap='CMRmap',
                        edgecolor='k', rstride=5, cstride=5)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_xlim(0, np.max(image.shape))
ax.set_ylim(0, np.max(image.shape))
cbar = plt.colorbar(color, shrink=0.6, label='z')
plt.show()

出力結果
Unknown-32.png

角度を変えたい場合

ax.view_init()を使うと、任意の角度で表示できます。

fig = plt.figure(figsize=(13, 10))
# 3Dプロット
ax = fig.add_subplot(111, projection='3d')
y, x = np.mgrid[:image.shape[0], :image.shape[1]]
color = ax.plot_surface(x, y, image, cmap='CMRmap',
                        edgecolor='k', rstride=5, cstride=5)
ax.view_init(80, 270)  # 表示角度の追加, ax.view_init(縦方向の角度, 横方向の角度)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_xlim(0, np.max(image.shape))
ax.set_ylim(0, np.max(image.shape))
cbar = plt.colorbar(color, shrink=0.6, label='z')
plt.show()

出力結果
Unknown-33.png

5. (番外編)Plotlyを使い、matplotlibで作ったグラフをインタラクティブな3次元のグラフで表示

Plotlyを使い、インタラクティブな3次元で表示
fig = go.Figure(go.Surface(
    x=np.arange(image.shape[1]),
    y=np.arange(image.shape[0]),
    z=image,
    opacity=1.0,  # 透明度(透明0-1不透明)
    colorbar=dict(title='z')  # colorbarのタイトル
    ))
fig.update_layout(
    scene=dict(
        xaxis=dict(nticks=10, range=[0,np.max(image.shape)],),  # x軸の範囲
        yaxis=dict(nticks=10, range=[0,np.max(image.shape)],),  # y軸の範囲
        ),
    width=700,  # インライン表示の横幅のエリア
    height=700,  # インライン表示の縦幅のエリア
    margin=dict(l=50, r=50, b=50, t=50)
    )
# 等高線の表示
'''パラメータ
show : グラフと面に常に等高線を表示するか
usecolormap : 等高線にカラーマップの色を表示するか
highlightcolor : colorの色
project_z : 面に等高線を投影するか
'''
fig.update_traces(contours_z=dict(show=True, usecolormap=True,
                                  highlightcolor='limegreen',
                                  project_z=True
                                  ))
fig.show()

出力結果
plotly_image.gif

Google Colab内でもインタラクティブに動きます。

まとめ

matplotlibで作成した2次元ヒートマップを3次元で表示する方法を紹介しましたが、2次元ヒートマップの良さもあるので、状況によって使い分けましょう。
3次元は角度によって見えない領域があるので、番外編で紹介したPlotlyが3次元を表示するのに便利です。

参考資料

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?