web-dev-qa-db-ja.com

ネットワークグラフの視覚化を改善するには?

python=でnetworkxを使用して、隣接するマトリックスをグラフに変換しようとしました。私の「加重」グラフには約8000ノードと14000エッジがあります。優れたレイアウトフォームまたは他のパッケージ、ツールがありますか?グラフがより美しくなりますか?結果として、ノードのエッジの重みが高くなるほどノードが近くなるため、クラスターノードを分析できます。

Networkxドキュメントで提供されているすべてのレイアウトを試しました。私もgephiを使用しようとしましたが、それでも私の理想には少し満足できません。これは、networkxでの外観です。すべてのクラスターを表示できますが、集中恐怖症の人には少し恐ろしいように見えます。

enter image description here

以下は、グラフを描くために使用したコードです。

G = nx.Graph()
for i in range(10000):
    for j in range(10000):
        if mat[i][j] > 10:
            G.add_Edge(a[i], a[j], weight=mat[i][j])
pos = nx.nx_pydot.graphviz_layout(G)
plt.figure(figsize=(8, 8))
plt.axis('off')
nx.draw_networkx(G, pos=pos, with_labels=False, node_size=25, edgecolors='black', Edge_color='b')
plt.show()
9
shaoyu0105

大きなグラフの視覚化を少し詳しく見てみましょう:

あなたの質問のコンテキストでは、グラフを視覚化する3つの方法があります。

  1. 一画面でグラフ全体を描く
  2. 1画面よりも大きい面にグラフを描く
  3. グラフを部分的に描画するか、描画される要素の数を減らします

これらの方法を1つずつ確認します。

1.非圧縮性の圧縮

グラフには8000ノードと14000エッジがあります。エッジのないノードのみを描画する必要があると想像してみましょう。したがって、平均的なFullHDディスプレイの場合、次のようになります。

ノードあたり_1920 * 1080 / 8000 = 259_ピクセル。それは:

sqrt(259) = 17

17×17ピクセル。表示全体をノードでタイル表示する場合はノード。ノードラベルを描画する場合は、次のものが必要です。

17 - 1 * 2 (outer node borders) - 1 * 2 (inner node borders) = 13×13 square。最小の可能なフォント(私は話さない 難解 フォント)は3×3(+1)サイズを持っているので、ノードごとに最大9文字を格納できます。

次のようになります。

enter image description here

そして、まだグラフのエッジを描画していません!それをしたい場合は、以下を使用します。

グラフ要素ごとの1920 * 1080 / (8000 + 14000) = 94ピクセル、および:

sqrt(94) = 9.7-_9×9_ px。ノードなので、単純なラベルを付けることはほぼ不可能です。

1つの画面のグラフ全体が常に恐ろしい混乱のように見えることは今や明らかです。したがって、この方法でグラフを描くことはできません。

2.ノンエキスパンドを展開します

1つの画面にグラフを描画できない場合は、頭をすくい上げて、いくつかの画面に描画するための方法を考案できます。それには2つの方法があります。

  • Matplotlibの使用
  • Graphvizの使用

Matplotlibの場合、(figsize引数を使用して)非常に大きな図を作成し、グラフを(plt.savefigを使用して)画像にインポートします。

_import networkx as nx 
import matplotlib.pyplot as plt 

fig = plt.figure(figsize=(40, 40)) 
G = nx.fast_gnp_random_graph(300, 0.02, seed=1337) 
nx.draw(G, node_size=30) 
plt.axis('equal') 
plt.show() 
fig.savefig('waka.svg') 
_

そのため、大きなベクター画像を作成します(ここにその一部を示します)。

enter image description here

この場合、networkxで使用可能な任意のグラフレイアウトを使用できます。

別の方法は、グラフを描画するGraphviz外部ライブラリを使用することです。正直なところ、この場合、networkxはグラフを_.dot_ファイルに変換し、それをGraphvizに送信します。主な欠点は、Graphvizがグラフを描画する方法を制御できないことです。しかし、それはかなり良いレイアウトなので、結果は許容できるでしょう。

次のPythonコードを使用して_.dot_ファイルを生成します:

_import networkx as nx 

G = nx.fast_gnp_random_graph(300, 0.02, seed=1337) 
nx.nx_agraph.write_dot(G, './waka.dot')
_

次に、Graphvizを使用します。

_dot -Tsvg waka.dot >waka.svg_

または無向グラフの場合:

_neato -Tsvg waka.dot -Goverlap=false >waka.svg_

したがって、結果の画像は次のようになります(全体の一部です):

enter image description here

Graphvizにはさまざまなオプションが数多く用意されているため、グラフをほぼ希望どおりに変換できます。

3.切断できないものを切り取ります

グラフには、巨大な接続コンポーネント( [〜#〜] gcc [〜#〜] )のようなものがあり、多くの小さなサブグラフがあります。全体像は約580×580サイズで、GCCは約290×290サイズなので、GCCは以下を使用します。

キャンバスの_(290 × 290) ÷ (580 × 580) × 100 = 25%_。 GCCのみを保持する場合は、描画するスペースが4倍になります。この場合、別の接続されたコンポーネントを別の画像に描画できます。

次のようなコードでGCCのみを保持できます。

_import networkx as nx 

G = nx.fast_gnp_random_graph(300, 0.01, seed=1337)
gcc = max(nx.connected_components(G), key=lambda x: len(x))
H = G.subgraph(gcc)
nx.draw(G, node_size=30, node_color='red')
_

元のグラフを描画します:

enter image description here

そしてこの最後の行で:

nx.draw(H, node_size=30, node_color='red')

gCCのみを描画します。

enter image description here


追伸.

グラフで他に何ができるか:

  • ノードをクラスター化する
  • ノードサイズで再生(PageRankなど)
  • エッジカラーで遊ぶ
  • エッジを描画せずにレイアウトを維持する
  • WEEP(私の答えが少しでも役に立たなかった場合)
11
vurmux