靳谷雪 发表于 2025-6-2 21:49:34

『Plotly实战指南』--布局进阶篇

在数据可视化领域,Plotly的子图布局是打造专业级仪表盘的核心武器。
当面对多维数据集时,合理的子图布局能显著提升多数据关联分析效率,让数据的呈现更加直观和美观。
本文将深入探讨Plotly中子图布局技巧,并结合代码实现与实际场景案例,介绍多子图组织方法的技巧。
多子图布局

网格布局

网格布局是Plotly中实现多子图排列的一种常见方式,通过make_subplots函数,我们可以轻松创建行列对齐的子图。
例如,设置rows=2, cols=3,就可以生成一个2行3列的子图网格,这种方式的好处是子图的尺寸会自动分配,
而且我们还可以通过horizontal_spacing和vertical_spacing参数来调整子图之间的水平和垂直间距,从而让整个布局更加紧凑和美观。
from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=2, cols=3, horizontal_spacing=0.2, vertical_spacing=0.2)

fig.add_trace(go.Scatter(x=, y=), row=1, col=1)
fig.add_trace(go.Scatter(x=, y=), row=1, col=2)
fig.add_trace(go.Scatter(x=, y=), row=1, col=3)
fig.add_trace(go.Scatter(x=, y=), row=2, col=1)
fig.add_trace(
    go.Scatter(x=, y=), row=2, col=2
)
fig.add_trace(
    go.Scatter(x=, y=), row=2, col=3
)

fig.show()
自由布局

自由布局则给予了我们更大的灵活性,通过domain参数,我们可以手动设置子图的位置,即指定子图在图表中的x和y坐标范围。
这种方式非常适合实现一些非对齐排列的子图布局,比如主图与缩略图的组合。
我们可以将主图放在较大的区域,而将缩略图放在角落,通过这种方式来辅助展示数据的局部细节。
# 自由布局

import plotly.graph_objects as go

# 自由布局示例
fig_free = go.Figure()

# 添加第一个子图
fig_free.add_trace(go.Scatter(x=, y=, name="Trace 1"))

# 添加第二个子图
fig_free.add_trace(go.Scatter(x=, y=, name="Trace 2"))

# 更新布局,定义每个子图的domain
fig_free.update_layout(
    xaxis=dict(domain=),# 第一个子图占据左侧70%
    yaxis=dict(domain=),    # 第一个子图占据整个高度
    xaxis2=dict(domain=, anchor="y2"),# 第二个子图占据右侧30%
    yaxis2=dict(domain=, anchor="x2")   # 第二个子图在右侧上方
)

# 更新每个trace的坐标轴引用
fig_free.update_traces(xaxis="x1", yaxis="y1", selector={"name": "Trace 1"})
fig_free.update_traces(xaxis="x2", yaxis="y2", selector={"name": "Trace 2"})

fig_free.show()
子图共享坐标轴

在多子图的情况下,共享坐标轴是一个非常实用的功能,通过设置shared_xaxes=True或shared_yaxes=True,可以让多个子图在同一个坐标轴上进行联动。
这样,当我们在一个子图上进行缩放或平移操作时,其他共享相同坐标轴的子图也会同步更新,从而方便我们进行多数据的对比分析。
此外,当遇到不同量纲的数据时,我们还可以通过secondary_y=True来独立控制次坐标轴,避免因量纲冲突而导致图表显示不清晰。
fig = make_subplots(
    rows=2,
    cols=1,
    shared_xaxes=True,
    specs=[[{"secondary_y": True}], [{}]],
)

fig.add_trace(go.Scatter(x=, y=), row=1, col=1)
fig.add_trace(go.Scatter(x=, y=), row=1, col=1, secondary_y=True)
fig.add_trace(go.Scatter(x=, y=), row=2, col=1)

fig.show()
实战案例

下面两个案例根据实际情况简化而来,主要演示布局如何在实际项目中使用。
股票多指标分析仪表盘

示例中先构造一些模拟数据,然后采用3行1列的布局模式来显示不同的股票信息。
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd

# 模拟股票数据
df = pd.DataFrame(
    {
      "date": pd.date_range(start="2023-01-01", periods=100),
      "price": ,
      "volume": ,
      "rsi": ,
    }
)

# 1. 创建3行1列的子图布局
fig = make_subplots(
    rows=3,
    cols=1,
    shared_xaxes=True,# 共享x轴
    vertical_spacing=0.05,# 子图间距
    subplot_titles=("价格趋势", "成交量", "RSI 指标"),
)

# 2. 添加价格走势图
fig.add_trace(
    go.Candlestick(
      x=df["date"],
      open=df["price"] * 0.99,
      high=df["price"] * 1.02,
      low=df["price"] * 0.98,
      close=df["price"],
      name="股票价格",
    ),
    row=1,
    col=1,
)

# 3. 添加成交量柱状图
fig.add_trace(
    go.Bar(x=df["date"], y=df["volume"], name="成交量", marker_color="lightgray"),
    row=2,
    col=1,
)

# 4. 添加RSI指标图
fig.add_trace(
    go.Scatter(x=df["date"], y=df["rsi"], name="RSI", line=dict(color="blue")),
    row=3,
    col=1,
)

# 5. 更新布局设置
fig.update_layout(
    title_text="多指标仪表盘",
    height=800,
    margin=dict(l=20, r=20, t=80, b=20),
    # 主图坐标轴配置
    xaxis=dict(domain=, rangeslider_visible=False),
    # 成交量图坐标轴
    xaxis2=dict(domain=, matches="x"),
    # RSI图坐标轴
    xaxis3=dict(domain=, matches="x"),
    # 公共y轴配置
    yaxis=dict(domain=, showticklabels=False),
    yaxis2=dict(domain=, showticklabels=False),
    yaxis3=dict(domain=, tickformat=".0%"),
)

# 6. 添加形状标注
fig.add_shape(
    type="line",
    x0="2023-01-01",
    y0=30,
    x1="2023-04-10",
    y1=70,
    line=dict(color="red", width=2, dash="dash"),
)

fig.show()
这是单列的布局,如果指标多的话,可以用多列的网格布局方式来布局。
物联网设备状态监控

这个示例采用自由布局实现主监控图+4个状态指标环绕。
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np

# 模拟设备数据
np.random.seed(42)
device_data = {
    "timestamp": np.arange(100),
    "temp": 25 + np.random.normal(0, 2, 100),
    "pressure": 100 + np.random.normal(0, 5, 100),
    "vibration": np.random.exponential(0.5, 100),
}

# 1. 创建2行2列的子图布局
fig = make_subplots(
    rows=2,
    cols=2,
    subplot_titles=("温度", "压力", "振动", "状态"),
    specs=[
      [{"type": "scatter"}, {"type": "scatter"}],
      [{"type": "scatter"}, {"type": "indicator"}],
    ],
)

# 2. 添加温度折线图
fig.add_trace(
    go.Scatter(
      x=device_data["timestamp"],
      y=device_data["temp"],
      mode="lines+markers",
      name="温度 (°C)",
      line=dict(color="firebrick"),
    ),
    row=1,
    col=1,
)

# 3. 添加压力散点图
fig.add_trace(
    go.Scatter(
      x=device_data["timestamp"],
      y=device_data["pressure"],
      mode="markers",
      name="压力 (kPa)",
      marker=dict(size=8, color="royalblue", opacity=0.7),
    ),
    row=1,
    col=2,
)

# 4. 添加振动频谱图
fig.add_trace(
    go.Scatter(
      x=device_data["timestamp"],
      y=device_data["vibration"],
      mode="lines",
      name="振动 (g)",
      line=dict(color="forestgreen"),
    ),
    row=2,
    col=1,
)

# 5. 添加状态指示器
fig.add_trace(
    go.Indicator(
      mode="gauge+number",
      value=85,
      domain={"x": , "y": },
      title="系统健康 (%)",
      gauge={
            "axis": {"range": },
            "bar": {"color": "gold"},
            "steps": [
                {"range": , "color": "red"},
                {"range": , "color": "orange"},
                {"range": , "color": "green"},
            ],
      },
    ),
    row=2,
    col=2,
)

# 6. 更新布局设置
fig.update_layout(
    title_text="IoT 设备监控仪表盘",
    height=600,
    margin=dict(l=20, r=20, t=80, b=20),
    showlegend=False,
    # 温度图坐标轴
    xaxis=dict(domain=, showgrid=False),
    yaxis=dict(domain=, showgrid=False),
    # 压力图坐标轴
    xaxis2=dict(domain=, showgrid=False),
    yaxis2=dict(domain=, showgrid=False),
    # 振动图坐标轴
    xaxis3=dict(domain=, showgrid=False),
    yaxis3=dict(domain=, showgrid=False),
)

fig.show()
总结

在Plotly中,子图布局对于创建高质量的数据可视化作品至关重要。
在实际应用中,对于复杂的仪表盘项目,优先采用网格布局可以保证子图之间的对齐和一致性;而对于一些创意性的场景,自由布局则能够更好地发挥我们的想象力。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 『Plotly实战指南』--布局进阶篇