首页 > 解决方案 > 将 Matplotlib 和 Networkx/Pygraphviz 单位转换为通用单位

问题描述

我正在尝试根据节点数以及是否有节点在水平方向或垂直方向上重叠(即,如果所有节点都在同一条线上,它们会相交)来自动缩放 networkx 图。为此,我查看每个节点的位置并检查位置加上节点大小是否在任何其他节点坐标加上节点大小之间。为了获得节点位置,我使用networkx.nx_agraph.graphviz_layout. 问题是位置和节点大小不是同一个单位。

Networkx 在底层调用pyplot.scatter(来源:) https://networkx.github.io/documentation/networkx-1.10/_modules/networkx/drawing/nx_pylab.html#draw_networkx_nodes,它将节点大小作为像素区域(来源:) https://stackoverflow.com/questions/14827650/pyplot-scatter-plot-marker-size

Networkx 使用圆形节点绘制图形,因此基于此将节点大小转换为英寸是有意义的,我会在node_size * 4 / (math.pi * DPI)哪里做DPIMatplotlib 使用的 DPI。在我的代码中,这似乎不起作用。我也尝试过取节点大小的平方根并将其除以 DPI,但这似乎也不起作用。

目前的问题是我无法检测到哪些节点重叠。

总之:如果我正在绘制一个带有圆形节点的 networkx 图,如何将节点大小和/或 Pygraphviz 位置转换为一个通用单位?

也可能是我的代码错误,所以这里有一个简短的可重现示例:

NODE_SIZE = 300
DPI = 100
mpl.rcParams['figure.dpi'] = DPI

G = nx.gnp_random_graph(50, 0)
pos = nx.nx_agraph.graphviz_layout(G)
tmp_pos = sorted(pos.items(), key=lambda x: x[1][0]) # Sort it by x value so you only have to check to the right of the node in the list of positions
node_size_inches = NODE_SIZE * 4 / (math.pi * DPI) # This is my attempt at getting the height/width of the nodes

i = 0
for key, xy in tmp_pos:
    x = xy[0]
    overlapping = []

    # Since list is sorted by x, you only need to check nodes to the right
    for k, xyt in tmp_pos[i+1:]:

        xt = xyt[0]

        # Check for overlapping nodes to the right
        if x <= xt <= x + node_size_inches:
            overlapping.append(k)

        # Since list is sorted by x, if the previous condition fails, nothing after can be applicable
        else:
            break

    if overlapping: print("{}:{}".format(key, overlapping))

    i += 1

nx.draw(G, pos=pos, with_labels=True)

标签: python-3.xmatplotlibnetworkxpygraphviz

解决方案


推荐阅读