使用anytree和graphviz在Python中呈现树形结构,但不合并相同节点

7

我正在使用Python3的anytree包从列表["abc", "abd", "aec", "add", "adcf"]中创建一棵树。在这个树中,每个列表元素的第一个字符 - a 是根节点,随后其他字符作为它们的子节点添加。当我渲染这棵树时,它看起来像:

a
├── b
│   ├── c
│   └── d
├── e
│   └── c
└── d
    ├── d
    └── c
        └── f

但是当我使用to_picture方法将树渲染成图片时,图片是这样的 -

enter image description here

我不希望普通节点被合并,因为它会给我的树添加不需要的路径。

你能分享一下你的代码吗? - Rojan
你想要类似这样的东西吗?https://i.stack.imgur.com/uRwYG.png - Tarun Lalwani
@Rojan.. 感谢关心。您可以参考Tarun Lalwani的答案获取代码。 - Himadri
3个回答

11

使用它们的id,在graphviz中排列节点。在您的情况下,图是仅使用节点名称生成的,然后graphviz创建了循环边,就像您得到的那样。

您真正想要的是每个节点都有不同的id和与之关联的labelDotExporter类有一个名为nodeattrfunc的属性,我们可以向其传递函数或lambda并为节点生成属性。

以下是基于您的数组的操作方式:

import anytree
from anytree import Node, RenderTree

data = ["abc", "abd", "aec", "add", "adcf"]
from anytree.exporter import DotExporter

nodes = {}
first_node = None

for elem in data:
    parent_node = None
    parent_node_name = ""
    for i, val in enumerate(elem):
        if i not in nodes:
            nodes[i] = {}
        key = parent_node_name + val
        if key not in nodes[i]:
            print("Creating new node for ", key)
            nodes[i][key] = Node(key, parent=parent_node, display_name=val)

        if first_node is None:
            first_node = nodes[i][key]
        parent_node = nodes[i][key]
        parent_node_name = val

print(nodes)
DotExporter(nodes[0]["a"],
            nodeattrfunc=lambda node: 'label="{}"'.format(node.display_name)).to_dotfile("graph.txt")
DotExporter(nodes[0]["a"],
            nodeattrfunc=lambda node: 'label="{}"'.format(node.display_name)).to_picture("graph.png")

这将生成下面的dot文件

digraph tree {
    "a" [label="a"];
    "ab" [label="b"];
    "bc" [label="c"];
    "bd" [label="d"];
    "ae" [label="e"];
    "ec" [label="c"];
    "ad" [label="d"];
    "dd" [label="d"];
    "dc" [label="c"];
    "cf" [label="f"];
    "a" -> "ab";
    "a" -> "ae";
    "a" -> "ad";
    "ab" -> "bc";
    "ab" -> "bd";
    "ae" -> "ec";
    "ad" -> "dd";
    "ad" -> "dc";
    "dc" -> "cf";
}

以下是下面的图表

最终图表


嗨Tarun,你的回答很棒。我在生成图片方面遇到了一些问题,你能看一下这个链接吗:https://stackoverflow.com/questions/52493775/rendering-a-tree-in-python-with-anytree-and-graphviz-cant-open-file。 提前感谢。 - luQ

1
任何树形结构都可以使用anytree库中的to_picture()函数生成文件,该函数使用graphviz进行操作。
这里 = 相似问题可以了解到:

graphviz使用节点id作为标签。如果不同的节点需要具有相同的标签,则必须显式定义标签。


1

我正打算实施推荐的修复方案,但发现使用UniqueDotExporter可以完美地解决重复的id问题!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接