1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Plotly] 3D空間に立方体(Bounding Box)ガイドを追加:データ範囲を直感的に把握する3D可視化

Posted at

はじめに

3D散布図やライン・Surfaceを描くとき、「このデータはどの範囲に分布しているのか?」を理解しづらいことがあります。

そこで Bounding Box(境界立方体) を描くと、全体のスケール・外れ値・広がりが一瞬でつかめます。

Plotly では Scatter3d の"線モード"を使うことで、軽量で美しい立方体ガイドが作れます。

highlight.png

この記事でできること

  • 3D空間に「立方体ガイド(Bounding Box)」を追加
  • 点群やラインの分布範囲を立体的に把握
  • 外れ値検知・可視化の文脈で活用
  • Colabですぐ動くコードつき

① データ例:3D点群を準備

import plotly.graph_objects as go
import numpy as np

np.random.seed(0)
x, y, z = np.random.randn(3, 300)

この点群を包む「立方体ガイド」を描いていきます。


② Bounding Box を描くための"8頂点"を作成

x, y, z の 最小値/最大値 を使って立方体を定義します。

xmin, xmax = x.min(), x.max()
ymin, ymax = y.min(), y.max()
zmin, zmax = z.min(), z.max()

# 8つの頂点
corners = np.array([
    [xmin, ymin, zmin],
    [xmin, ymin, zmax],
    [xmin, ymax, zmin],
    [xmin, ymax, zmax],
    [xmax, ymin, zmin],
    [xmax, ymin, zmax],
    [xmax, ymax, zmin],
    [xmax, ymax, zmax],
])

③ Bounding Box の"12本の辺"を結ぶ

立方体には 12 本のエッジ があります。頂点番号を組み合わせて線を引きます。

edges = [
    (0,1), (0,2), (0,4),
    (3,1), (3,2), (3,7),
    (5,1), (5,4), (5,7),
    (6,2), (6,4), (6,7)
]

④ Plotly の Scatter3d(mode="lines") で立方体を描画

fig = go.Figure()

# 点群
fig.add_trace(go.Scatter3d(
    x=x, y=y, z=z,
    mode='markers',
    marker=dict(size=3, color=z, colorscale='Viridis', opacity=0.7),
    name='Points'
))

# Bounding Box
for e in edges:
    xs = [corners[e[0], 0], corners[e[1], 0]]
    ys = [corners[e[0], 1], corners[e[1], 1]]
    zs = [corners[e[0], 2], corners[e[1], 2]]
    fig.add_trace(go.Scatter3d(
        x=xs, y=ys, z=zs,
        mode='lines',
        line=dict(color='black', width=4),
        showlegend=False
    ))

fig.update_layout(
    title="3D Scatter with Bounding Box",
    scene=dict(aspectmode='data')
)

fig.show()

newplot (1).png

黒い線で囲まれた立方体が表示され、データの空間的な広がりが直感的に理解できます。


⑤ 軽量な"ワイヤーボックス"にする

見やすさ&軽量化のため、細いグレー線に変更する例:

line_style = dict(color='gray', width=2)

for e in edges:
    fig.add_trace(go.Scatter3d(
        x=[corners[e[0],0], corners[e[1],0]],
        y=[corners[e[0],1], corners[e[1],1]],
        z=[corners[e[0],2], corners[e[1],2]],
        mode='lines',
        line=line_style,
        showlegend=False
    ))

newplot (2).png

データ可視化時の"補助ガイド"として最適です。


⑥ Bounding Box を"正方立方体"にする(統一スケール)

比率を揃えて 見た目の歪みを防ぐ 方法です。

min〜max を 同じ長さ に揃えます。

min_val = min(xmin, ymin, zmin)
max_val = max(xmax, ymax, zmax)

# Bounding Box の corners も立方体に再計算
corners = np.array([
    [min_val, min_val, min_val],
    [min_val, min_val, max_val],
    [min_val, max_val, min_val],
    [min_val, max_val, max_val],
    [max_val, min_val, min_val],
    [max_val, min_val, max_val],
    [max_val, max_val, min_val],
    [max_val, max_val, max_val],
])

# 全軸を同じ範囲に揃える(視覚的に正方立方体)
fig.update_layout(
    scene=dict(
        xaxis=dict(range=[min_val, max_val]),
        yaxis=dict(range=[min_val, max_val]),
        zaxis=dict(range=[min_val, max_val]),
        aspectmode='cube'
    )
)

newplot (3).png

  • Bounding Box 自体が「立方体」になる
  • 空間が「立方体」に統一されるため違和感がなくなる
  • 3D分布比較に便利

⑦ Mesh3d で"透明な立方体Surface"を追加する

Bounding Box を 面付きの透明立方体 にする表現です。

go.Mesh3d を使って立方体の6面(12三角形)を定義します。

# 立方体の6面を12個の三角形で定義
# 各面(下面・上面・前面・後面・左面・右面)を2つの三角形で構成
i = [0, 2, 1, 3, 0, 1, 2, 3, 0, 1, 4, 5]
j = [2, 4, 3, 5, 1, 4, 3, 6, 1, 2, 5, 6]
k = [4, 6, 5, 7, 4, 5, 6, 7, 2, 3, 6, 7]

fig.add_trace(go.Mesh3d(
    x=corners[:, 0],
    y=corners[:, 1],
    z=corners[:, 2],
    i=i, j=j, k=k,
    opacity=0.1,
    color='lightblue',
    flatshading=True,
    showscale=False
))

特徴:

  • 立体感UP
  • 視認性アップ
  • Surface や点群との相性がよい
  • 軽量で確実に立方体が描画される

⑧ 背景・軸を整えて視認性を高める

fig.update_layout(
    scene=dict(
        xaxis=dict(backgroundcolor='rgb(245,245,245)'),
        yaxis=dict(backgroundcolor='rgb(245,245,245)'),
        zaxis=dict(backgroundcolor='rgb(250,250,250)'),
        aspectmode='data'
    )
)

newplot (4).png

特に線ガイドは背景が明るい方が見やすくなります。


トラブルシュート

問題 解決方法
Box が歪む aspectmode='cube' を使う
Box の線が太すぎ width を 1〜3 に調整
点群と色がかぶる line.color を gray に
スケールが見づらい 軸範囲を [min_val,max_val] で揃える

まとめ

summary.png

Bounding Box を追加すると、3Dデータの分布範囲が直感的に把握できるようになります。

基本は Scatter3d(mode="lines") で12本の線を描くだけで、必要に応じて透明な立方体(Mesh3d)も作成できます。

aspectmode="cube" にすれば歪みのない立方体表示になり、外れ値検知やスケール比較、シミュレーション可視化にも役立ちます。3D空間に“枠”を入れるだけで、データの理解が一段と進みます。

動画解説

参考リンク

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?