如何在Plotly桑基图中无需悬停即可显示节点与链路数值
在Plotly桑基图中直接显示节点和链路的数值
问题背景
在Plotly桑基图中,默认仅能通过悬停查看节点和链路的value值。若直接将节点标签替换为数值,会丢失节点的名称标识,因此需要实现同时显示节点名称和数值,并在链路上直接标注数值的效果。
解决方案
1. 节点显示名称+总数值
先计算每个节点的总流入/流出值,再将节点的label设置为名称\n总数值的格式,即可在节点上同时展示名称和数值。
2. 链路显示数值
Plotly原生go.Sankey不支持直接在链路上标注数值,需通过go.Scatter添加文本注释:
- 提取桑基图布局中每个节点的位置坐标
- 计算每条链路的起点(source节点)和终点(target节点)的坐标中点
- 在中点位置添加对应链路的
value文本
修改后的完整代码
import plotly.graph_objects as go import numpy as np # 原始数据 node_labels = ["A1", "A2", "B1", "B2", "C1", "C2"] link_sources = [0, 1, 0, 2, 3, 3] link_targets = [2, 3, 3, 4, 4, 5] link_values = [8, 4, 2, 8, 4, 2] # 计算每个节点的总数值(流入+流出) node_values = np.zeros(len(node_labels)) for s, t, v in zip(link_sources, link_targets, link_values): node_values[s] += v node_values[t] += v # 生成带数值的节点标签 node_labels_with_value = [f"{label}\n{int(val)}" for label, val in zip(node_labels, node_values)] # 创建桑基图 fig = go.Figure(data=[go.Sankey( node=dict( pad=15, thickness=20, line=dict(color="black", width=0.5), label=node_labels_with_value, customdata=[f"Long name {label}" for label in node_labels], hovertemplate='Node %{customdata} has total value %{value}<extra></extra>', color="blue" ), link=dict( source=link_sources, target=link_targets, value=link_values, customdata=["q","r","s","t","u","v"], hovertemplate='Link from node %{source.customdata}<br />'+ 'to node%{target.customdata}<br />has value %{value}'+ '<br />and data %{customdata}<extra></extra>', ))]) # 先渲染获取节点坐标(脚本运行时需此步骤,Notebook可直接用fig.full_figure_for_development()) fig.update_layout(title_text="Sankey Diagram with Values Displayed", font_size=10) fig.show(renderer="browser") # 提取节点坐标(实际使用时可通过fig.full_figure_for_development()['data'][0]['node']['x/y']获取) node_x = [0.0, 0.0, 0.5, 0.5, 1.0, 1.0] node_y = [0.75, 0.25, 0.8333, 0.1667, 0.6667, 0.3333] # 添加链路数值注释 for s, t, v in zip(link_sources, link_targets, link_values): mid_x = (node_x[s] + node_x[t]) / 2 mid_y = (node_y[s] + node_y[t]) / 2 fig.add_trace(go.Scatter( x=[mid_x], y=[mid_y], text=[str(v)], mode="text", textfont=dict(size=12, color="black"), showlegend=False )) fig.show()
效果对比
实际输出(默认效果):

期望输出(显示数值后):

内容的提问来源于stack exchange,提问作者MrChadMWood
相关产品推荐
相关产品推荐

