Jaalでグラフをインタラクティブにイジる

IT

グラフデータをApache AGEでPostgreSQLに格納したら、それをビジュアライズしたいのが普通なので、Jaalを使ってインタラクティブにイジれるグラフにしてみた。

#!/usr/bin/env python3.11

# builtin modules
import json
import os
import sys

cur_python = f"python{sys.version_info[0]}.{sys.version_info[1]}"

# third party modules
try:
    import pandas as pd
except ModuleNotFoundError:
    os.system(f'{cur_python} -m pip install pandas')
    import pandas as pd

try:
    import psycopg as pg
    from psycopg.rows import dict_row, namedtuple_row
except ModuleNotFoundError:
    os.system(f'{cur_python} -m pip install psycopg')
    import psycopg as pg
    from psycopg.rows import dict_row, namedtuple_row

try:
    from jaal import Jaal
except ModuleNotFoundError:
    os.system(f'{cur_python} -m pip install jaal')
    from jaal import Jaal

def main() -> None:
    # load data
    try:
        with pg.connect(
            host="localhost",
            port=5455,
            dbname="postgres",
            user=os.environ.get('USER'),
            password="passw0rd",
            options="-c search_path=ag_catalog,'$user',public"
        ) as con:
            with con.cursor(row_factory=namedtuple_row) as cur:
                cur.execute('''SELECT *
                    FROM cypher('routes', $$
                    MATCH p = (a:airport)-[r:route]->(b:airport)
                    WHERE r.airline = "JL"
                    RETURN relationships(p), a, b
                    $$) as (r agtype, a agtype, b agtype)''')
                data = cur.fetchall()
                edges = []
                for d in data:
                    route = json.loads(d.r[1:-len("::edge")-1])
                    ap_a = json.loads(d.a[:-len("::vertex")])
                    ap_b = json.loads(d.b[:-len("::vertex")])
                    edges.append({"from":ap_a["properties"]["code"], "to":ap_b["properties"]["code"], "title":route["properties"]["airline"]})
                e_df = pd.DataFrame(edges)
    except pg.OperationalError as e:
            print(e)
            sys.exit("Failed to connect to the database.")
    aggreated = e_df.groupby(["from", "to"], as_index=False).agg({"title": lambda x: ",".join(x)})
    Jaal(aggreated).plot(vis_opts={"height":"1600"})

if __name__ == "__main__":
    main()