Plotly子图实现按Dip编号分色的速度、温度垂直剖面并排绘制
问题根因
你之前用make_subplots搭配go.Scatter无法实现自动分色,核心是**color="Dip No."是plotly.express的高层封装能力,不是原生go.Scatter的内置参数**。px在后台会自动按指定分组字段拆分数据集,为每个独立分组生成单独绘图trace,并调用内置离散色板为每个trace分配差异化颜色。而原生go.Scatter不会自动做分组拆分,直接传入整份DataFrame时,所有数据会被合并为一个trace,自然只能显示统一颜色。
最省心的实现方案:复用px已生成的trace迁移到子图布局
这个方案完全不需要手动写分组循环、手动匹配颜色,100%复刻你之前独立绘图的分色、样式逻辑,改造成本最低:
- 先按照你之前的逻辑,用px分别生成深度-速度、深度-温度两个独立的临时绘图对象,保留原有的Depth取反、深色主题配置
- 构建1行2列的子图画布
- 把两个临时绘图对象里的所有trace,逐个挂载到子图的对应位置
- 统一调整坐标轴标签、图例显示逻辑,避免冗余
可直接运行的参考代码:
import plotly.express as px from plotly.subplots import make_subplots # 完全复用你原有的px绘图逻辑 # 深度-速度独立图 fig_vel = px.line( df, x="Velocity", y=-df["Depth"], # 保留原有的深度取反适配逻辑 color="Dip No.", # 自动按观测批次分色的逻辑完全保留 template="plotly_dark" ) # 深度-温度独立图 fig_temp = px.line( df, x="Temperature", y=-df["Depth"], color="Dip No.", template="plotly_dark" ) # 构建1行2列的子图画布 fig = make_subplots(rows=1, cols=2, subplot_titles=("深度-速度剖面", "深度-温度剖面")) # 将两个px图的trace迁移到对应子图位置 for trace in fig_vel.data: fig.add_trace(trace, row=1, col=1) for trace in fig_temp.data: fig.add_trace(trace, row=1, col=2) # 统一调整布局样式 fig.update_xaxes(title_text="Velocity", row=1, col=1) fig.update_xaxes(title_text="Temperature", row=1, col=2) fig.update_yaxes(title_text="Depth", row=1, col=1) fig.update_yaxes(title_text="", row=1, col=2) # 取消第二幅图的重复Y轴标签 fig.update_layout(template="plotly_dark", showlegend=True) fig.show()
原生go.Scatter实现路径:手动复刻px的分色逻辑
如果你希望完全基于go接口构建子图,不需要生成临时px对象,可以手动复现px的自动分组分色逻辑:
- 先提取
Dip No.字段的所有唯一观测批次 - 调用plotly内置离散色板为每个批次预分配差异化颜色
- 遍历每个批次筛选对应数据子集,单独添加到两个子图的对应位置,保证同一批次在两个子图上的颜色完全一致
参考代码片段:
import plotly.graph_objects as go # 提取所有观测批次 dip_groups = df["Dip No."].unique() # 调用plotly默认离散色板,自动保证颜色差异,无需手动指定 color_palette = px.colors.qualitative.Plotly for idx, dip_name in enumerate(dip_groups): subset = df[df["Dip No."] == dip_name] current_color = color_palette[idx % len(color_palette)] # 添加速度剖面trace fig.add_trace( go.Scatter( x=subset["Velocity"], y=-subset["Depth"], mode="lines", name=dip_name, line=dict(color=current_color), showlegend=(idx == 0) # 仅在第一个trace显示图例,避免重复 ), row=1, col=1 ) # 添加温度剖面trace fig.add_trace( go.Scatter( x=subset["Temperature"], y=-subset["Depth"], mode="lines", name=dip_name, line=dict(color=current_color), showlegend=False ), row=1, col=2 )
实现注意事项
- 两种方案都不需要手动为Dip1、Dip2指定固定配色,颜色差异化由内置色板自动保证
- 两个子图展示的是同一批观测的两类剖面,需要保证同一Dip批次的线条在两个子图上颜色完全一致,不能出现分色错位
- 深色主题的配置可以直接全局统一设置,不需要在每个trace上单独配置
内容的提问来源于stack exchange,提问作者WillH
相关产品推荐
相关产品推荐

