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

使用Python和Graphviz绘制家谱图时实现配偶同层级显示的问题

使用Python和Graphviz绘制家谱图时实现配偶同层级显示的问题

我完全懂你的困扰——想用Graphviz画出家谱图,却没法让配偶们处在同一层级,试了rank="same"也没起效对吧?其实问题出在Graphviz的布局逻辑上:默认会根据节点间的连接关系自动分配层级,而你的原始代码里配偶是作为当前节点的后续节点添加的,自然就跑到下一层去了。咱们调整下代码逻辑,用**子图(subgraph)**来强制配偶组同层级,就能解决这个问题。

关键修改思路

  • 用子图分组配偶:创建一个rank="same"的子图,把当前人物和他的所有配偶都放进这个子图里,强制他们处于同一层级。
  • 避免重复节点:添加一个集合跟踪已创建的节点,防止同一个人物被多次添加(比如Eddy既是Alice的配偶,又是Dave等孩子的父亲,容易重复创建)。
  • 理顺连接关系:配偶之间用虚线连接,亲子关系从父母(包括所有配偶)分别连到孩子,确保层级传递正确。

修改后的完整代码

from graphviz import Digraph

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        self.partners = []
        self.children = []

# Example family tree
alice = Person("Alice", "Female")
eddy = Person("Eddy", "Male")
bob = Person("Bob", "Male")
charlie = Person("Charlie", "Male")
dave = Person("Dave", "Male")
eve = Person("Eve", "Female")
frank = Person("Frank", "Male")
fp = Person("fictional Partner", "Female")
fjr = Person("fjr", "Female")
fjr2 = Person("fjr2", "Male")

alice.partners.append(eddy)
alice.children.append(bob)
alice.children.append(charlie)
eddy.children.append(dave)
eddy.children.append(eve)
eddy.children.append(frank)
alice.partners.append(fp)
frank.children.append(fjr)
frank.children.append(fjr2)

def build_family_tree(person, graph, added_nodes=None):
    # 初始化已添加节点集合,避免重复创建节点
    if added_nodes is None:
        added_nodes = set()
    
    # 如果当前人物已在图中,直接返回
    if person.name in added_nodes:
        return
    
    # 创建子图,强制当前人物和配偶同层级
    with graph.subgraph() as spouse_subgraph:
        spouse_subgraph.attr(rank="same")
        # 添加当前人物节点
        spouse_subgraph.node(person.name, shape="none", label=person.name)
        added_nodes.add(person.name)
        # 处理所有配偶:添加节点+虚线连接
        for partner in person.partners:
            if partner.name not in added_nodes:
                spouse_subgraph.node(partner.name, shape="none", label=partner.name)
                added_nodes.add(partner.name)
            # 配偶间用虚线连接
            graph.edge(person.name, partner.name, style="dashed")
    
    # 处理当前人物的孩子:连接+递归
    for child in person.children:
        graph.edge(person.name, child.name, arrowhead="none")
        build_family_tree(child, graph, added_nodes)
    
    # 处理配偶的孩子:确保孩子和配偶的连接
    for partner in person.partners:
        for child in partner.children:
            if child.name not in added_nodes:
                graph.edge(partner.name, child.name, arrowhead="none")
                build_family_tree(child, graph, added_nodes)

# 创建图谱并生成
family_tree_graph = Digraph()
build_family_tree(alice, family_tree_graph)
family_tree_graph.render('family_tree', format='png', view=True)

效果说明

修改后,Alice、Eddy和fictional Partner会被强制放在同一层级,他们的孩子(Bob、Charlie、Dave等)自动排列在下一层,Frank的孩子fjr和fjr2则在更下一层,完美符合家谱的层级逻辑。

备注:内容来源于stack exchange,提问作者Jahlove

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 10:28:11