问题
I have a dataset that represents a kind of genealogy tree. Each node has 2 parents (except first generation, they have no parents). For a given node, its parents can be from any previous generation. For example a node in generation n, can have a parent in n-1, and another parent in n-5. A node can be parent of several other nodes.
So basically, for every node I know its generation and its parents.
I am trying to represent this graph keeping the nodes from the same generation in the same line. Each generation has 10 nodes, except the first one.
So far I am trying the "dot" layout. When I only input two generations it does a good job, but when I input 3 generations, it is "too smart", and rearranges the nodes in some way.
For example, the following data, which represents 3 generations:
[(ObjectId('530b2ad783a1a15e695c9711'), ObjectId('530b804883a1a15e695c972b')), (ObjectId('530b2ad783a1a15e695c971c'), ObjectId('530b804883a1a15e695c972b')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530b804883a1a15e695c9727')), (ObjectId('530b2ad783a1a15e695c970a'), ObjectId('530b804883a1a15e695c9727')), (ObjectId('530b2ad783a1a15e695c970b'), ObjectId('530b804883a1a15e695c9724')), (ObjectId('530b2ad783a1a15e695c970f'), ObjectId('530b804883a1a15e695c9724')), (ObjectId('530b2ad783a1a15e695c9714'), ObjectId('530b804883a1a15e695c9729')), (ObjectId('530b2ad783a1a15e695c970e'), ObjectId('530b804883a1a15e695c9729')), (ObjectId('530b2ad783a1a15e695c9711'), ObjectId('530b804883a1a15e695c9723')), (ObjectId('530b2ad783a1a15e695c970e'), ObjectId('530b804883a1a15e695c9723')), (ObjectId('530b2ad783a1a15e695c971c'), ObjectId('530b804883a1a15e695c9728')), (ObjectId('530b2ad783a1a15e695c9719'), ObjectId('530b804883a1a15e695c9728')), (ObjectId('530b2ad783a1a15e695c9714'), ObjectId('530b804883a1a15e695c9726')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530b804883a1a15e695c9726')), (ObjectId('530b2ad783a1a15e695c9716'), ObjectId('530b804883a1a15e695c9722')), (ObjectId('530b2ad783a1a15e695c9719'), ObjectId('530b804883a1a15e695c9722')), (ObjectId('530b2ad783a1a15e695c970d'), ObjectId('530b804883a1a15e695c9725')), (ObjectId('530b2ad783a1a15e695c9715'), ObjectId('530b804883a1a15e695c9725')), (ObjectId('530b804883a1a15e695c9724'), ObjectId('530ba27c83a1a15e695c972d')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530ba27c83a1a15e695c972d')), (ObjectId('530b804883a1a15e695c9724'), ObjectId('530ba27c83a1a15e695c972e')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530ba27c83a1a15e695c972e')), (ObjectId('530b804883a1a15e695c9727'), ObjectId('530ba27c83a1a15e695c972f')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530ba27c83a1a15e695c972f')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530ba27c83a1a15e695c9730')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530ba27c83a1a15e695c9730')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530ba27c83a1a15e695c9731')), (ObjectId('530b804883a1a15e695c9725'), ObjectId('530ba27c83a1a15e695c9731')), (ObjectId('530b804883a1a15e695c9722'), ObjectId('530ba27c83a1a15e695c9732')), (ObjectId('530b2ad783a1a15e695c970b'), ObjectId('530ba27c83a1a15e695c9732')), (ObjectId('530b2ad783a1a15e695c9711'), ObjectId('530ba27c83a1a15e695c9733')), (ObjectId('530b2ad783a1a15e695c971f'), ObjectId('530ba27c83a1a15e695c9733')), (ObjectId('530b804883a1a15e695c972b'), ObjectId('530ba27c83a1a15e695c9734')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530ba27c83a1a15e695c9734')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530ba27c83a1a15e695c9735')), (ObjectId('530b804883a1a15e695c9724'), ObjectId('530ba27c83a1a15e695c9735')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530ba27c83a1a15e695c9736')), (ObjectId('530b804883a1a15e695c9723'), ObjectId('530ba27c83a1a15e695c9736')), (ObjectId('530b2ad783a1a15e695c9716'), ObjectId('530b804883a1a15e695c9722')), (ObjectId('530b2ad783a1a15e695c9719'), ObjectId('530b804883a1a15e695c9722')), (ObjectId('530b2ad783a1a15e695c9711'), ObjectId('530b804883a1a15e695c9723')), (ObjectId('530b2ad783a1a15e695c970e'), ObjectId('530b804883a1a15e695c9723')), (ObjectId('530b2ad783a1a15e695c970b'), ObjectId('530b804883a1a15e695c9724')), (ObjectId('530b2ad783a1a15e695c970f'), ObjectId('530b804883a1a15e695c9724')), (ObjectId('530b2ad783a1a15e695c970d'), ObjectId('530b804883a1a15e695c9725')), (ObjectId('530b2ad783a1a15e695c9715'), ObjectId('530b804883a1a15e695c9725')), (ObjectId('530b2ad783a1a15e695c9714'), ObjectId('530b804883a1a15e695c9726')), (ObjectId('530b2ad783a1a15e695c9713'), ObjectId('530b804883a1a15e695c9726')), (ObjectId('530b2ad783a1a15e695c9709'), ObjectId('530b804883a1a15e695c9727')), (ObjectId('530b2ad783a1a15e695c970a'), ObjectId('530b804883a1a15e695c9727')), (ObjectId('530b2ad783a1a15e695c971c'), ObjectId('530b804883a1a15e695c9728')), (ObjectId('530b2ad783a1a15e695c9719'), ObjectId('530b804883a1a15e695c9728')), (ObjectId('530b2ad783a1a15e695c9714'), ObjectId('530b804883a1a15e695c9729')), (ObjectId('530b2ad783a1a15e695c970e'), ObjectId('530b804883a1a15e695c9729')), (ObjectId('530b2ad783a1a15e695c9715'), ObjectId('530b804883a1a15e695c972a')), (ObjectId('530b2ad783a1a15e695c970b'), ObjectId('530b804883a1a15e695c972a')), (ObjectId('530b2ad783a1a15e695c9711'), ObjectId('530b804883a1a15e695c972b')), (ObjectId('530b2ad783a1a15e695c971c'), ObjectId('530b804883a1a15e695c972b'))]
produces:
All the nodes that are "root" and therefore don't receive an edge should be placed on the first line, for example, but it is placing some of them on the second level.
Once I try to make bigger graphs, with 10 generations, all the hierarchy makes no sense at all.
is there any parameter or way to specify the level or layer of a node? In the data I provided that info is not there, but I can easily produce it, the problem is that I don't know how to send that info to pygraphviz or networkx.
I also want to use this data to produce graphs with twopi like this one http://networkx.github.io/documentation/latest/examples/drawing/lanl_routes.html
where the layers are represented on a circular way.
回答1:
Use a Graphviz subgraph with attribute rank=same. e.g.
import networkx as nx
import pygraphviz as pgv # pygraphviz should be available
G = nx.DiGraph()
G.add_edge('a','aa')
G.add_edge('a','ab')
G.add_edge('a','bbc')
G.add_edge('b','ab')
G.add_edge('b','bb')
G.add_edge('c','bbc')
G.add_edge('bb','bba')
G.add_edge('bb','bbc')
A = nx.to_agraph(G)
one = A.add_subgraph(['a','b','c'],rank='same')
two = A.add_subgraph(['aa','ab','bb'],rank='same')
three = A.add_subgraph(['bba','bbc'],rank='same')
A.draw('example.png', prog='dot')
回答2:
As of 2017, the function to_agraph
is no longer exposed at the nx.level
.
Now you must call nx.nx_agraph.to_agraph()
来源:https://stackoverflow.com/questions/22207802/pygraphviz-networkx-set-node-level-or-layer