web-dev-qa-db-fra.com

Combiner (joindre) des graphes networkx

Disons que j'ai deux graphiques networkx, G et H:

G=nx.Graph()
fromnodes=[0,1,1,1,1,1,2]
tonodes=[1,2,3,4,5,6,7]
for x,y in Zip(fromnodes,tonodes):
    G.add_Edge(x,y)

H=nx.Graph()
fromnodes=range(2,8)
tonodes=range(8,14)
for x,y in Zip(fromnodes,tonodes):
    H.add_Edge(x,y)

Quelle est la meilleure façon de joindre les deux graphiques networkx?

Je voudrais conserver les noms de nœuds (notez les nœuds communs, 2 à 7). Lorsque j'ai utilisé nx.disjoint_union(G,H), cela ne s'est pas produit:

>>> G.nodes()
[0, 1, 2, 3, 4, 5, 6, 7]
>>> H.nodes()
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
>>> Un= nx.disjoint_union(G,H)
>>> Un.nodes()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
# 

Les étiquettes des nœuds H ont été modifiées (pas ce que je veux). Je veux joindre les graphiques aux nœuds avec le même numéro.

Remarque. Ce n'est pas un doublon de Combinez deux graphiques pondérés dans NetworkX .

21
atomh33ls

La fonction que vous recherchez est composer , qui produit un graphique avec tous les bords et tous les nœuds qui se trouvent dans les deux graphiques. Si les deux graphiques ont un nœud avec le même nom, une seule copie se retrouve dans le nouveau graphique. De même, si le même Edge existe dans les deux. Voici un exemple, y compris les attributs Edge/node:

import networkx as nx

G=nx.Graph()
G.add_node(1, weight = 2)
G.add_node(2, weight = 3)
G.add_Edge(1,2, flux = 5)
G.add_Edge(2,4)

H=nx.Graph()
H.add_node(1, weight = 4)
H.add_Edge(1,2, flux = 10)
H.add_Edge(1,3) 

F = nx.compose(G,H)
#F has all nodes & edges of both graphs, including attributes
#Where the attributes conflict, it uses the attributes of H.

G.nodes(data=True)
> NodeDataView({1: {'weight': 2}, 2: {'weight': 3}, 4: {}})
H.nodes(data=True)
> NodeDataView({1: {'weight': 4}, 2: {}, 3: {}})
F.nodes(data=True)
> NodeDataView({1: {'weight': 4}, 2: {'weight': 3}, 4: {}, 3: {}})

G.edges(data=True)
> EdgeDataView([(1, 2, {'flux': 5}), (2, 4, {})])
H.edges(data=True)
> EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {})])
F.edges(data=True)
EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {}), (2, 4, {})])

Ces attributs préservent, mais évidemment s'il y a un conflit ce n'est pas possible. Les attributs de H ont priorité.

Il existe également d'autres options pour faire différence symétrique, intersection , ...

Si vous avez plusieurs graphiques à joindre, vous pouvez utiliser compose_all , qui enveloppe simplement une boucle for autour de compose.

41
Joel

Ça l'a fait.

   U=nx.Graph()
   U.add_edges_from(G.edges()+H.edges())
   U.add_nodes_from(G.nodes()+H.nodes()) #deals with isolated nodes

ou, en préservant les attributs Edge:

   U.add_edges_from(G.edges(data=True)+H.edges(data=True))

et, pour conserver également les attributs du nœud:

   U.add_nodes_from(G.nodes(data=True)+H.nodes(data=True))
9
atomh33ls