python - 水平绘制具有层次结构的 networkx 图并操纵箭头的长度

标签 python matplotlib graph networkx graphviz

我正在努力制作我想要的情节。我用我的模型创建了一个 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 函数中传递的额外参数之间存在冲突后,我设法进行了水平翻转。我用了this documentation到那里。见下面的代码:

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()

这就是现在的样子: enter image description here

最佳答案

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

如果您基本上只想旋转图形,可以执行以下操作:

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

应该取原来的 x 和 y 坐标并翻转它们(并使原来的向下方向变成新的水平向右移动)。

关于python - 水平绘制具有层次结构的 networkx 图并操纵箭头的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65124349/

相关文章:

python - 以编程方式在 Matplotlib 中的图的一侧添加间距

python - 如何用每个簇独特的颜色可视化输出簇

python - 无法通过python在phpMyAdmin中连接MySQL数据库

python - flask 形式 : how can I use multiple forms to add Parent and Child entities to DB in one commit?

python glob 为 "excluding pattern"

python - 如何在 matplotlib 绘图中正确设置 cartopy geoaxes 中的投影和变换

python - 为什么 Python 仍在垃圾收集我的 Tkinter 图像?

php - 生成随机曲线

java - 使用 GraphViz 打印树

algorithm - 最少出行次数