2015-09-18 17 views
12

Dire che ho due grafici NetworkX, G e H:Combine (join) Grafici NetworkX

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) 

Qual è il modo migliore per unire le due grafici NetworkX?

Vorrei conservare i nomi dei nodi (notare i nodi comuni, da 2 a 7). Quando ho usato nx.disjoint_union(G,H), questo non è accaduto:

>>> 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] 
# 

I H etichette dei nodi sono stati cambiati (non quello che voglio). Voglio unire i grafici ai nodi con lo stesso numero.

Nota. Questo non è un duplicato di Combine two weighted graphs in NetworkX.

+1

Cosa si vuole fare se esiste un bordo in entrambi? Dovrebbe diventare un doppio vantaggio? o solo un singolo bordo? – Joel

+0

@Joel hmm Sono interessato a entrambi i casi. Diciamo il single edge però. – atomh33ls

+1

Il caso single edge è gestito correttamente dal codice che hai scritto. Il caso multiedge ti basta fare 'U = nx.MultiGraph()' – Joel

risposta

23

La funzione che stai cercando è compose.

import networkx as nx 
G=nx.Graph() 
G.add_edge(1,2) 
H=nx.Graph() 
H.add_edge(1,3) 
F = nx.compose(G,H) 
F.edges() 
> [(1, 2), (1, 3)] 

ci sono anche altre opzioni per fare il symmetric difference, intersection, ...

Se si dispone di più grafici ad unirsi insieme, è possibile utilizzare compose_all, che avvolge solo un ciclo for intorno compose.

+0

Come forzare tutti i grafici condividono la stessa posizione per i nodi con la stessa etichetta quando disegnamo tutti con' nx.draw_networkx (G) nx.draw_networkx (H) nx.draw_networkx (F) plt.show() '? Voglio dire, le coordinate del nodo '1' dovrebbero essere le stesse per tutti e 3 i grafici. – Sigur

+0

@Sigur I comandi di stampa prendono un (facoltativo) input 'pos' come' nx.draw_networkx (G, pos = pos) '. 'pos' è un dizionario le cui chiavi sono i nodi e i cui valori sono le loro coordinate (x, y). Puoi definirlo tu stesso, o attraverso alcuni dei comandi 'layout'. ad es., pos = nx.spring_layout (F) '. – Joel

+0

Mi piacerebbe usare prima il layout per ottenere una buona visualizzazione e quindi usare le stesse coordinate quando aggiungo nuovi bordi e tracciamo nuovamente in un'altra finestra. Più o meno mi piacerebbe produrre una sequenza di figure per mostrare una sorta di linea del tempo per il grafico. – Sigur

4

Questo ha funzionato.

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

o, preservando il bordo attributi:

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

e, per preservare anche gli attributi del nodo:

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