Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

鉄道路線データをグラフとしてCytoscapeで可視化する 4: 東京メトロのデータを例に

More than 5 years have passed since last update.

はじめに

このシリーズは、Cytoscapeを使ってやIPython NotebookPandasなどのオープンソースツールを利用し、公開データを元に実際のグラフ可視化を行う過程を紹介する、可視化の実践者向けの記事です。

最終回は、グラフ可視化で重要なレイアウトとスタイル設定、そしてCytoscapeで作成したデータの他のアプリケーションでの利用について紹介します。

東京メトロのアプリコンテスト

このシリーズでは、どなたにも馴染みのあるデータとして鉄道路線図のグラフデータを例として利用しました。全くの偶然ですが、まもなく東京メトロが運行状況などの各種情報をJSON-LDとして公開し、アプリケーションコンテストを行うと発表しました:

これはコンテスト参加者しか利用できないデータなので、真の意味でのオープンデータではないのですが、それはまあ今後に期待ということで。せっかくなので、先日作成した東京メトロのデータセットを例に、レイアウトやスタイリングでどのように見え方が変わるのかを紹介したいと思います。ここで作成した基本的なグラフ可視化結果にAPIから取得した各種データを各種視覚変数にマッピングすることで、最終的なアプリケーション作成の前に、基本的なデザインやレイアウトを確認するのにも使えると思います。まだデータの詳細が発表になっていないので、コンテストで利用できる実際のデータを使用することは出来ませんが、可視化の方針が路線図データを元に、そこへ各種情報、すなわち電車の位置、遅延、時刻表等をマッピングするというものでしたら、ここで解説してある基本的なここで解説してある基本的なテクニックは、実際のデータでも問題なく利用できると思います。

また最後に触れますが、私達のプロジェクトで作成しているネットワーク可視化JavaScriptライブラリのCytoscape.jsや、D3.jsのForceレイアウトで利用できるJSON形式でデータを書き出すことも可能ですから、最終的に作成するウェブアプリで利用するデータの作成ツールとしても使えます。

レイアウトとスタイルを使いこなす

グラフ可視化において、各種アルゴリズムを利用した自動レイアウトとデータを視覚変数にマッピングするスタイルの作成は重要なステップです。今回はこれをCytoscapeでどのように行うかを見ていきます。

利用するデータセット

手元で実際に試せるように、前回までに作成したデータを元にしたCytoscape用のセッションファイルを用意しましたので、これを使います。統合した全国版のデータを、東京メトロの部分だけ切り出したものです:

スタイル作成

Review: スタイルとは?

Cytoscapeでは、可視化に使われるマッピングの集合をVisual Styleと呼んでいます。これは2つの要素に分解できます:

  • デフォルト値 - 何のマッピングも存在しない時に使われる値
  • マッピング - データから視覚変数(CytoscapeではVisual Propertyと呼ばれます)への変換

この2つを上手く調節して行くことにより最終的な可視化を作成します。

実際のスタイル作成

今回の可視化のテーマは、ビギナー用の簡単な例として「銀座線、丸ノ内線、東西線の各駅の2012年度の一日あたりの平均乗降客数を見やすく提示する」とします。このゴールに向かってレイアウトとスタイルを決定していきます。

まず上のリンクからダウンロードしたセッションファイルを開くと、必要最小限のマッピングが設定されたデータが表示されます:

minimal_style1.png

この状態では何のデータかよくわかりませんね。ここでは、ほとんど何のマッピングも設定されていません。ここから必要な値を設定することにより、より分かりやすい見た目に加工していきます。まずは「過剰な装飾を避けるため、本当に必要のある視覚要素以外は極力削ぎ落とす」と言う方針に則り、ノードの境界線(Nord Border)を削除したいと思います。これは、Node Border Widthのデフォルト値をゼロに設定するだけです(Def.以下にある四角いエリアをクリックすることで値を入力できます):

border1.png

すると見た目は以下のように変化します:

minimal_style.png

この「白地図」に各種データをマッピングしましょう。

Passthrough Mapping

このサンプルでは、予め一つだけマッピングが設定されています。それは、駅名(station_name)と言うデータからノードラベル(Node Label)と言う視覚変数へのPassthroughマッピングです。前回も触れたように、Passthroughは単純にデータの値を視覚変数にそのまま渡すだけです。つまりこの場合は、「station_nameと言うカラムに存在する値を、そのままノードのラベルとして描け」と言う意味です。

ではここで実際にこのタイプのマッピングを設定しましょう。今回のデータは、前々回に収集した路線ごとの色データ(line_colorと言う名前のカラム)も含みますので、それを使ったPassthroughマッピングを設定します。

  • line_colorからNode Fill Color
  • line_colorからEdge Stroke Color (Unselected)

colorpt1.png colorpt2.png

すると、16進数で指定された色がそのままノードとエッジの色に反映されます:

minimal_style2.png

デフォルト値の変更

次はマッピングの必要のない要素の初期値を調整することにより、全体をより見やすく調整します。

  • ノードの形を円形に変更 - Node ShapeをEllipse(楕円)に。
  • 路線図らしく、各路線を太い線で表現 - Edge Widthを20へ。

これで見た目は以下のように変化します:

minimal_style3.png

ではここで一度自動レイアウトを適用して繋がりを見やすくしましょう。ここでは、yFiles社の開発したプロプライエタリな自動レイアウトアルゴリズムであるOrganicレイアウトを使ってみます:

organic.png

metro_layout1.png

ここでは駅の配置は純粋にグラフとしてのつながりを元に計算されていますので、地理的な位置などは一切考慮されていません。

Discrete Mappingによる乗り換え可能を示すエッジの区別

第二回で、元となったデータ内に含まれている駅グループの情報を用いて、乗り換え可能を表すエッジを追加しました。これを他のエッジと区別するマッピングを作成します。これにはDiscrete Mappingを使用します。Interactionと呼ばれるエッジのタイプを示すカラムを使い、ここに含まれる0と言う乗り換え可能を表す値に細い点線を表示するようにマップします。すなわち、

  • Interactionの値が0ならば:
    • Edge Line Typeを点線に
    • Edge Widthを2に

と言う簡単な命令をDiscreteマッピングで作ります:

スクリーンショット 2014-09-07 20.31.43.png スクリーンショット 2014-09-07 20.31.58.png

これにより、他のエッジに比べて、徒歩での乗り換え可能を意味する特殊なエッジが細い点線で表示されます:

minimal_style4.png

レイアウト

ここでは、自動レイアウトがどのようなものかを試してみましょう。以下は、Layoutメニュー以下から選択できる各種自動レイアウトアルゴリズムをこの東京メトロのネットワークに適用したものです:

Circular

円形にノードを配置するレイアウト。とても単純なアルゴリズムなので、大規模なネットワークにも利用できます。
circular.png

Force-Directed

いわゆる力学モデルを利用したアルゴリズムで、ネットで見られるグラフ描画のサンプルの多くはこれでレイアウトしてあります。多くの場合うまく行くのですが、大変重い計算なので、大規模グラフには非常に長い時間を要します。
force-directed.png

Hierarchical

階層的な構造を持ったデータに適しますが、そうでないものも強引にツリー状に並べることも可能です。
hir.png

レイアウトアルゴリズムの選択

どのレイアウトアルゴリズムを選択するかは純粋に最終的な可視化をどのようなものにしたいかというゴールによります。一般的に、このような地理データに対して自動レイアウトを行えば、地図上での位置関係は失われます。しかし、抽象化された接続図と言う物を可視化し、そこに各種データをマッピングするのならば、実際の位置関係よりも、以下の様な抽象化されたモノのほうが都合のいい場合が多いです。


(東京メトロの作成した丸ノ内線の手書き路線図)

その場合、選択した部分ごとに各種レイアウトを利用し、データマッピングに適した形に仕上げるのがベストです。

マニュアルレイアウト

この他にも、手動で微調整を行うときに利用するマニュアルレイアウトと言う機能もあります。Illustratorをお使いの方ならお馴染みの、指定したオブジェクトを整列させたり、拡大、回転などを行う機能です。後ほど例の中で使用します。

数値を視覚変数にマッピングする: Continuous Mapping

ここでは、今回のメインである乗降客数を利用するマッピングを作成します。安直ですが、2011年度の乗降客数を以下のVisual Propertyにマッピングします。

  • ノードの大きさ
  • ラベルの文字の大きさ

ここでは乗降客数という数値を大きさに変換するので、Continuous Mappingを使用します。以下のように、最大値と最小値に対してマッピング先の値を指定することにより、シンプルな線形のマッピングを作成できます:

cont1.png

cont2.png

結果、乗降客数が多いほど大きなノード、大きなラベルで表示される図が作成されます:

cont_final.png

サブグラフ切り出しと加工

ここで、最終的に必要な三路線を切り出します。検索窓に以下のクエリを打ち込んでエンターを押すと、目的のノードが選択されます:

銀座線 OR 丸ノ内線 OR 東西線

と入力して、CTR+N (Macの場合はCommand+N)で切り出せます。これにyFiles→hierarchicレイアウトを適用すると以下のようになります:

comparison1.png

ここからの仕上げは手動で作業を行います。プルダウンメニューからCopy Styleを選んで、新しいスタイルをこのサブグラフ向けに作成しましょう:

copy.png

スケーリング

横軸が詰まりすぎているので、幅を広げて見やすくします。Layout → Scalingで表示されるパネルを利用します。X軸方向のスケーリングを選択し、見やすくなるように8倍程度まで広げます。ちなみに、Reset scale barをクリックすれば、そこからまた拡大できるので、いくらでも大きく出来ます。

scaling.png

ラベル位置の変更

ラベルを見やすい位置に移動します。これはNode Label PositionというVisual Propertyのデフォルト値を変更することで行います。デフォルトの状態では表示されていないと思うので、まずPropertiesの一覧から選んで表示させます:

prop.png

そして位置をドラッグ&ドロップで決めたあとに、X方向のオフセット値で微調整します:

labelpos.png

整列

拡大することにより各路線がずれてしまっていると思うので、これを修正します。路線ごとにドラッグで選択して、Aligh & Distributeのパネルから縦方向の串刺しアイコンを選べば自動整列します:

aligh.png

必要に応じて細部を調整して、最終的には以下の様なものに仕上げます:


(ハイレゾ版はこちら

簡単な描画ですが、とりあえずどの駅が乗降客が多いか、をざっと把握することは出来ると思います。なお、データの無い駅については小さく表示して混乱を招かないようにしてあります。

これはマッピング機能(Visual Style)を学ぶための単純な可視化の一例に過ぎませんので、上のリンクからダウンロードしたセッションを色々といじってみて、マッピングをどう変更するとそれがどう可視化に反映されるのかを調べてみてください。以下は同じセッションから作った別のサンプルです:

(full res)

(full res)

Webアプリケーションとの連携

spa.png

Cytoscapeでこういったスケッチを作成した場合、何も画像としてのスケッチだけで終わらせる必要はありません。私達の長期的なビジョンとして、今存在する様々な著名ツール(D3.js、Pandas、igraph等の可視化や解析のためのツール群)との連携は重要な項目の一つで、できるだけ一般的な形式でのデータ書き出しをサポートしています。

Cytoscape.js用JSON形式への書き出し

Cytoscape.js形式のJSONとしてネットワークとスタイルを書き出すことが出来ます。これらは直接Cytoscape.jsでレンダリング可能です。また、これらはシンプルなJSONファイルに過ぎませんので、ちょっとした処理を加えれば、他の様々なアプリケーションで利用できると思います。

どうやってJavaオブジェクトをCytoscape.js用のJSON形式にしているのか?

CytoscapeはJavaで書かれたデスクトップアプリケーションで、ネットワーク、テーブル、そしてスタイルも全部Javaオブジェクトです。これらをそのままJackson等のデータマッパを使ってもCytoscape.js形式には上手く変換できませんので、書き出しはカスタムシリアライザを作成してJSONを作っています。特にスタイルは、Cytoscape.jsのCSSのセレクタ形式に各マッピングを変換するため、マッピングの設定によってはとても効率の悪いセレクタが生成されます。JSON形式へのスタイル書き出しを行う場合、Passthrough形式で指定したものが最も効率のいいセレクタを生成します。これはCytoscapeで可視化を作成するときのベストプラクティスではないのですが、最終的にはCytoscape.jsでの利用を考えている場合、これは頭の隅に置いておくと良いでしょう。

D3.jsのForce形式での書き出し

このAppを使うことにより、D3.jsのForceレイアウトで直接使えるデータ形式に書き出すことも可能です。

D3.jsとグラフデータ

D3.jsには「元になるデータのフォーマットに関する制約は最小限にする」と言う思想があるようです。基本的にはCSVなどのテーブル形式でデータを用意すればほとんどの場合はそのまま読み込めます。そんな中グラフ形式のデータに関しては、並び順(ordinal)をIDとみなすという、冗長性は少なくなる一方、若干可読性に欠ける方式となっています。もちろんそれでもシンプルなので、ちょっとしたスクリプトを書いてしまえば済む作業ですが、目で見ながらグラフィカルにグラフ構造をエディットし、それを自動的に書き出せたらそれも便利です。D3.js Exporterは、Cytoscape上で動くプラグイン(App)で、読み込まれたグラフのトポロジと属性データをそのままD3.jsで読み込める形式に書き出すものです。

D3.jsで簡単に読める形式への書き出し

Appをインストールしたあとは、File → Export → Networkで、ファイル名を指定してD3.js形式のフォーマットを選択するだけです。書き出しの結果はこんな感じになります

D3.js側の基本的なコード

D3.js上で、このJSONに含まれるデータを使ったマッピングを作るのは簡単です。例えば、2012年度の乗降客数データをそのままノードの大きさにマッピングする場合、返り値を半径にマップするだけです:

node.append("circle")
    .attr("class", "node")
    .attr("r", function(data) {
        return data.passengers2012;
    });

この辺りは大量にサンプルが出回っているので、D3.jsとForce Layoutで検索してみてください。D3.jsで可視化を作成する場合、D3.jsでデータを準備したり加工するのはナンセンスですから、IPython Notebook, Pandas, Cytoscape辺りを組み合わせてデータの下準備をしておくと便利だと思います。D3.js側でのコードは上記のようなマッピングや、トランジションといった部分に集中できますので。

D3.jsの使いどころ

リンクした下の例を見ていただければお分かりになると思いますが、JavaScriptでグラフ(ネットワーク)を描画する、と言うだけでしたら、Cytoscape.jsなどを使う方がはるかにコード量も少ないですし、APIの抽象度も高レベルで簡単です。しかし、単なるnode-link diagramを超えた新しい可視化を試したいような場合は、D3.jsのローレベルさが逆に便利です。例えば、D3.jsのTransitionを上手く使って、node-link図とTreemapを切り替え可能にしたりといった場合です。また、D3.jsはデフォルトではSVGで描画する場合がほとんどでしょうから、最終的な出力が紙などの場合もこれは便利な点です(Cytoscape.jsを含むグラフ可視化ライブラリのほとんどがCanvasを利用していますので)。

Single Page Applicationとしての書き出し

これはまもなくリリースされるCytoscape 3.2.0の新機能なのですが、バラバラにJSONファイルを書き出す代わりに、プリセットのWebアプリケーションとして書き出す機能があります。要するに、サーバにそのフォルダごとアップロードすれば、Cytoscapeで作った可視化をそのままウェブアプリケーションとして共有できるという機能です。要するに、既存のCytoscape.js向けJSONシリアライザの出力を一つのzipファイルにまとめて、更にその中にCytoscape.js、AngularJSなどを使ったJSコードとCSS、HTMLをまとめて書き出す機能です。解凍してそのディレクトリに入り、

python -m SimpleHTTPServer 8000

とでもタイプすれば、そのままSPAとしてCytoscape側で作業していた結果をブラウザで再現できます。

もちろん、レンダリングの詳細部分でCytoscapeとCytoscape.jsは異なる部分もあるのでまだ100%の再現性とは行かないですが、これは今後も順次アップデートしていき、再現性をあげます。Webアプリケーションとの連携機能はまだまだ今後増えると思いますが、今の段階でも、Cytoscapeでスケッチしたグラフ可視化をWebアプリケーションで再利用する道は用意されています。


おわりに

これは様々な可視化が可能なCytoscapeの機能のほんの一部です。また機会があったら書いてみようと思うのですが、現在、CytoscapeをREST API経由で操作できるようにするモジュールも開発中で、これが完成すれば、日常的にIPython NotebookやRStudioを利用されている方が、それらのコマンドラインから離れることなく可視化を作成できるようになると思います。

また、可視化一般の知識は別の連載にまとめましたので、こちらも合わせて読んでいただくことにより、理論と実践の関係(とギャップ)を理解していただけると思います:

今後もできるだけ日本語での情報提供を続けたいと思いますが、最新の情報はどうしても英語になってしまいますので、ご興味のある方はぜひ我々の公式ツイッターアカウントや、メーリングリストをチェックしてみてください:

また簡単な質問なら、私に日本語でTweetしてもらっても構いません。皆様が様々なプロジェクトでCytoscapeを活用してくだされば幸いです。

Keiichiro Ono

keiono
アメリカの研究機関で、生命科学系の研究に使用されるソフトウェアを開発しております。主な分野はデータの統合と可視化です。
http://keiono.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away