用层次结构水平绘制networkx图,并操纵箭头的长度

3

我正在努力制作我想要的图表。我使用我的模型创建了一个networkx图形,并使用graphviz_layout获取节点的分层显示。我成功地按照自己的意愿对节点进行了彩色编码,但有几件事情我无法实现:

  • 我希望图是水平的,使得节点0在左边作为起点。
  • 我想要修改箭头的长度(将其缩小)。
  • 我想要在所有具有相互连接边的节点之间添加箭头,例如节点3和5、5和7、7和8等。(我检查过G.edges(),它们存在,但不会显示)

这是我的代码...

from networkx.drawing.nx_agraph import write_dot, graphviz_layout

G = model.block_tree.tree
write_dot(G,'test.dot')
pos = graphviz_layout(G, prog='dot', root=0)
plt.title("Some title")
nx.draw_networkx_nodes(G, pos, node_color=color_vector, node_shape='s', node_size=500)
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos, font_size=10, font_color="white")
plt.show()

这就是我得到的内容... enter image description here 如果有人能指引我正确的方向,我将不胜感激。非常感谢!!!
编辑1: 感谢评论,现在我所有正确节点之间都有箭头了。原来节点太大并且重叠了。现在它看起来像这样: enter image description here
如果有人知道如何使它变为水平,并以某种方式调整箭头长度,我仍然希望得到帮助...
编辑2: 我现在已经成功地让它正常工作了。我通过调整图形大小来缩小箭头长度(不是理想的解决方案,但完成了工作...)。我设法让水平翻转正常工作,发现root与传递给graphviz_lazout函数的额外参数之间存在冲突。我使用了这份文档来进行操作。请参见下面的代码:
def blocktree_plot(model):
    honest_blocks = []
    selfish_blocks = []
    
    for block in model.block_tree.tree.nodes():
        if model.block_tree[block]["miner_is_selfish"] == True:
            selfish_blocks.append(model.block_tree[block]["id"])
        else:
            honest_blocks.append(model.block_tree[block]["id"])

    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(6, 2), sharex=True, sharey=True)
    G = model.block_tree.tree
    H = G.reverse(copy=True)
    pos = graphviz_layout(H, prog='dot', args='-Grankdir="RL"')

    plt.title(r"Blockchain with Selfish Mining ($\alpha$ = {})".format(alpha))

    nx.draw_networkx_nodes(H,pos=pos, nodelist=honest_blocks, node_color='green', label="Honest miner", node_shape='s', node_size=200)
    nx.draw_networkx_nodes(H,pos=pos, nodelist=selfish_blocks, node_color='red', label="Selfish miner", node_shape='s', node_size=200)
    nx.draw_networkx_nodes(H,pos=pos, nodelist=[0], node_color='blue', label="Genesis block", node_shape='s', node_size=200)    

    nx.draw_networkx_edges(H, pos, arrows=True)
    nx.draw_networkx_labels(H, pos, font_size=10, font_color="white")
    # plt.legend(labelspacing=0.8, fontsize=9, frameon=False, borderpad=0.1)
    plt.show()

现在的样子如下所示: 这里输入图片描述


1
有关编程的内容翻译成中文。仅返回翻译后的文本:https://dev59.com/ul0b5IYBdhLWcg3wIOB9#29597209. 您需要交换x和y坐标。我不确定networkx是否允许缩放边缘长度。我认为一些边缘似乎丢失的原因是节点绘制得太大并重叠了。 - Joel
@Joel,你关于节点大小的建议是正确的,谢谢! 这似乎与此有关,我也可以运行代码,但我不知道如何使它水平。而且很奇怪,想到不能缩放箭头长度,但是我没有找到任何相关资料... - casparschwa
1个回答

2

我不确定是否可以轻松缩放边长,所以这部分我没有回答,希望其他人有建议。

如果你只是想旋转你的图形,你可以按照以下步骤操作:

tmppos = graphviz_layout(G, prog='dot', root=0)
pos = {node: (-y, x) for node, x,y in tmppos.items()}

该操作应该将原始的x和y坐标进行翻转(并使原始的向下方向转换为新坐标系中的水平向右移动)。


谢谢!我终于使用这个完成了工作。请参见我的原始帖子中的EDIT2,以获取解决问题的方法。 - casparschwa

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