You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly 3D图表中绘制2D柱状图的实现方案

Plotly 3D画布绘制分面2D柱状图实现方案

Plotly 3D场景暂未内置原生柱状图类型,通过Mesh3d图元手动构造柱体网格是兼容性最好的实现方式,完全支持原生的旋转、缩放、悬停交互,效果和Matplotlib实现的参考效果一致。

Matplotlib版本参考效果

核心实现逻辑

  • 每个柱体为固定y轴位置(对应单条轨迹)的薄长方体
  • x轴方向:对应日期维度,柱体宽度设为0.7个日期间隔,避免相邻柱重叠
  • y轴方向:对应轨迹维度,柱体厚度设为0.3个轨迹间隔,不同轨迹的柱子沿y轴排布互不遮挡
  • z轴方向:对应指标数值,柱体高度直接映射指标大小
  • 提前预定义长方体的三角剖分索引,不用每次做自动三角剖分,渲染效率更高

可直接运行的完整代码

import plotly.graph_objects as go
import pandas as pd
import numpy as np

# ---------------------- 1. 模拟测试数据 可替换成自己的业务数据 ----------------------
# 轨迹列表
trace_names = ["轨迹A", "轨迹B", "轨迹C"]
# 日期维度
dates = pd.date_range(start="2024-01-01", end="2024-01-07")
# 随机生成指标值
np.random.seed(42)
df = pd.DataFrame({
    "date": np.repeat(dates, len(trace_names)),
    "trace": np.tile(trace_names, len(dates)),
    "value": np.random.randint(low=10, high=100, size=len(dates)*len(trace_names))
})
# 把分类维度映射成数值坐标
trace_y_map = {name:i for i, name in enumerate(trace_names)}
df["y_pos"] = df["trace"].map(trace_y_map)
df["x_pos"] = df["date"].astype(np.int64) // 10**9  # 日期转时间戳作为x数值坐标

# 柱体尺寸配置
bar_width_x = 0.7 * 86400  # x方向宽度 对应0.7天的时间戳长度
bar_thickness_y = 0.3      # y方向厚度
# 预定义长方体的12个三角面索引 固定复用
cube_faces = [
    [0,1,2], [0,2,3],  # 底面
    [4,5,6], [4,6,7],  # 顶面
    [0,1,5], [0,5,4],  # 前侧面
    [2,3,7], [2,7,6],  # 后侧面
    [0,3,7], [0,7,4],  # 左侧面
    [1,2,6], [1,6,5]   # 右侧面
]
# 轨迹配色
trace_colors = ["#1f77b4", "#ff7f0e", "#2ca02c"]

# ---------------------- 2. 生成每个柱体的Mesh3d轨迹 ----------------------
fig = go.Figure()
for _, row in df.iterrows():
    x0 = row["x_pos"] - bar_width_x/2
    x1 = row["x_pos"] + bar_width_x/2
    y0 = row["y_pos"] - bar_thickness_y/2
    y1 = row["y_pos"] + bar_thickness_y/2
    z0 = 0
    z1 = row["value"]
    # 长方体8个顶点坐标
    x_verts = [x0, x1, x1, x0, x0, x1, x1, x0]
    y_verts = [y0, y0, y1, y1, y0, y0, y1, y1]
    z_verts = [z0, z0, z0, z0, z1, z1, z1, z1]
    # 展开面索引
    i_idx, j_idx, k_idx = [], [], []
    for face in cube_faces:
        i_idx.append(face[0])
        j_idx.append(face[1])
        k_idx.append(face[2])
    # 添加柱体到画布
    fig.add_trace(go.Mesh3d(
        x=x_verts,
        y=y_verts,
        z=z_verts,
        i=i_idx,
        j=j_idx,
        k=k_idx,
        color=trace_colors[trace_y_map[row["trace"]]],
        opacity=0.9,
        hovertemplate=f"日期: {row['date'].date()}<br>轨迹: {row['trace']}<br>数值: {row['value']}<extra></extra>"
    ))

# ---------------------- 3. 坐标轴配置 还原分类轴效果 ----------------------
fig.update_layout(
    scene=dict(
        xaxis=dict(
            title="日期",
            tickmode="array",
            tickvals=df["x_pos"].unique(),
            ticktext=[d.date() for d in dates]
        ),
        yaxis=dict(
            title="轨迹名称",
            tickmode="array",
            tickvals=list(trace_y_map.values()),
            ticktext=list(trace_y_map.keys())
        ),
        zaxis=dict(title="指标数值"),
        camera=dict(eye=dict(x=1.5, y=1.5, z=1.2))  # 初始视角 可按需调整
    ),
    margin=dict(l=0, r=0, t=30, b=0),
    showlegend=False
)

fig.show()

自定义调整说明

  • 替换数据:把模拟数据部分换成自己的数据集即可,只要保证每条数据对应一个(日期、轨迹、数值)三元组
  • 柱体尺寸:调整bar_width_x和bar_thickness_y参数可以修改柱子的宽窄厚薄,适配自己的数据密度
  • 配色:修改trace_colors列表可以自定义不同轨迹的柱体颜色
  • 初始视角:修改camera.eye参数可以调整打开图表时的默认观察角度

内容的提问来源于stack exchange,提问作者mark377

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:18:15