LoginSignup
2
3

More than 1 year has passed since last update.

Pythonプログラミング:Qiita記事のタグからNetworkX+Plotlyを使ってインタラクティブなグラフを描画してみた

Posted at

はじめに

先日、公開されましたね。ガートナーさんの先進テクノロジのハイプ・サイクル(2022年版)12
英日それぞれで関連記事が出始めているので、私もちょこちょこWeb記事を拝読している今日この頃。。。

さて、Web記事を眺めていると、コーザルAI(Causal AI)もキーワードとしては登場しており、そこから連想して過去の投稿を思い出しました。

当時は可視化することが目的で、満足していました。
が、最近のQiita記事の動向を把握するための一環として、違った可視化の方法を試してみようと思い至りました。

というわけで、NetworkX3を使った可視化で面白い有志の投稿を見つけたので、試してみました。
結果的には、大満足。ネットワークグラフが、、、Plotly4でいとも簡単にきれいな仕上がりになるものかと感動しました。

本稿で紹介すること

  • Plotlyを使ったネットワークグラフの描画

本稿で紹介しないこと

  • ガートナーさん公開のハイプ・サイクルの内容

Plotlyを使ったネットワークグラフの描画

以下、2つの投稿を参考にさせていただきました。

掲載されたCodeのうち、build_interactive_network関数がPlotlyを使って描画する部分と理解しました。
こちらを、試しました。

環境の準備

参考、GitHubのCodeに記載の動作環境を目標に、筆者の環境は以下の仕上がりになりました。
VirtualBox上のGuestOSとして、Ubuntuを準備しました。(いつものように、Vagrantから起動)

【動作環境】

  • Ubuntu 20.04.4 LTS
  • Python 3.8.10
  • Node.js 18.7.0
  • MeCab 0.996
  • Graphviz 2.43.0

筆者の環境は、参考に比べてPythonとNode.jsのVer.が上がっています。

以下、Jupyter関係のコンポーネント群のVer情報です。

$ jupyter --version
Selected Jupyter core packages...
IPython          : 8.4.0
ipykernel        : 6.15.1
ipywidgets       : 8.0.1
jupyter_client   : 7.3.4
jupyter_core     : 4.11.1
jupyter_server   : 1.18.1
jupyterlab       : 3.4.5
nbclient         : 0.6.6
nbconvert        : 6.5.3
nbformat         : 5.4.0
notebook         : 6.4.12
qtconsole        : 5.3.1
traitlets        : 5.3.0

あと、Qiita記事のタグを描画するのですが、当然日本語を含むので、フォントもインストールしました。

フォントのインストール
$ sudo apt install -y fonts-ipafont
$ sudo apt install -y fonts-ipaexfont
$ fc-cache -fv
$ fc-list | grep -i ipa

環境Setupのコマンド群も、末尾記載のGitHubで公開しました。

まずは、現状把握

筆者は、自宅PCからプロバイダ網抜けてインターネット接続ありの環境で実行しています。
企業(Proxy環境)の方はお気を付けくださいませ。

過去の投稿を懐かしみながら、同じコードを一旦流し切りました。
すると、こんな結果が得られました。
オブジェクトが重なっており、詳細を確認できない状態。。。ちょっと惜しい。

image.png

いざ、Plotlyで描画

参考にしたのは、以下のPlotlyを使ってインタラクティブなグラフを描画するCode部分。

def build_interactive_network(G, pos, node_sizes, node_colors):
     
    # edgeデータの作成
    edge_x = []
    edge_y = []
    for edge in G.edges():
        x0, y0 = pos[edge[0]]
        x1, y1 = pos[edge[1]]
        edge_x.append(x0)
        edge_x.append(x1)
        edge_x.append(None)
        edge_y.append(y0)
        edge_y.append(y1)
        edge_y.append(None)
 
    edge_trace = go.Scatter(
        x=edge_x, y=edge_y,
        line=dict(width=0.5, color='#888'),
        hoverinfo='none',
        mode='lines')
 
    # nodeデータの作成
    node_x = []
    node_y = []
    for node in G.nodes():
        x, y = pos[node]
        node_x.append(x)
        node_y.append(y)
 
    # nodeの色、サイズ、マウスオーバーしたときに表示するテキストの設定
    node_trace = go.Scatter(
        x=node_x,
        y=node_y,
        text=list(G.nodes()),
        hovertext=node_sizes,
        textposition='top center',
        mode='markers+text',
        hoverinfo='text',
        marker=dict(
            showscale=True,
            colorscale='Portland',
            reversescale=False,
            color=node_colors,
            size=node_sizes,
            colorbar=dict(
                thickness=15,
                title='Page Ranking',
            ),
            line_width=2))
    
    data = [edge_trace, node_trace]

    # レイアウトの設定
    layout=go.Layout(
                paper_bgcolor='rgba(0,0,0,0)',
                plot_bgcolor='rgba(0,0,0,0)',
                showlegend=False,
                hovermode='closest',
                margin=dict(b=10, l=5, r=5, t=10),
                font=dict(size=10),
                xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
                yaxis = dict(showgrid = False, zeroline = False, showticklabels = False))

    fig = go.Figure(data=data, layout=layout)
    fig.show()

上記関数を呼び出すCode部分がこちら。同じく参考のGitHubだと、LL.206~218に相当。
第三引数、Nodeの大きさのところを調整した程度でした。

# nodeの配置方法の指定
seed = 0
np.random.seed(seed)
pos = nx_agraph.graphviz_layout(
    G,
    prog='neato',
    args='-Goverlap="scalexy" -Gsep="+6" -Gnodesep=0.8 -Gsplines="polyline" -GpackMode="graph" -Gstart={}'.format(seed))

# nodeの色をページランクアルゴリズムによる重要度により変える
pr = nx.pagerank(G)

# インタラクティブな共起ネットワークの可視化
build_interactive_network(G, pos, list([1000*v for v in pr.values()]), list(pr.values()))

実行すると、以下のようになりました。

  • NodeのPageRank値が大きいと、配色が赤系になる。
  • Node(を表す単語)の登場回数が多いと、サイズが大きくなる。

image.png

Plotlyの描画で何が魅力的かというと、拡大縮小が自由自在なのです。
マウスで範囲選択をすると、その範囲が拡大されより細かくEdgeのつながりを見ることができました。
例えば、JavaScriptやPythonを含むように範囲選択をした結果が以下。

image.png

もっとビジーなグラフになっても、Plotlyなら無問題。範囲選択して拡大するだけ(ダブルクリックで全体俯瞰の初期状態へ戻る)。

ちなみに、描画したグラフをHTML形式で保管するには、以下のCodeを実行するだけです。
WebブラウザでHTMLファイルを開けば、Jupyter上で表示したグラフを見ることができます。

fig.write_html("qiita.html") # オフライン利用のためにHTML出力

Notebook(Pythonコード)

GitHubで公開しました。

まとめ

NetworkX+Plotlyでインタラクティブかつ美しいグラフ描画を試しました。
PlotlyならHTML形式で出力もできるので、ちょっとWebブラウザでDEMOしたいときなんかも非常に重宝するかと思いました。

  1. Gartner Hype Cycle for Cloud Platform Services 2022 Positions Two Technologies to Reach the Plateau of Productivity in Less Than Two Years | https://www.gartner.com/en/newsroom/press-releases/2022-08-04-cloud-platform-hc-press-release

  2. Gartner、「先進テクノロジのハイプ・サイクル:2022年」を発表 | https://www.gartner.co.jp/ja/newsroom/press-releases/pr-20220816

  3. NetworkX | https://networkx.org/

  4. Plotly Python Graphing Library | https://plotly.com/python/

2
3
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
3