You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用NetworkX和Pyvis实现有向图双向边的单箭头可视化

解决Pyvis绘制双向关系单条双向箭头的问题

要实现单向关系显示单箭头、双向关系显示单条双向箭头的效果,不需要用NetworkX的DiGraph添加两条边,而是可以通过无向图存储关系类型+Pyvis手动控制边箭头的方式实现,具体步骤如下:

核心思路

用NetworkX的无向图(Graph)存储所有角色关系,给每条边添加relation_type(区分单向/双向)和label(关系描述)属性,然后在Pyvis中遍历边,根据关系类型设置箭头样式:

  • 单向关系:设置arrows="to"(仅目标节点显示箭头)
  • 双向关系:设置arrows="to,from"(两端都显示箭头)

代码实现

1. 准备关系数据CSV

假设你的CSV文件(love_actually_relations.csv)结构如下:

source,target,relation_type,label
Mark,Juliet,one_way,爱慕
Mark,Peter,two_way,挚友
Peter,Juliet,two_way,已婚

2. 完整代码

import networkx as nx
from pyvis.network import Network
import pandas as pd

# 加载关系数据
df = pd.read_csv("love_actually_relations.csv")

# 构建NetworkX无向图,存储边的关系属性
G = nx.Graph()
for _, row in df.iterrows():
    G.add_edge(
        row["source"],
        row["target"],
        relation_type=row["relation_type"],
        label=row["label"]
    )

# 初始化Pyvis有向网络图
net = Network(directed=True, height="800px", width="100%")

# 添加所有节点
net.add_nodes(G.nodes())

# 遍历边,设置箭头样式和关系标签
for u, v, attrs in G.edges(data=True):
    rel_type = attrs["relation_type"]
    rel_label = attrs["label"]
    
    if rel_type == "two_way":
        # 双向关系:添加带双向箭头的边
        net.add_edge(u, v, label=rel_label, arrows="to,from")
    else:
        # 单向关系:添加带单向箭头的边
        net.add_edge(u, v, label=rel_label, arrows="to")

# 启用物理布局优化节点位置
net.barnes_hut()

# 保存为可交互的HTML文件
net.write_html("love_actually_relations.html")

关键细节说明

  • Pyvis的arrows参数支持多种配置:"to"(目标箭头)、"from"(源箭头)、"to,from"(双向箭头)
  • 用无向图存储关系可以避免重复添加双向边,同时通过属性保留关系类型信息
  • 启用barnes_hut布局可以让节点分布更合理,避免重叠

备选方案(基于已有的DiGraph)

如果已经用DiGraph构建了包含双向边的图,可以先去重反向边,再修改箭头样式:

import networkx as nx
from pyvis.network import Network

# 假设已有的DiGraph G
G = nx.DiGraph()
# 示例添加边
G.add_edge("Mark", "Juliet", label="爱慕")
G.add_edge("Mark", "Peter", label="挚友")
G.add_edge("Peter", "Mark", label="挚友")
G.add_edge("Peter", "Juliet", label="已婚")
G.add_edge("Juliet", "Peter", label="已婚")

# 找出并删除重复的双向边
processed = set()
bidirectional_pairs = []
for u, v in G.edges():
    if (v, u) in G.edges() and (u, v) not in processed and (v, u) not in processed:
        bidirectional_pairs.append((u, v))
        G.remove_edge(v, u)
        processed.add((u, v))

# 转换为Pyvis网络并设置箭头
net = Network(directed=True)
net.from_nx(G)

# 给双向边设置双向箭头
for edge in net.edges:
    u, v = edge["from"], edge["to"]
    if (u, v) in bidirectional_pairs:
        edge["arrows"] = "to,from"

net.write_html("love_actually_relations.html")

内容的提问来源于stack exchange,提问作者Lou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:10:38