はじめに
この書籍に networkx+matplotlib による 静的共起ネットワーク が紹介されています。
以前の記事 の通り、無事に描くことはできたのですが、
- ネットワークレイアウト(描画アルゴリズム)を選択できるようにしたい
- ノードを部分ネットワークごとに色分けしたい(※部分ネットワーク=コミュニティ)
- コミュニティ分割のアルゴリズムを変更できるようにしたい
- ノードの配置を決めるlayoutのパラメータkを変更できるようにしたい
- ノードのサイズを変えたい
- ノードテキスト(表記単語)の表記サイズをノードのサイズに応じ、大きくしたい
- 単語表記のフォントサイズを変えたい
など、カスタマイズしてみたい! ということでやってみましたという記事です。
なお、以下のサイトが 超参考になりました。
実行したこと
共起ネットワーク
以下がカスタマイズ後です。
まずは、レイアウト(描画アルゴリズム)による違いからです。
レイアウト(描画アルゴリズム)変更
springレイアウト
layoutでspring, fruchterman_reingold を選択した場合のみ、パラメータk の値を変えるとノードの配置を変えることができます。
値を小さくすると コミュニティ毎に分かれてくれ、値を大きくするとコミュニティ同士が重なり合う感じです。パラメータk の設定範囲は0-1です。
以下は、springレイアウトにおいて、kの設定を小さく(0.04)して描画させたものです。
kamada_kawaiレイアウト
これは、nlplot に近いですね。これではテキストサイズがノードサイズに応じすこしだけ大きくなるように調整しています。(※あとで述べるフォームで比率が変えられるようにしています。)
circularレイアウト
spiralレイアウト
fruchterman_reingoldレイアウト
springレイアウトと近いですね。どうもアルゴリズムは同じようです。
randomレイアウト
spectralレイアウト
これは・・・おまけですね。
コミュニティ検出アルゴリズム変更
networkx は いくつかの コミュニティ検出アルゴリズム が実行できます。
コミュニティ検出アルゴリズムは、さまざまなネットワークで密に接続されたコンポーネントグループを明確にしてくれます。
community_algorithmによる違いは以下の通りです。(※レイアウトはspringレイアウトとしています。)
greedy_modularity
label_propagation
connected_components
各種調整し、以下に落ち着きました。
上記の描画条件は以下です。
コードに関する補足
テキストアナリティクス入門 に掲載されているコードからの差分についてのみ、以下に補足します。
まず、共起ネットワークのカスタマイズ変数をGoogle colabのフォーム機能を利用しセット。
#@title 共起ネットワーク表示
#@markdown **<font color= "Crimson">ガイド</font>:layout** でネットワークレイアウトが選択できます。**community_algorithm** でコミュニティ分割のアルゴリズムが選択できます。(greedy_modularityはモジュラリティ最適化、label_propagationはラベル伝搬、connected_componentsは連結成分)|**weight_cuttoff** で一定の割合に満たない共起を除外(枝切り)できます。|**node_size** で円の大きさ、**text_size** で単語表記サイズが変更でき、**node_fit_rate**でノードサイズに応じたサイズアップレートが指定できます。|**layout_parameter_k** はノード間の反発力の設定です。**k**が大きいほどノードの配置は円形に近くなります。(この設定はspringとfruchtermanレイアウト時のみ有効)
layout = 'kamada_kawai' #@param ['spring','fruchterman_reingold','kamada_kawai','spectral','spiral','circular','random']
community_algorithm = 'greedy_modularity' #@param ['greedy_modularity','label_propagation','connected_components']
weight_cutoff = 0.025 #@param {type:"slider", min:0.01, max:0.05, step:0.005}
node_size_ = 3500 #@param {type:"slider", min:1000, max:6000, step:500}
text_size = 9 #@param {type:"slider", min:5, max:30, step:1}
text_size_node_fit_rate = 0.3 #@param {type:"slider", min:0, max:1, step:0.05}
layout_parameter_k = 0.07 #@param {type:"slider", min:0.01, max:1, step:0.01}
上記コードにより、Google Colabのセルに以下のフォームが表示されます。
コミュニティライブラリをインポート
from networkx.algorithms.community import greedy_modularity_communities
from networkx.algorithms.community import label_propagation_communities
def pyplot_network (G):
plt.figure(figsize=(20, 11), dpi=300)
if layout == 'spring':
pos = nx.spring_layout(G, k=layout_parameter_k,iterations=50, threshold=0.0001, weight='weight', scale=1, center=None, dim=2, seed=123)
elif layout == 'fruchterman_reingold':
pos = nx.fruchterman_reingold_layout(G, dim=2, k=layout_parameter_k, pos=None, fixed=None, iterations=50, weight='weight', scale=1.0, center=None)
elif layout == 'spectral':
pos = nx.spectral_layout(G, weight='weight', scale=1, center=None, dim=2)
elif layout == 'spiral':
pos = nx.spiral_layout(G, scale=1, center=None, dim=2, resolution=0.35, equidistant=False)
elif layout == 'kamada_kawai':
pos = nx.kamada_kawai_layout(G, dist=None, pos=None, weight=1, scale=1, center=None, dim=2)
elif layout == 'circular':
pos = nx.circular_layout(G, scale=1, center=None, dim=2)
else:
pos = nx.random_layout(G, center=None, dim=2, seed=None)
connecteds = []
colors = []
if community_algorithm == 'greedy_modularity':
for i, c in enumerate(greedy_modularity_communities(G)):
connecteds.append(c)
colors.append(1/20 * i)
if community_algorithm == 'label_propagation':
for i, c in enumerate(label_propagation_communities(G)):
connecteds.append(c)
colors.append(1/20 * i)
else:
for i, c in enumerate(nx.connected_components(G)):
connecteds.append(c)
colors.append(1/20 * i)
node_colors = []
for node in G.nodes():
for i, c in enumerate(connecteds):
if node in c:
node_colors.append(colors[i])
break
テキスト表示は、nx.draw_networkx_labels() ではなく、ノードサイズに応じたテキストサイズにするため、以下のコードとしています。
text_sizeでテキスト表示の最小フォントサイズを指定し、text_size_node_fit_rate でノードサイズに応じてフォントを大きくして表示させるというものです。
from matplotlib.pyplot import figure, text
d = dict(G.degree)
for node, (x, y) in pos.items():
text(x, y, node, fontsize=text_size+d[node]*text_size_node_fit_rate, ha='center', va='center')
plt.axis ("off")
plt.savefig("networkx.jpeg")
plt.show()
また、以下の引数を追加しています。
- nx.draw_networkx_nodes()の引数に node_color=node_colors, alpha=0.3 を追加
- nx.draw_networkx_edges()の引数に alpha=0.4, edge_color="darkgrey" を追加
※alphaは、透明度です。
ムリヤリPlotly表示
Jpeg保存した共起ネットワーク(ファイル名「networkx.jpeg」)をムリヤリ Plotly で表示させました。
解像度をある程度確保しないときびしいので、dpi=300 としました。
あとはムリヤリ描くだけ・・・
#@title 共起ネットワーク表示(Plotly)
import plotly.express as px
from skimage import io
img = io.imread('networkx.jpeg')
fig = px.imshow(img)
fig.update_layout(width=1500, height=1000, margin=dict(l=10, r=10, b=10, t=10))
fig.update_xaxes(showticklabels=False).update_yaxes(showticklabels=False)
fig.show()
最後に
nlplot には敵わないですが、自分好みに見た目をカスタマイズしたいな・・・というときはよいとおもいます。
肝心なのはテキストを分析することなので、美しく描いてモチベをあげることと、共有しやすくすることを通して、よりよき前進を図りたいというところです。
それにしても
networkx はすごいです。いろんなことができすぎ。。。ですね。
networkx で共起ネットワークを描きたい!という方は、ぜひ「テキストアナリティクス入門」を手にされることをおすすめします。(私は回し者ではありません)
GoogleColabで実行するために必要なことについては、以下で触れています。
参考