如何用Plotly实现带固定节点的同步网络图与累积时序折线图
解决Plotly同步可视化的两个核心问题
问题1:网络图节点位置固定,仅更新颜色
问题根源
原代码为每个时间点创建独立的网络图Scatter trace,切换trace时易导致坐标轴范围变动,且存在冗余。正确思路是只保留一个网络图trace,通过滑块动态更新节点颜色属性,位置始终固定。
修改方案
- 仅添加一次网络图trace,设置固定x、y坐标
- 滑块的
update方法中,仅修改该trace的marker.color属性,而非切换trace可见性
问题2:折线图累积展示历史数据
问题根源
原代码为每个节点的每个时间点创建单独trace,导致滑块拖动时多个trace叠加显示,不符合累积展示需求。正确思路是每个节点仅创建一个trace,通过滑块动态扩展该trace的x、y数据至当前时间点的历史范围。
修改方案
- 每个节点仅添加一个初始trace(显示第一个时间点数据)
- 滑块的
update方法中,更新对应节点trace的x和y为times[:t+1]和activation_data[node][:t+1]
完整修正代码
import plotly.graph_objects as go from plotly.subplots import make_subplots import numpy as np # 示例激活数据 times = np.arange(0, 10, 0.5) nodes = ['A', 'B', 'C'] activation_data = { 'A': np.sin(times), 'B': np.cos(times), 'C': np.sin(times + np.pi / 4) } # 节点固定颜色 node_colors = { 'A': 'red', 'B': 'blue', 'C': 'green' } # 固定节点位置(可替换为实际业务坐标) fixed_node_x = [1, 2, 3] fixed_node_y = [1, 2, 3] # 创建子图布局:上方折线图,下方网络图 fig = make_subplots(rows=2, cols=1, row_heights=[0.5, 0.5], vertical_spacing=0.15) # 添加折线图:每个节点一个trace,初始仅显示第一个时间点数据 line_trace_indices = {} for idx, node in enumerate(nodes): fig.add_trace( go.Scatter( x=[times[0]], y=[activation_data[node][0]], mode='lines+markers', line=dict(color=node_colors[node]), name=f'Node {node}' ), row=1, col=1 ) line_trace_indices[node] = idx # 添加网络图:仅一个trace,固定位置,初始颜色为第一个时间点的激活值 network_trace_idx = len(nodes) fig.add_trace( go.Scatter( x=fixed_node_x, y=fixed_node_y, mode='markers', marker=dict( size=20, color=[activation_data[node][0] for node in nodes], colorscale='Viridis', showscale=False ), name='Network Nodes' ), row=2, col=1 ) # 定义滑块步骤 steps = [] for t in range(len(times)): step = dict( method="update", args=[ # 更新折线图数据和网络图颜色 { 'x': [times[:t+1] for _ in nodes] + [fixed_node_x], 'y': [activation_data[node][:t+1] for node in nodes] + [fixed_node_y], 'marker.color': [None]*len(nodes) + [[activation_data[node][t] for node in nodes]] }, # 固定坐标轴范围,避免切换时偏移 { 'xaxis.range': [times[0], times[-1]], 'xaxis2.range': [min(fixed_node_x)-0.5, max(fixed_node_x)+0.5], 'yaxis2.range': [min(fixed_node_y)-0.5, max(fixed_node_y)+0.5] } ], label=f"t = {times[t]:.1f}", ) steps.append(step) # 添加滑块控件 sliders = [dict( active=0, currentvalue={"prefix": "当前时间: "}, pad={"t": 50}, steps=steps )] # 更新整体布局 fig.update_layout( sliders=sliders, height=600, title="同步网络图与折线图(时间滑块控制)", showlegend=True ) # 强制固定网络图坐标轴范围,彻底避免位置偏移 fig.update_xaxes(row=2, col=1, range=[min(fixed_node_x)-0.5, max(fixed_node_x)+0.5]) fig.update_yaxes(row=2, col=1, range=[min(fixed_node_y)-0.5, max(fixed_node_y)+0.5]) fig.show()
内容的提问来源于stack exchange,提问作者CapsLock
相关产品推荐
相关产品推荐

