1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

StreamlitAdvent Calendar 2024

Day 25

Streamlit×Cytoscape.jsの話

Posted at

Streamlit の Component とは

Streamlit には Component と呼ばれる
「インタラクティブなウィジェットや、サードパーティの JavaScript ライブラリなどを簡単に統合するための仕組み」があります。

Component のギャラリーは https://streamlit.io/components にあります。

その Component の中でもっとも Star がついているのは Pygwalker (pandas の DataFrame を Tableau のような操作感でインタラクティブに探索・可視化することを実現してくれるもの)

ですが、この記事では Cytoscape.js というネットワーク可視化用 JavaScript ライブラリを統合している Streamlit Component についてとりとめのない話をします。

Cytoscape.js を用いる Streamlit Component

Cytoscape.js とは?なんですが
「百聞は一見にしかず」で https://js.cytoscape.org/ にずらっとならんでいる Demos のような可視化を実現してくれる JavaScript ライブラリです。

image.png

この Cytoscape.js を「Streamlit の中で (js ではなく) python を書くことで活用したい」と思う人は、私以外にもいるわけで、
https://streamlit.io/components?category=graphs
には すでに下記の 2 つの Streamlit Component があります。

何はともあれ vivien000 さんの st-cytoscape を試してみましょう。

st-cytoscape のインストールは下記の pip コマンドで行えます。

pip install st-cytoscape

st-cytoscape を試してみるための python script は下記です。
下記のコードを app.py という名前のファイルで保存してください。

import streamlit as st
from st_cytoscape import cytoscape

elements = [
    {"data": {"id": "X"}, "selected": True, "selectable": False},
    {"data": {"id": "Y"}},
    {"data": {"id": "Z"}},
    {"data": {"source": "X", "target": "Y", "id": "X➞Y"}},
    {"data": {"source": "Z", "target": "Y", "id": "Z➞Y"}},
    {"data": {"source": "Z", "target": "X", "id": "Z➞X"}},
]

stylesheet = [
    {"selector": "node", "style": {"label": "data(id)", "width": 20, "height": 20}},
    {
        "selector": "edge",
        "style": {
            "width": 3,
            "curve-style": "bezier",
            "target-arrow-shape": "triangle",
        },
    },
]

selected = cytoscape(elements, stylesheet, key="graph")

st.markdown("**Selected nodes**: %s" % (", ".join(selected["nodes"])))
st.markdown("**Selected edges**: %s" % (", ".join(selected["edges"])))

上記の app.py は、下記のように streamlit コマンドへの入力として使えます。

streamlit run app.py

その結果、下記の Streamlit アプリを見ることができます。
image.png

このネットワークグラフは、本記事の冒頭で述べた「インタラクティブなウィジェット」になっています。

試しに Y の丸 (以降はノードと呼びます)、Z のノード、そして X-Y-Z ノードをつなぐ矢印 (以降はエッジと呼びます) をクリックしてみましょう。

image.png

すると上記のようにノードやエッジが「選択されたこと」を示す赤色に変わり、下記コードに相当する出力がインタラクティブに更新されることがわかります。

st.markdown("**Selected nodes**: %s" % (", ".join(selected["nodes"])))
st.markdown("**Selected edges**: %s" % (", ".join(selected["edges"])))

selected のオブジェクトは dict で、 nodesedges という 2 つの key に、選択されたノードとエッジの id がリストの value が入っています。

東京の路線図データを st-cytoscape に入力してみよう

今度は先のお試しデータではなく、がっつりしたデータで st-cytoscape を使ってみましょう。

app.py を下記のように変えてください。

import streamlit as st
from st_cytoscape import cytoscape

# elements = [
#     {"data": {"id": "X"}, "selected": True, "selectable": False},
#     {"data": {"id": "Y"}},
#     {"data": {"id": "Z"}},
#     {"data": {"source": "X", "target": "Y", "id": "X➞Y"}},
#     {"data": {"source": "Z", "target": "Y", "id": "Z➞Y"}},
#     {"data": {"source": "Z", "target": "X", "id": "Z➞X"}},
# ]

import requests
import json

url = "https://raw.githubusercontent.com/cytoscape/cytoscape.js/refs/heads/master/documentation/demos/tokyo-railways/tokyo-railways.json"
response = requests.get(url)
data = json.loads(response.text)
elements = data['elements']['nodes'] + data['elements']['edges']

stylesheet = [
    {"selector": "node",
      "style": {"label": "data(station_name)", "width": 10, "height": 10}},
    # {
    #     "selector": "edge",
    #     "style": {
    #         "width": 3,
    #         "curve-style": "bezier",
    #         "target-arrow-shape": "triangle",
    #     },
    # },
]


selected = cytoscape(elements, stylesheet, width="100%", height="540px", layout={"name": "preset"}, key="graph")

print(selected)
st.markdown("**Selected nodes**: %s" % (", ".join(selected["nodes"])))
st.markdown("**Selected edges**: %s" % (", ".join(selected["edges"])))

すると下記のようなネットワークが streamlit 中に見えると思います。

image.png

ズームしてみると下記みたいな感じ。

image.png

おっこれなら何か面白いものができるかも?と思われたのではないでしょうか?

尻切れトンボですが、最後に新たなコードの肝だけ説明します。

selected = cytoscape(elements, stylesheet, width="100%", height="540px", layout={"name": "preset"}, key="graph")

この行の layout={"name": "preset"} が肝です。

このパラメーター設定によって

url = "https://raw.githubusercontent.com/cytoscape/cytoscape.js/refs/heads/master/documentation/demos/tokyo-railways/tokyo-railways.json"

の json 中の x と y の座標がネットワークのノードのレイアウトに使われます。

    }, {
      "data" : {
        "id" : "5572",
        "station_name" : "武蔵野台",
        "close_ymd" : "",
        "lon" : 139.51128899999998,
        "post" : "183-0011",
        "e_status" : 0,
        "SUID" : 5572,
        "station_g_cd" : 2400121,
        "add" : "府中市白糸台4-18-4",
        "line_cd" : 24001,
        "selected" : false,
        "open_ymd" : "",
        "name" : "2400121",
        "pref_name" : "東京都",
        "shared_name" : "2400121",
        "lat" : 35.664159000000005,
        "y" : -356641.59,
        "x" : 1395112.8899999997
      },

そんなわけで、東京の実際の路線図の駅配置が再現されるわけなんですね。

じゃあ 自分は streamlit と cytoscape.js を使って次に何しようかな?

ネットワーク可視化ってものは結構いろんな使い方ができます。

ChatGPT に 「streamlit と cytoscape.js を使った実用的なアプリケーションの例を複数挙げてください。」
と聞いてみると、みなさんの興味に合うアプリケーションが見つかるかもしれません。

ぜひ streamlit と cytoscape.js を組み合わせて、何かアプリケーションを作ってみてください!

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?