[Python] Python plot of connected graph with control over one coordinate of node position, but...

Discussão em 'Python' iniciado por Stack, Junho 11, 2025.

  1. Stack

    Stack Membro Participativo

    I have a situation in which I want to generate a graph such as the following sketch I have a set of discrete items A -- J, each of which has a univariate measurement (say the quality measurement of item i). There is a known connectivity graph of edges for these items (corresponding to the nodes), some of which may not be connected to any others. Thus there may be some grouping of the items which is independent of the measurement value. What I would like is to have the items arranged with the edges but so that the vertical coordinate of the node placement corresponds to the measurement value. Thus, A, B and E have similar measurement and are connected. The horizontal coordinate of the node placement is unimportant and would be optimized by a plotting utility which ideally minimizes the length of the edges and reduces line crossing. For instance, I and J are plotted to the side of G-H and don't cross the line. Does this type of plot have a name? I'd like to have as much of this under the optimization control without having to code it myself.

    I've seen in Python's networkx module that you can specify the coordinates of the nodes, but I only want to specify one of the coordinates and let the other be optimized according to the connectivity/other node placements in some way. [​IMG] EDIT: Here is what I've tried with networkx. To be honest the results are okay.

    import networkx as nx
    from collections import defaultdict
    import numpy as np
    from itertools import combinations

    nnodes = 10
    # this should determine the heights
    node_measurements = np.random.normal(size=nnodes)
    nc = 0.2

    edges = defaultdict(list)
    for pair in combinations(range(nnodes), r=2):
    if np.random.binomial(n=1, p=nc):
    edges[pair[0]].append(pair[1])


    G = nx.DiGraph()
    for node, others in edges.items():
    if len(others):
    for jj in others:
    # edge between nodes
    G.add_edge(node, jj)
    else:
    # node with no connetions
    G.add_node(node)

    for node in range(nnodes):
    if node not in G.nodes:
    G.add_node(node)

    sd = 5
    # get the optimal positions according to spring layout (saw using k can improve)
    pos = nx.spring_layout(G, seed=sd, k=10/np.sqrt(G.order()))
    nx.draw_networkx(G, with_labels=True, pos=pos, node_color="lightblue")
    plt.title('Default positions')
    plt.show()

    # now we want the vertical positions to be according to node_measurements
    pos = {ii: np.array([pos[ii][0], meas]) for ii, meas in enumerate(node_measurements)}
    nx.draw_networkx(G, with_labels=True, pos=pos, node_color="lightblue")
    plt.title('Adjusted positions')
    plt.show()


    [​IMG] [​IMG]

    The second image shows the nodes placed according to the desired y-axis height but with the x-axis coordinate being the default (without knowing the height). Obviously in some cases if the height was known it would look nicer. For instance 8->9 can be placed where it doesn't cross other lines, and 5->7 could be placed so it goes to the left rather than right. It seems that the results really depend on the situation and in many cases you end up with oblong graphs that take a sharp diagonal form where they could have been more regular and even if the x-coordinates could have been shifted. But my point is that the optimization done in the default coordinates could look different if the desired y-coordinate constraint were known.

    Continue reading...

Compartilhe esta Página