Ce guide vous apprendra à utiliser NetworkX, une bibliothèque Python puissante pour l'analyse et la visualisation de graphes. Nous allons également explorer BiGraphMulti, une structure de graphe biparti et multi-arêtes.
NetworkX permet de créer différents types de graphes, comme les graphes non orientés, orientés, pondérés, etc. Voici un exemple simple :
import networkx as nx
import matplotlib.pyplot as plt
# Création d'un graphe
G = nx.Graph()
# Ajout de nœuds (un ou plusieurs)
G.add_node(1)
G.add_nodes_from([2, 3, 4])
# Ajout d'arêtes (un ou plusieurs)
G.add_edge(1, 2)
G.add_edges_from([(2, 3), (3, 4), (4, 1)])
# Visualisation du graphe
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_size=10)
plt.title("Graphe Simple")
plt.show()
NetworkX offre des outils pour accéder aux propriétés du graphe :
# Liste des nœuds et arêtes
print("Nœuds :", G.nodes())
print("Arêtes :", G.edges())
# Nombre de nœuds et arêtes
print("Nœuds :", len(G.nodes()))
print("Arêtes :", len(G.edges()))
# Degré d'un nœud
print("Degré du nœud 1 :", G.degree[1])
# Degré de tout les nœud
degree = list(dict(G.degree()).values())
# Degré de tout les nœud (entrant et sortant) (si graph directionnel !)
out_degree = list(dict(G.out_degree()).values())
in_degree = list(dict(G.in_degree()).values())
G = nx.from_pandas_edgelist(edge_df, source='node1', target='node2', edge_attr='attr', create_using=nx.DiGraph())
G = nx.DiGraph()
for _, row in node_df.iterrows():
G.add_node(row['node1'], score=row['attr1'], name=row['attr2'])
for _, row in edge_df.iterrows():
G.add_edge(row['node1'], row['node2'], gender=row['attr'])
for node in G.nodes:
continue
Un graphe orienté a des arêtes directionnelles :
# Création d'un graphe orienté
DG = nx.DiGraph()
DG.add_edges_from([(1, 2), (2, 3), (3, 1)])
# Visualisation
nx.draw(DG, with_labels=True, node_color='lightgreen', node_size=500, font_size=10, arrowsize=20)
plt.title("Graphe Orienté")
plt.show()
Un graphe pondéré associe des poids aux arêtes :
# Création d'un graphe pondéré
WG = nx.Graph()
WG.add_edge(1, 2, weight=4)
WG.add_edge(2, 3, weight=7)
# Visualisation avec poids
pos = nx.spring_layout(WG)
nx.draw(WG, pos, with_labels=True, node_color='lightcoral', node_size=500, font_size=10)
labels = nx.get_edge_attributes(WG, 'weight')
nx.draw_networkx_edge_labels(WG, pos, edge_labels=labels)
plt.title("Graphe Pondéré")
plt.show()
Un graphe biparti est un graphe dont les nœuds peuvent être divisés en deux ensembles distincts, tels qu'aucune arête ne relie deux nœuds du même ensemble. Voici un exemple :
from networkx.algorithms import bipartite
# Création d'un graphe biparti
B = nx.Graph()
# Ajout des nœuds des deux ensembles
B.add_nodes_from([1, 2, 3], bipartite=0) # Ensemble 1
B.add_nodes_from(['A', 'B'], bipartite=1) # Ensemble 2
# Ajout des arêtes
B.add_edges_from([(1, 'A'), (2, 'A'), (3, 'B')])
# Visualisation
pos = nx.bipartite_layout(B, nodes=[1, 2, 3])
nx.draw(B, pos, with_labels=True, node_color=['lightblue', 'lightgreen'], node_size=500, font_size=10)
plt.title("Graphe Biparti")
plt.show()
Vous pouvez vérifier si un graphe est biparti :
is_bipartite = bipartite.is_bipartite(B)
print("Le graphe est biparti :", is_bipartite)
Un MultiGraph permet d'avoir plusieurs arêtes entre deux nœuds :
# Création d'un MultiGraph
MG = nx.MultiGraph()
MG.add_edge(1, 2)
MG.add_edge(1, 2, weight=3)
MG.add_edge(2, 3)
# Visualisation
pos = nx.spring_layout(MG)
nx.draw(MG, pos, with_labels=True, node_color='orange', node_size=500, font_size=10)
plt.title("MultiGraph")
plt.show()
Vous pouvez accéder aux arêtes multiples et leurs attributs :
# Accéder aux arêtes multiples entre deux nœuds
edges = MG[1][2]
print("Arêtes entre 1 et 2 :", edges)
Un MultiDiGraph est un MultiGraph orienté :
# Création d'un MultiDiGraph
MDG = nx.MultiDiGraph()
MDG.add_edge(1, 2)
MDG.add_edge(1, 2, weight=5)
MDG.add_edge(2, 1)
# Visualisation
pos = nx.spring_layout(MDG)
nx.draw(MDG, pos, with_labels=True, node_color='pink', node_size=500, font_size=10, arrowsize=20)
plt.title("MultiDiGraph")
plt.show()
edges_2004 = [i for i, v in nx.get_edge_attributes(G, "YEA").items() if v == 2004]
G_2004 = G.edge_subgraph(edges_2004)
color = nx.get_node_attributes(G, "color")
>>> color[4]
color=nx.get_edge_attributes(G,'color')
>>> color[(1,2)]
edge_attr = nx.get_edge_attributes(G.subgraph(node_list), "attribute")
nx.set_edge_attributes(G, dict(df.set_index(["node1", "node2"]).COL_NAME), "ATTR_NAME")
# dict(df.set_index(["node1", "node2"]).COL_NAME) could differ but need to be of the form :
# {(node1, node2): attr12, (node3, node4): attr34 , ...}
G.has_edge(0, 1) # using two nodes
>>> True