はじめに
この記事では、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軸を表現することで、空間構造を直感的に理解できます。
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()
→ カテゴリ(群)ごとに色分けし、凡例も自動表示されます。
応用例
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')
トラブルシュート
| 症状 | 対処 |
|---|---|
| グラフが出ない | Colabの出力リセット。セル再実行で改善 |
| 色が反映されない | colorscale のスペル確認(例:'Viridis') |
| 点が見えにくい | opacity や size を調整(小さい点が重なってることも) |
まとめ
go.Scatter3d()を使えば、Plotlyで手軽に3D散布図を描画できる。色・サイズ・透明度を組み合わせることで最大4次元まで表現でき、グループ化や時系列、特徴量分析などにも応用可能。軽量で高解像度、HTML形式での共有が容易な点も大きな魅力である。
x・y・zの数値が立体的に見えてくると、少しずつ空間の感覚がつかめてきます。そうした感覚を身につけることで、この先のサーフェスやベクトル場の理解もよりスムーズになると思います。





