如何在Plotly的go.Sankey中抑制循环显示?
Plotly桑基图抑制循环连接的解决方法
Plotly的Sankey组件没有内置参数直接隐藏循环连接,但可以通过预处理链接数据来实现需求。
核心思路
手动过滤掉构成循环的链接条目,可针对不同循环场景处理:
- 自循环(节点指向自身):直接跳过
source与target相同的链接 - 双向循环(A→B且B→A):选择保留其中一条链接,或完全移除两条链接
- 多节点闭环(如A→B→C→A):通过图遍历算法识别闭环路径后移除对应链接
示例代码(以双向循环处理为例)
import plotly.graph_objects as go # 原始链接数据 raw_links = [ {"source": 0, "target": 5, "value": 1}, {"source": 0, "target": 3, "value": 2}, {"source": 1, "target": 4, "value": 1}, {"source": 2, "target": 3, "value": 1}, {"source": 5, "target": 0, "value": 1}, {"source": 4, "target": 2, "value": 1}, {"source": 3, "target": 2, "value": 1}, {"source": 5, "target": 3, "value": 2} ] # 方案1:保留双向循环中的一条链接 filtered_links = [] seen_pairs = set() for link in raw_links: s, t = link["source"], link["target"] # 跳过自循环 if s == t: continue # 用排序后的有序对标记已处理的双向关系,避免重复 pair = tuple(sorted((s, t))) if pair not in seen_pairs: seen_pairs.add(pair) filtered_links.append(link) # 方案2:完全移除所有双向循环的链接 # bidirectional_pairs = set() # temp_pairs = set() # for link in raw_links: # s, t = link["source"], link["target"] # if s != t: # pair = tuple(sorted((s, t))) # if pair in temp_pairs: # bidirectional_pairs.add(pair) # else: # temp_pairs.add(pair) # filtered_links = [link for link in raw_links if tuple(sorted((link["source"], link["target"]))) not in bidirectional_pairs] # 提取过滤后的链接数据 source = [item["source"] for item in filtered_links] target = [item["target"] for item in filtered_links] value = [item["value"] for item in filtered_links] fig = go.Figure(go.Sankey( arrangement = "snap", node = { "label": ["A", "B", "C", "D", "E", "F"], "x": [0.2, 0.1, 0.5, 0.7, 0.3, 0.5], "y": [0.7, 0.5, 0.2, 0.4, 0.2, 0.3], 'pad':10}, link = {"source": source, "target": target, "value": value} )) fig.show()
说明
- 方案1适合需要保留单向流量展示的场景,避免重复绘制双向连接
- 方案2适合彻底消除循环显示的需求
- 若需处理多节点闭环,可引入DFS等图遍历算法识别闭环路径后过滤对应链接
内容的提问来源于stack exchange,提问作者Jimmy Zhao
相关产品推荐
相关产品推荐

