長文を読むのは大変ですよね。Pythonで自然言語処理をすることで、可視化する手法があるそうなので、挑戦してみます。
可視化の手段としてNetworkXが使えそうです。
GalleryのAlgorithmsのところに「Betweenness Centrality」が紹介されていましたので、ダウンロードしてグラフを作成しました。紹介されていたものにはテキストがありませんでしが、テキストを表示するようにしました。
Network download (inetbio.org)
何をしているコードなのか調べます。
# ライブラリーのインストール
from random import sample
import networkx as nx
import matplotlib.pyplot as plt
randomモジュールからsample関数をインポートしています。- この関数は、リストなどから指定した数の要素をランダムに選ぶために使います。
networkxライブラリをnxというエイリアスでインポートしています。- このライブラリは、ネットワークやグラフを作成・操作するための強力なツールです。
matplotlibライブラリのpyplotモジュールをpltというエイリアスでインポートしています。pyplotは、データの視覚化を行うための機能を提供します。
# データの読み込み
G = nx.read_edgelist("WormNet.v3.benchmark.txt")
networkxの関数で、エッジリスト形式のデータを持つテキストファイルを読み込み、そのデータを使ってグラフオブジェクトを作成します。- エッジリストとは、ノード間の接続(エッジ)の情報をリスト形式で記述したもので、通常は2列の形式で、1行が2つのノードを表すことが多いです。このデータも1行に2つのノードが入っています。
# 実行速度を上げるためにランダムにノードを削除
num_to_remove = int(len(G) / 1.5)
nodes = sample(list(G.nodes), num_to_remove)
G.remove_nodes_from(nodes)
- num_to_remove = int(len(G) / 1.5)は、グラフ
Gのノードの総数を取得し、その1.5分の1の数(約66%)を計算しています。この数が、削除するノードの数を決定します。 - nodes = sample(list(G.nodes), num_to_remove)は、
G.nodesでグラフのすべてのノードを取得し、list()でリストに変換します。sample()関数を使って、そのリストからnum_to_remove個のノードをランダムに選びます。 - G.remove_nodes_from(nodes)は、ランダムに選ばれたノードをグラフ
Gから削除します。
# 低次数のノードを除去
low_degree = [n for n, d in G.degree() if d < 10]
G.remove_nodes_from(low_degree)
G.degree()は、グラフG内の全てのノードに対する次数を返します。ここでdは各ノードの次数を表します。- リスト内包表記
[n for n, d in G.degree() if d < 10]は、次数が10未満のノードを抽出しています。具体的には、(n, d)というタプルを各ノードに対して生成し、その中でif d < 10の条件に合致するものをリストに追加しています。 G.remove_nodes_from(low_degree)は、上記で抽出したlow_degreeリストに含まれるノードをグラフGから削除します。
# 最大の連結成分を抽出
components = nx.connected_components(G)
largest_component = max(components, key=len)
H = G.subgraph(largest_component)
components = nx.connected_components(G)は、グラフGのすべての連結成分を見つけます。各連結成分は、ノードの集合として表されます。largest_component = max(components, key=len)は、componentsという連結成分の集合の中から、最大の成分を選択しています。ここでkey=lenは、各成分の長さ(ノード数)を基準にして最大の成分を選ぶためのキー関数です。H = G.subgraph(largest_component)は、元のグラフGからlargest_componentに含まれるノードとその間のエッジだけを取り出して、新しい部分グラフHを作成しています。つまり、Hは元のグラフGの中で最大の連結成分だけを含んでいます。
# 媒介中心性を計算
centrality = nx.betweenness_centrality(H, k=10, endpoints=True)
nx.betweenness_centrality(H, k=10, endpoints=True)は、グラフHの各ノードについて、他のノード間の最短経路にどれだけ関与しているかを示す値を計算します。k=10は、計算の際に考慮するノードの数を制限しており、最も重要なノードの10個を選ぶことを示します。endpoints=Trueは、最短経路の端点もカウントするオプションです。これにより、最短経路が端点を含む場合にも、そのノードが媒介中心性に寄与します。
# コミュニティ構造の計算
lpc = nx.community.label_propagation_communities(H)
community_index = {n: i for i, com in enumerate(lpc) for n in com}
nx.community.label_propagation_communities(H)を呼び出すことで、グラフHにおけるノードのコミュニティを検出します。ラベル伝播法を用いて、ノードがどのコミュニティに属するかを決定します。{n: i for i, com in enumerate(lpc) for n in com}は、辞書内包表記を使って、各ノードnをその所属するコミュニティのインデックスiにマッピングします。この結果、各ノードがどのコミュニティに属しているかを示すcommunity_indexという辞書が作成されます。
#### グラフ描画 ####
fig, ax = plt.subplots(figsize=(20, 15))
pos = nx.spring_layout(H, k=0.15, seed=4572321)
node_color = [community_index[n] for n in H]
node_size = [v * 20000 for v in centrality.values()]
nx.draw_networkx(
H,
pos=pos,
with_labels=Ture,
# with_labels=False, FalseとなっているところをTrueに書き換え
node_color=node_color,
node_size=node_size,
edge_color="gainsboro",
alpha=0.4,
)
fig, ax = plt.subplots(figsize=(20, 15))で、20x15インチのサイズの図を作成しています。pos = nx.spring_layout(H, k=0.15, seed=4572321)で、グラフHのノードの位置をスプリングレイアウトを使って計算しています。kはノード間の距離のスケール、seedは再現性のためのランダムシードです。node_colorは、各ノードのコミュニティインデックスに基づいて色を決定しています。node_sizeは、各ノードの中心性を基にしたサイズを設定しています。中心性の値に20000を掛けています。nx.draw_networkxを使って、グラフを描画しています。with_labels=Falseはノードにラベルを表示しない設定です。node_color,node_sizeでそれぞれノードの色とサイズを指定し、edge_color="gainsboro"でエッジの色を薄い灰色に、alpha=0.4で透明度を設定しています。
# タイトルと凡例
font = {"color": "k", "fontweight": "bold", "fontsize": 20}
ax.set_title("Gene functional association network (C. elegans)", font)
font辞書を定義し、タイトルのフォントスタイルを指定しています。色は黒("k")、太字、フォントサイズは20です。ax.set_titleで指定したタイトルをグラフに設定します。
# 凡例の色変更
font["color"] = "r"
ax.text(
0.80,
0.10,
"node color = community structure",
horizontalalignment="center",
transform=ax.transAxes,
fontdict=font,
)
ax.text(
0.80,
0.06,
"node size = betweenness centrality",
horizontalalignment="center",
transform=ax.transAxes,
fontdict=font,
)
- 凡例のテキストの色を赤("r")に変更しています。
ax.textを使って、グラフの特定の位置にテキストを追加しています。0.80と0.10、0.06は、グラフの座標系における位置を指定しています(ax.transAxesを使うことで、0から1の範囲で位置を指定)。horizontalalignment="center"でテキストを中央揃えにしています。
# 可読性を高めるための最終調整
ax.margins(0.1, 0.05)
fig.tight_layout()
plt.axis("off")
plt.show()
ax.marginsを使って、グラフの周囲に余白を設定しています。ここでは、x軸に対して10%(0.1)、y軸に対して5%(0.05)のマージンを追加しています。これにより、ラベルやノードが図の端に近づきすぎるのを防ぎます。tight_layoutメソッドを呼び出すことで、図全体のレイアウトを自動的に調整し、ラベルやタイトルが重ならないようにしています。これにより、全体の見た目が整えられます。plt.axis("off")を使用して、グラフの軸(x軸とy軸)を非表示にしています。これにより、視覚的にグラフがすっきりとし、データの視認性が向上します。- 最後に、
plt.show()でグラフを表示します。
コメント
コメントを投稿