PythonのNetworkXの使い方|ノードやエッジの追加、削除、座標の取得を解説する

スポンサーリンク

NetworkXパッケージは、グラフやネットワークを研究するためのPythonライブラリです。

動的で複雑なネットワーク構造を作成、操作、研究するためのツールを提供します。

NetworkXを使用すると、多くのデータ形式でネットワークをロードして保存し、多くの種類のランダムおよび古典的なネットワークを生成し、ネットワーク構造を分析し、ネットワークモデルを構築し、新しいネットワークアルゴリズムを設計し、ネットワークを描画し、その他にも多くのことを行うことができます。

この記事では、NetworkXを使用してグラフを作成し、ネットワークを研究する方法を学びます。

スポンサーリンク

NetworkX パッケージのインポート

NetworkX パッケージを使用するために、ローカルマシンにダウンロードする必要があります。

pipコマンドでダウンロードできます。

pip install networkx

そして、以下のようにライブラリをインポートします。

import networkx as nx

グラフにノードを追加する

まず、以下のように Graph() クラスを呼び出して、空のグラフを作成します。

G = nx.Graph()

NetworkXのノードは、整数、文字列、画像、XMLオブジェクトなど、ハッシュ可能な任意のオブジェクトにすることができます。

また、NetworkXのグラフであることもできます。

グラフにノードを追加するには、2つのメソッドがあります。

  • add_node()。ノードを1つずつ追加するメソッドです。
  • add_nodes_from(): このメソッドは、1つのノードを一度に追加するために使用されます。リストやセットなどの反復可能なコンテナを受け取り、複数のノードを一度に追加するメソッドです。
import networkx as nx
 
G = nx.Graph()
 
G.add_node(1)
G.add_nodes_from([2,3,"node 5"])
print(G.nodes())
[1, 2, 3, 'node 5']

グラフにエッジを追加する

エッジとは、2つのノードの間のリンクのことです。

グラフにエッジを追加するには、主にこの2つの方法が使われます。

パラメータで指定された未知のノードは、自動的にグラフに追加される。

  • add_edge()。一度に1つのエッジを追加するメソッド。
  • add_edges_from(): このメソッドは、一度に1つのエッジを追加します。リストやイテレータのようなエッジのタプルの反復可能なコンテナを取る。

ノードやエッジの再追加は、NetworkX では無視されます。

import networkx as nx
 
G = nx.Graph()
 
# Adding one edge at a time
# Node 1 and 2 will be automatically added
G.add_edge(1,2)
G.add_edge(3,2)
 
# Adding multiple edges at a time
G.add_edges_from([(4,2), (3,5), (5,4)])
 
# Adding duplicates will be ignored.
G.add_node(1)
G.add_edge(1,2)
 
print(G.nodes())
print(G.edges())
[1, 2, 3, 4, 5]
[(1, 2), (2, 3), (2, 4), (3, 5), (4, 5)]

グラフからノードとエッジを削除する

ノードやエッジを追加するのと同様に、一度に単一のノードやエッジを削除することができますし、一度に複数のノードやエッジを削除することもできます。

  • remove_node()。このメソッドは、1つのノードとそのノードに関連するエッジをグラフから削除します。もし、そのノードがグラフに存在しない場合、NetworkXErrorを発生します。
  • remove_nodes_from(): このメソッドは反復可能なコンテナを取り、グラフからすべてのノードとそのノードに関連するエッジを削除します。ノードがグラフに存在しない場合は、何も変更せずに黙って破棄します。
  • remove_edge()。このメソッドは、ノードをそのままにグラフからエッジを1つ削除します。もし、そのエッジがグラフに存在しない場合は、NetworkXErrorを発生します。
  • remove_edges_from(): このメソッドは、反復可能なコンテナを受け取ります。このメソッドは反復可能なコンテナを取り、グラフからエッジを削除します。グラフに存在しないエッジは、変更されずに破棄される。
import networkx as nx
 
G = nx.Graph()
 
# Creating graph
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
G.add_edges_from([(5, 6), (5, 7), (5, 8), (7, 8)])
 
print(G.nodes())
print(G.edges())
 
# Removing edge 1-2 from graph
G.remove_edge(2, 1)
# Removing edge 3-4 and 1-4 at once
G.remove_edges_from([(3, 4), (1, 4)])
 
print()
print(G.nodes())
print(G.edges())
 
# Removing node 5 from graph
G.remove_node(5)
# Removing node 7 and 8
G.remove_nodes_from([7,8])
 
print()
print(G.nodes())
print(G.edges())
[1, 2, 3, 4, 5, 6, 7, 8]
[(1, 2), (1, 4), (2, 3), (3, 4), (5, 6), (5, 7), (5, 8), (7, 8)]
 
[1, 2, 3, 4, 5, 6, 7, 8]
[(2, 3), (5, 6), (5, 7), (5, 8), (7, 8)]
 
[1, 2, 3, 4, 6]
[(2, 3)]

グラフの要素にアクセスする

NetworkXのグラフでは,以下の4つの基本的なグラフ要素にアクセスすることができます.

  • G.nodes。グラフ内のノードのリストを返します。
  • G.edges: G.edges: グラフに含まれるエッジのリストを返します.
  • G.adj: G.adj: すべてのノードの隣接リストを返す.ノードXの隣接リストには,ノードXに直接リンクしている隣接ノードが含まれる.ノードに隣接するすべてのノードには,添え字表記(G.adjの後に角括弧を使用)でアクセスできる.
  • G.degree: G.degree: グラフ中の各ノードにリンクしているノードの数を返す.G.degree`の後に角括弧を付けると、そのノードの学位にアクセスできる。
import networkx as nx
 
G = nx.Graph()
 
G.add_edges_from([(1,2), (1,3), (3,4), (3,5)])
 
print("Nodes")
print(G.nodes)
print("Edges")
print(G.edges)
print("Adjacency List")
print(G.adj)
print("Degree")
print(G.degree)
 
print()
 
print("Adjacency List for node 3")
print(G.adj[3])
print("Degree for node 3")
print(G.degree[3])
Nodes
[1, 2, 3, 4, 5]
Edges
[(1, 2), (1, 3), (3, 4), (3, 5)]
Adjacency List
{1: {2: {}, 3: {}}, 2: {1: {}}, 3: {1: {}, 4: {}, 5: {}}, 4: {3: {}}, 5: {3: {}}}
Degree
[(1, 2), (2, 1), (3, 3), (4, 1), (5, 1)]
 
Adjacency List for node 3
{1: {}, 4: {}, 5: {}}
Degree for node 3
3

Graph, Nodes, Edges の属性

各グラフ、ノード、エッジは、関連する属性辞書にキーと値の属性ペアを保持することができます。

デフォルトではこれらは空であるが、 add_edgeadd_node を用いて属性を追加したり変更したり、グラフ G に対して G.graph, G.nodes, G.edges という名前の属性辞書を直接操作したりすることができる。

1. グラフの属性

nx.Graph()`を使用してグラフを作成する際に、グラフに属性を割り当てることができます。

import networkx as nx
G = nx.Graph(graph_description = "This is an empty graph")
print(G.graph)
# Output: {'graph_description': 'This is an empty graph'}

また、辞書オブジェクトのように後から属性を追加・変更することもできます。

import networkx as nx
G = nx.Graph()
G.graph["description"] = "This is empty graph"
G.graph["data"] = 5
print(G.graph)
# Output: {'description': 'This is empty graph', 'data': 5}

2. ノードの属性

ノードに属性を追加するには、 add_node(), add_nodes_from() または G.nodes を使用します。

また、G.nodes.data() を使用すると、すべてのノードの属性を取得することができます。

特定のノードを指定する場合は、角括弧を使用してください。

import networkx as nx
G = nx.Graph()
 
# Using add_node
G.add_node(1, data = "data1")
 
# Using add_nodes_from
G.add_nodes_from([(2, {"data": "data2"}),
                  (3, {"data": "data3"})],
                   node_type = "child node")
 
# Adding more attributes on node 1 using G.nodes
G.nodes[1]["type"] = "root node"
 
print(G.nodes.data())
# Output: [(1, {'data': 'data1', 'type': 'root node'}), (2, {'node_type': 'child node', 'data': 'data2'}), (3, {'node_type': 'child node', 'data': 'data3'})]
 
print(G.nodes[1])
# Output: {'data': 'data1', 'type': 'root node'}

3. エッジの属性 – 重み付けグラフの作成

エッジの属性は、 add_edge(), add_edges_from(), G.edges または添え字記法を用いて追加することができる。

エッジに属性を付与することで、図のような重み付きグラフを作成することができます。

import networkx as nx
G = nx.Graph()
 
# Using add_edge
G.add_edge(1, 2, weight = 50)
 
# Using add_edges_from
G.add_edges_from([
                  (1, 3, {"weight": 70}),
                  (1, 4, {"weight": 100})
                ])
 
# Using subscript notation
G.add_edge(4,5)
G[4][5]["weight"] = 175
 
# Using G.edges
G.edges[1, 2]["weight"] = 10
 
print(G.edges.data())
 
# Output: [(1, 2, {'weight': 10}), (1, 3, {'weight': 70}), (1, 4, {'weight': 100}), (4, 5, {'weight': 175})]

NetworkXパッケージのグラフの可視化

NetworkXパッケージでは、図のようにdraw()メソッドを用いてグラフを描き、可視化することができます。

import networkx as nx
 
G = nx.Graph()
 
# Using add_edge
G.add_edge(1, 2, weight = 12.5)
G.add_edge(3, 2, weight = 50.0)
G.add_edge(1, 3, weight = 17)
G.add_edge(4, 2, weight = 100)
G.add_edge(2, 5, weight = 1)
G.add_edge(4, 6, weight = 25.5)
G.add_edge(7, 4, weight = 175)
G.add_edge(5, 8, weight = 90)
 
nx.draw(G, with_labels= True, font_weight='bold')
import networkx as nx
import matplotlib.pyplot as plt
 
G = nx.Graph()
 
# Using add_edge
G.add_edge(1, 2, weight = 12.5)
G.add_edge(3, 2, weight = 50.0)
G.add_edge(1, 3, weight = 17)
G.add_edge(4, 2, weight = 100)
G.add_edge(2, 5, weight = 1)
G.add_edge(4, 6, weight = 25.5)
G.add_edge(7, 4, weight = 175)
G.add_edge(5, 8, weight = 90)
 
 
pos=nx.circular_layout(G)
nx.draw(G, pos, with_labels=True, font_weight='bold')
edge_weight = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels = edge_weight)
plt.show()

重みのあるグラフを描画したい場合は、グラフ、pos、edge_label属性を指定した nx.draw() と共に draw_networkx_edge_labels() を使用します。

import networkx as nx
 
DG = nx.DiGraph()
 
DG.add_edges_from([(1,2), (2,3), (3,4), (4,5), (5,2), (4, 6)])
 
# Print edges going out from node 4
print("Out edges of node 4 are:",DG.out_edges(4))
 
# Print in degree of node 2
print("In Degree of node 2 is:",DG.in_degree(2))
 
# Print successors of node 4
print("Successors of node 4 are:",list(DG.successors(4)))
 
# Print predecessors of node 2
print("Predecessors of node 2 are:",list(DG.predecessors(2)))
 
nx.draw(DG, with_labels= True, font_weight='bold')
Out edges of node 4 are: [(4, 5), (4, 6)]
In Degree of node 2 is: 2
Successors of node 4 are: [5, 6]
Predecessors of node 2 are: [1, 5]

NetworkX パッケージを用いた有向グラフの作成

NetworkX では、有向グラフに特化した追加のメソッドやプロパティ、例えば DiGraph.out_edges, DiGraph.in_degree, DiGraph.predecessors(), DiGraph.successors() 等を提供する DiGraph() クラスを用いて、有向グラフを作成することも可能です。

NetworkX Graph Visualization
NetworkX Graph Visualization
NetworkX Graph Visualization With Weights
NetworkX Graph Visualization With Weights
NetwokX Directed Graph
NetworkX Directed Graph

まとめ

この記事では、NetworkX パッケージと、それを使ってグラフを作成、操作、視覚化する方法について学びました。

このライブラリは、複雑なネットワークやグラフを研究する際に役立ちます。

数学者、物理学者、生物学者、コンピュータ科学者などが研究のために使用します。

お読みいただきありがとうございました。

タイトルとURLをコピーしました