2013年1月18日

NetworkX を使って GEXF ファイルを作成する

Python でネットワークもしくはグラフデータを扱うライブラリ NetworkX を使って GEXF ファイルを作成してみます。 GEXF は XML でグラフを表現するフォーマットです。

NetworkX is a Python language software package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.

準備

pip を使ってライブラリをインストールします。

$ pip install networkx

NetworkX のサイトのトップページにサンプルコードがありますので、それをコピペして動くことを確認します。 「ノード」と「エッジ」を定義して出力できれば成功です。 add_node() でグラフにノードを追加、 add_edge() でグラフにエッジを追加しています。 明示的にノードを追加しなくても、エッジを追加するとその端点となるノードは宣言されます。 もちろん、定義済みのノードの ID を指定することでエッジは追加されます。

ネットワークにおけるノードの配置

ノードとエッジは抽象的なものですので、そのままではどこにどのように配置するのかが分かりません。 そこで、GEXF の VIZ 拡張に従って位置 (position) と大きさ (size) を指定します。 色 (color) も指定できます。最初の4行はサイトのトップページにあるサンプルコードです。

import networkx as nx

G = nx.Graph()
G.add_node("spam")
G.add_edge(1, 2)

# Add VIZ extension for GEXF writer.
G.node["spam"]['viz'] = {'size': 10,
                         'color': {'r': 255, 'g': 0, 'b': 0},
                         'position': {'x': 0, 'y': 0}}
G.node[1]['viz'] = {'size': 10,
                    'color': {'r': 0, 'g': 255, 'b': 0},
                    'position': {'x': 100, 'y': 100}}
G.node[2]['viz'] = {'size': 10,
                    'color': {'r': 0, 'g': 0, 'b': 255},
                    'position': {'x': 200, 'y': 200}}

グラフの "node" プロパティにキーでアクセスすると個々のノードのデータがあります。 これに "viz" プロパティを追加してあげます。 "size", "color", "position" は見たままの表現なので特に説明は不要でしょう。

GEXF ファイルを出力

NetworkX はいくつものファイル形式をサポートしていますが、 その中のひとつに GEXF もあります。 リファレンスによれば、3つの関数を提供してくれています。

Reference > Reading and writing graphs > GEXF

  • read_gexf(): 与えられたパスから GEXF フォーマットのグラフを読み取ります。
  • write_gexf(): GEXF フォーマットのグラフ G をパスに書き出します。
  • relabel_gexf_graph(): ノードのラベルに対して、"label" キーワードを使ってグラフにラベルを貼り直します。

ということで、先ほどのスクリプトの最後に write_gexf() を追加します。

import networkx as nx

G = nx.Graph()
G.add_node("spam")
G.add_edge(1, 2)

# Add VIZ extension for GEXF writer.
G.node["spam"]['viz'] = {'size': 10,
                         'color': {'r': 255, 'g': 0, 'b': 0},
                         'position': {'x': 0, 'y': 0}}
G.node[1]['viz'] = {'size': 10,
                         'color': {'r': 0, 'g': 255, 'b': 0},
                         'position': {'x': 100, 'y': 100}}
G.node[2]['viz'] = {'size': 10,
                         'color': {'r': 0, 'g': 0, 'b': 255},
                         'position': {'x': 200, 'y': 200}}

nx.write_gexf(G, "example.gexf")

出力結果 ("example.gexf") は次のようになります。

<?xml version="1.0" encoding="utf-8"?><gexf xmlns:ns0="http://www.gexf.net/1.1draft/viz" version="1.1" xmlns="http://www.gexf.net/1.1draft" xmlns:viz="http://www.gexf.net/1.1draft/viz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/XMLSchema-instance">
  <graph defaultedgetype="undirected" mode="static">
    <nodes>
      <node id="1" label="1">
        <ns0:color b="0" g="255" r="0" />
        <ns0:size value="10" />
        <ns0:position x="100" y="100" z="None" />
      </node>
      <node id="2" label="2">
        <ns0:color b="255" g="0" r="0" />
        <ns0:size value="10" />
        <ns0:position x="200" y="200" z="None" />
      </node>
      <node id="spam" label="spam">
        <ns0:color b="0" g="0" r="255" />
        <ns0:size value="10" />
        <ns0:position x="0" y="0" z="None" />
      </node>
    </nodes>
    <edges>
      <edge id="0" source="1" target="2" />
    </edges>
  </graph>
</gexf>

"viz" を使わずに "ns0" という名前空間が追加されてしまうのはキレイではありませんが、定義に沿った XML ファイルになっています。 この GEXF ファイルを Gephigexf-js で閲覧してみましょう。 ノードの位置が指定され、色も付いていることが分かります。 (エッジの色は Gephi が付けています。ノードと同様にして、自分で指定することも可能です。)

終わりに

NetworkX を使って GEXF ファイルを作成してみました。 "viz" プロパティに大きさや位置の情報を付与することで、描画ツールにそのまま渡すことができます。

ここでは無向グラフを扱いましたが、 DiGraph を使うと有向グラフも扱えます。 その他にもいくつかの グラフタイプ をサポートしていますので、用途に合わせて使い分けることも可能です。 また、ノードの「関係」を視覚化したい場合、位置をひとつずつ割り振るのは大変だったりします。 標準でいくつかの レイアウト をサポートしていますので、いくつかの見せ方を試してみると新しい発見があるかもしれません。

関連:

コメントを投稿