dogrunjp
12/18/2016 - 2:29 AM

OracleのParallel Graph Analytics (PGX)を使って出力したEDEG_LIST形式のグラフデータをCytoscape.jsで描画するために、JSON変換するPythonスクリプトです。PGXにはtoString()関数がありJSONへの出力はコマンド

OracleのParallel Graph Analytics (PGX)を使って出力したEDEG_LIST形式のグラフデータをCytoscape.jsで描画するために、JSON変換するPythonスクリプトです。PGXにはtoString()関数がありJSONへの出力はコマンドから実行できるはずなのですが、パラメータ等の設定が不明だったためオレオレconverterを書いてみました。

PGXでエッジリストを読み込みフィルターしたグラフデータを出力するサンプルスクリプトと、このデータをブラウザで見るためのHTML&JSも置いておきます。

import json
import re

def get_graph_data():
    with open("./data/test_subgraph.txt", "r") as infile:
        data = [line.strip() for line in infile.readlines()]

    edge_list = []
    pat = re.compile('\"')
    for row in data:
        if re.match(".+\d$", row) and not row.startswith("#"):
            row = re.sub(pat, "", row)
            edge_list.append(row.split("\t"))


    node_list = []
    for e in edge_list:
        node_list.append(e[0])
        node_list.append(e[1])

    node_list = list(set(node_list))
    node_map = {v: str(k) for k, v in enumerate(node_list)}
    nodes = [{"data": {"id": str(k),  "name": v}} for k, v in enumerate(node_list)]
    edges = [{"data": {"source": node_map[row[0]], "target": node_map[row[1]]}} for row in edge_list]

    data = dict()
    data["elements"] = {}
    data["elements"]["nodes"] = nodes
    data["elements"]["edges"] = edges

    with open("./data/test_subgraph.json", "w") as outfile:
        json.dump(data, outfile)


get_graph_data()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Juice=Juice #nowplaying similar user graph</title>
    <script src="./js/jquery.min.js"></script>
    <script src="./js/cola.min.js"></script>
    <script src="./js/cytoscape.min.js"></script>
    <script src="./js/d3.min.js"></script>
    <script src="./js/cytoscape-cola.js"></script>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div#header{
            margin: 0;
            padding: 0;
            height:28px;
            width: 100%;
            border-bottom: solid 1px #888;
            font-family: sans-serif;
        }
        div#header .header_title{
            float: left;
        }
        div#header h1{
            font-size: 12px;
            margin: 6px 0 4px 12px;
            padding: 0;

            color: #444;

        }

        div#header p{
            margin: 6px 30px 0 0;
            font-size: 12px;
            color: #444444;
        }
        div#cy{
            width: 800px;
            height: 800px;

        }
        div.contents{
            width: 800px;
            margin: auto;
        }

    </style>
</head>
<body>
<div id="header">
    <div class="header_title">
        <h1>#nowplayingしたアーティストの類似度を元に集計したTWアカウントのグラフ</h1>
    </div>
</div>
<div class="contents">
    <div id="cy"></div>
</div>

<script>
    $(function() {
        show_graph();
        function show_graph(){
            $.when(
                $.get("./data/test_subgraph.json")
            ).done(function(data1){
                var d1 = data1["elements"];
                var cy = cytoscape({
                    container: document.getElementById('cy'),

                    style: cytoscape.stylesheet()
                            .selector('node')
                                .css({
                                    'content': 'data(name)',
                                    'color': '#333',
                                    'background-color': '#ED6137',
                                    'width': 10,
                                    'height': 10,
                                    'font-size': 8,
                                    'opacity': 0.95
                                })
                            .selector('edge')
                                .css({
                                    'target-arrow-shape': 'triangle',
                                    'line-color': '#5DAED9',
                                    'width': 1,
                                    'opacity': 0.5
                                })
                            .selector(':selected')
                                .css({
                                'line-color': 'black',
                                    'background-color': '#F2E533'
                            }),
                    elements: d1
                });

                cy.layout({
                    name: 'cola'
                });

            });

        }
    });

</script>
</body>
</html>

PGXコンソールでedgeのパラメータをフィルターしたsubgraphを出力するサンプルスクリプト

subgraph作成

tsvデータを読み込む用の設定 : sample_for_pgx.tsv.json

{
  "uri": "sample_for_pgx.tsv"
, "format": "edge_list"
, "node_id_type": "string"
, "vertex_props":[
    {"name":"name", "type":"string"}
  ]
, "edge_props":[
    {"name":"score", "type":"double"}
  ]
, "separator": "\t"
}

エッジデータの読み込み

pgx> G = session.readGraphWithProperties("./sample_for_pgx.tsv.json")

ノードの数を表示

pgx> G.queryPgql("SELECT x.id() WHERE (x)").getNumResults()

エッジの数を表示

pgx> G.queryPgql("SELECT x.id(), y.id() WHERE (x)-->(y)").getNumResults()

edgeのプロパティでフィルターしたsubgraphを作成

pgx> subgraph = G.filter(new EdgeFilter("edge.score > 0.05"))

subgraphのエッジの数を表示

pgx> subgraph.queryPgql("SELECT x.id(), y.id() WHERE (x)-->(y)").getNumResults()

EDGE_LIST形式のデータを保存

pgx> config = subgraph.store(Format.EDGE_LIST, "./sample.elist")

本来はJSON変換したグラフデータを保存するスクリプト

pgx> new File("./sample.json") << config.toString()