2
2

More than 1 year has passed since last update.

networkxで生成したネットワークをCytoscapeで可視化する

Posted at

モチベーション

ネットワークを可視化するためにnetworkxを使っていたのですが、ノード数が多くなるとnetworkxで自動計算されるレイアウトだと見やすさに限界が出ます(ノードが重なり合ってつぶれてしまう)。そこで、networkxで生成したグラフを流用してより柔軟な可視化が可能なCytoscapeを用いた可視化を試してみます。

手順

ゴールは相関係数をもとにした各要素間のネットワークの可視化です。相関係数の計算とnetworkxでの可視化までは以下を参照しています。

改めて手順を確認すると

  1. 相関係数行列を作成する

      # generate a sample weight matrix
      n1 = 10
      n2 = 20
      n = n1 + n2
      np.random.seed(12345)
      X  = np.random.randn(n, 20)
      v = 0.6 * X[0]
      X[:n1] += v
      X[n1:] -= v
      W = np.corrcoef(X)
    
  2. networkxを用いてグラフを作成する

    G = nx.Graph()
    # Wは相関係数行列
    for i, j in zip(*np.triu_indices_from(W, 1)):
      G.add_edge(i, j, weight=W[i,j])
    
  3. networkxでCytoscapeが対応している形式のjsonを生成する

    • 吐き出されるjsonをCytoscapeで読んでも解釈されなかった
  4. (上記の変換がうまくできなかったため)jsonのデータをもとにcsvに変換する

    import pandas as pd
    
    # 空のDataFrameを用意する
    out = pd.DataFrame()
    for e in nx.cytoscape_data(G)["elements"]["edges"]:
        # "edges"の中に含まれるsource, target, weightの情報をDataFrameに追加する
        out = pd.concat(
            [
                out,
                pd.DataFrame(
                    {
                        "from": [e["data"]["source"]],
                        "to": [e["data"]["target"]],
                        "weight": [e["data"]["weight"]],
                    }
                )
            ]
        )
    out.reset_index(inplace=True, drop=True) # indexの振り直し
    out.to_csv("network.csv")
    
  5. Cytoscapeでcsvを読み込む

    • networkのペインにcsvをドラッグすればok
    • source/destinationのカラムを指定してネットワーク図を生成する
    • 緑の○がsource/赤の○はdestination(今回はどっちでもいいはず)
      image.png
    • 初期配置だとこう
      image.png
    • レイアウトを選ぶと整列する(circular layout)
      image.png
      image.png
  6. 重みによってエッジの色を変更する

    • CytoscapeのStyleペインでstroke colorを選択
    • weightに対応して色を付けたいので、columnにweightを選択する
      image.png

1, 2の手順は参照先で説明されているのでコード以外は割愛します

コード全体

import numpy as np
import pandas as pd
import networkx as nx

n1 = 10
n2 = 20
n = n1 + n2
np.random.seed(12345)
X = np.random.randn(n, 20)
v = 0.6 * X[0]
X[:n1] += v
X[n1:] -= v
W = np.corrcoef(X)

G = nx.Graph()

for i, j in zip(*np.triu_indices_from(W, 1)):
    G.add_edge(i, j, weight=W[i, j])
# ここまで流用

# ここからCytoscape用出力
out = pd.DataFrame()
for e in nx.cytoscape_data(G)["elements"]["edges"]:
    out = pd.concat(
         [
            out,
            pd.DataFrame(
                {
                    "from": [e["data"]["source"]],
                    "to": [e["data"]["target"]],
                    "weight": [e["data"]["weight"]],
                }
            )
        ]
     )
out.reset_index(inplace=True, drop=True)
out.to_csv("network.csv")

tips

エッジの足切り

for i, j in zip(*np.triu_indices_from(W, 1)):
    # 相関係数の閾値をもとに足切りできる
    if abs(weight[i, j]) > 0.8:
        G.add_edge(i, j, weight=W[i, j])

おわりに

ノードはnetworkxを用いた場合に比べて個々が目視で分かるようになりました。
一方でエッジが多すぎて埋もれるものも出てしまいました。
理想はweightベースにエッジの長さがコントロールできれば良いのですが、一旦はノードのつぶれを改善できたので良いことにします。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2