4
2

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散布図(scatter3d)を描く】立体座標を直感的に理解する

Last updated at Posted at 2025-11-09

はじめに

image.png

この記事では、Plotlyの「3D散布図(scatter3d)」を使って
3次元座標を"見る"感覚で理解する方法を紹介します。
Google Colabでも動作確認でき、色や大きさで4次元目も表現可能です。

目的

Plotlyを使えば、3Dの点群(scatter3d)を描画して、x・y・z座標の関係を直感的に理解できます。さらに、点の色やサイズを変えることで、4次元的な情報も同時に表現できるようになります。

実装例(Colabでも動く)

import plotly.graph_objects as go
import numpy as np

# 乱数で3D座標を生成
np.random.seed(42)
x = np.random.randn(100)
y = np.random.randn(100)
z = np.random.randn(100)

# 3D散布図を作成
fig = go.Figure(data=[go.Scatter3d(
    x=x, y=y, z=z,
    mode='markers',
    marker=dict(
        size=5,
        color=z,                 # Z値を色に対応
        colorscale='Viridis',    # カラーマップ
        opacity=0.8
    )
)])

fig.update_layout(
    title="3D Scatter Plot: Random Points",
    scene=dict(aspectmode='data')
)
fig.show()

Colab上で回転・ズーム・ドラッグ可能
色でZ軸を表現することで、空間構造を直感的に理解できます。

image.png

image.png

scatter3dの構造を理解する

引数 役割
x, y, z 各点の座標値
mode='markers' 点として表示(線の場合はlines)
marker.size 点のサイズ
marker.color 点の色(連続値 or グループ)
colorscale 色マップの種類(Viridis, Plasma, Cividisなど)
opacity 透明度(0〜1)

Stepアップ:色とサイズで意味を持たせる

① 値に応じて色を変える

marker=dict(color=z, colorscale='Plasma', size=6, opacity=0.8)

→ 高さや温度、強度などの"量的情報"を色で表現。

② 値に応じてサイズも変える

marker=dict(size=(z - z.min()) * 5, color=z, colorscale='Cividis', opacity=0.8)

→ Zが大きいほど点を大きく表示。立体+大小で"データの重み"を感じられます。

③ グループごとに色分けする

group = np.random.choice(['A','B','C'], size=100)

fig = go.Figure()
for g, color in zip(['A','B','C'], ['red','green','blue']):
    mask = (group == g)
    fig.add_trace(go.Scatter3d(
        x=x[mask], y=y[mask], z=z[mask],
        mode='markers',
        marker=dict(size=5, color=color, opacity=0.7),
        name=f'Group {g}'
    ))

fig.update_layout(title='3D Scatter by Group', scene=dict(aspectmode='data'))
fig.show()

→ カテゴリ(群)ごとに色分けし、凡例も自動表示されます。

image.png

応用例

3D散布図はさまざまな分野で活用できる。たとえば、PCA後の分布を可視化してクラスタ構造を確認したり、機械学習モデルの中間層出力を立体的に表示して特徴量の意味を探ることができる。さらに、IoTやセンサーのデータを座標と値で表現したり、数学教育で3次元座標や点の距離の理解を深める用途にも適している。

軸や背景を整える

fig.update_layout(
    scene=dict(
        xaxis_title='X Axis',
        yaxis_title='Y Axis',
        zaxis_title='Z Axis',
        xaxis=dict(backgroundcolor='rgb(240,240,240)'),
        yaxis=dict(backgroundcolor='rgb(240,240,240)'),
        zaxis=dict(backgroundcolor='rgb(240,240,240)')
    )
)

背景を薄くするだけでも視認性が大幅アップ。
3D空間が"どっち向きか"がすぐ分かります。

時間変化をアニメーションで見る(おまけ)

import plotly.graph_objects as go
import numpy as np
from PIL import Image
import io
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

# Chrome設定
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--window-size=900,800')  # ウィンドウサイズを大きめに

driver = webdriver.Chrome(options=chrome_options)

# 乱数で3D座標を生成
np.random.seed(42)
x = np.random.randn(100)
y = np.random.randn(100)
z = np.random.randn(100)

frames_images = []

for i in range(30):
    angle = i * np.pi / 15
    x_new = x * np.cos(angle) - y * np.sin(angle)
    y_new = x * np.sin(angle) + y * np.cos(angle)

    fig = go.Figure(data=[go.Scatter3d(
        x=x_new, y=y_new, z=z,
        mode='markers',
        marker=dict(size=5, color=z, colorscale='Viridis', opacity=0.8)
    )])

    fig.update_layout(
        scene=dict(
            aspectmode='data',
            camera=dict(eye=dict(x=1.5, y=1.5, z=1.5))
        ),
        title=f"Frame {i+1}/30",
        width=800,
        height=700,  # 高さを増やす
        margin=dict(l=0, r=0, t=40, b=40)  # 上下のマージンを確保
    )

    # HTMLとして保存して画像化
    fig.write_html(f'temp_frame_{i}.html')
    driver.get(f'file:///content/temp_frame_{i}.html')
    time.sleep(1.5)  # 読み込み時間を少し長めに

    png = driver.get_screenshot_as_png()
    img = Image.open(io.BytesIO(png))

    # 画像をクロップして余白を削除(必要に応じて)
    # img = img.crop((0, 0, 800, 700))

    frames_images.append(img)

    if (i + 1) % 5 == 0:
        print(f"フレーム {i+1}/30 作成完了")

driver.quit()

# GIFとして保存
frames_images[0].save(
    'scatter3d_animation.gif',
    save_all=True,
    append_images=frames_images[1:],
    duration=100,
    loop=0
)

print("GIF保存完了")

from google.colab import files
files.download('scatter3d_animation.gif')

scatter3d_animation.gif

トラブルシュート

症状 対処
グラフが出ない Colabの出力リセット。セル再実行で改善
色が反映されない colorscale のスペル確認(例:'Viridis')
点が見えにくい opacity や size を調整(小さい点が重なってることも)

まとめ

image.png

go.Scatter3d()を使えば、Plotlyで手軽に3D散布図を描画できる。色・サイズ・透明度を組み合わせることで最大4次元まで表現でき、グループ化や時系列、特徴量分析などにも応用可能。軽量で高解像度、HTML形式での共有が容易な点も大きな魅力である。

x・y・zの数値が立体的に見えてくると、少しずつ空間の感覚がつかめてきます。そうした感覚を身につけることで、この先のサーフェスやベクトル場の理解もよりスムーズになると思います。

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?