【问题标题】:Plot networkx graph with hierachy horizontally and manipulate length of arrows水平绘制具有层次结构的networkx图并操纵箭头的长度
【发布时间】:2021-03-15 08:56:28
【问题描述】:

我正在努力制作我想要的情节。我用我的模型创建了一个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()

这就是我得到的...

如果有人能指出我正确的方向,我将不胜感激。非常感谢!!!

EDIT1 感谢评论,我现在在所有正确节点之间都有箭头。事实证明,节点太大且重叠。现在看起来像这样:

如果有人知道的话,我仍然想让它水平并以某种方式缩放箭头长度......

EDIT2 我现在设法让它正常工作。我通过图形大小压缩绘图来减少箭头长度(不是理想的解决方案,但可以完成工作......) 在发现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()

这就是现在的样子:

【问题讨论】:

  • 相关? stackoverflow.com/a/29597209/2966723。您需要交换 x 和 y 坐标。我不确定 networkx 是否允许缩放边缘长度。我认为您的某些边缘似乎丢失的原因是节点绘制得太大并且重叠。
  • @Joel 您对节点大小的看法是正确的,谢谢!似乎相关,我也可以运行代码,但我不知道如何使其水平。认为一个人无法缩放箭头长度很奇怪,但是是的,我没有在上面找到任何东西......

标签: python matplotlib graph networkx graphviz


【解决方案1】:

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

如果你基本上只想旋转你的身材,你可以做的是:

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

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

【讨论】:

  • 谢谢!我终于设法使用this 完成了这项工作。有关问题的解决方案,请参阅我的原始帖子中的 EDIT2。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多