ソーシャルグラフの作成を簡単に行うことのできるNeo4jというツールを試してみたのでメモです.
ソーシャルグラフとは
この記事のトップの画像のようなものです.
あるデータ1とデータ2の関係性を表す際に使います.アニメやドラマのHPとかで良くある関係図みたいなものを想像すると分かりやすいかもしれません.もちろん人間の関係だけでなく,「サイトAはサイトBにリンクしている」などを可視化するのにも便利です.
Neo4jとは
Neo4jはソーシャルグラフを簡単に作る事のできるJAVAで作られたツールです.Neo4jをインストールし,起動することでNeo4jのサーバが立ち上がり,そこにアクセスすることでWebUI上で操作することが可能です.Cypher QLと呼ばれるSQLライクなクエリランゲージを操作することで,データベースにノードやその関係を示したデータを追加したり,グラフの表示したりグラフを削除することができます.
環境
環境は以下とします.
- OS : Windows 8.1
- Client : Python 2.7
Neo4jのグラフデータを操作するにはCypher QLをWebUIで入力する以外に,プログラムなどで外部からCypherのクエリを送って操作する方法もあります.今回はPythonのneo4j-rest-clientというライブラリを使ってみます.
インストール
こちらのサイトからインストーラをダウンロードします.ここでは個人利用版をダウンロードしていますが,商用版もあるようです.
インストーラをダウンロードしたら実行し,手順に沿っていけばインストールが完了します.
ちなみにMac等はbrewで入れられたリ,あるいはバイナリのtarがあるのでそれをダウンロードすればいいみたいです.
使い方
Neo4jの起動
下記のようなウィンドウがでるので,Startを押すとサーバが起動します.デフォは7474ポートが使用されます.Stopすればサーバが止まります.
サーバ起動状態でブラウザでhttp://localhost:7474/にアクセスすればWebUIを使うことができます.
確か初回起動時にログインが必要で,デフォルトのID/PASSはneo4j/neo4jだった気がします.それでログインするとパスワードの変更を求められて,任意のパスワードに変更できます.
クエリの例
Pythonで使うクエリの例です.ノードというのはグラフで言う丸っこいやつです.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# coding:utf-8 from neo4jrestclient.client import GraphDatabase # urlを指定し,ローカルに立ててるNeo4jと接続 # username,passwordは自分が設定したものに読み替える url = "http://username:password@localhost:7474/db/data/" gdb = GraphDatabase(url) gdb.query("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r", data_contents=True) # ノードを追加 spica73 = gdb.nodes.create(name="73spica", age="23") # 第一引数はノードの名前.第二引数は好きなデータを入れられるみたい. chiaki = gdb.nodes.create(name="七海千秋") # ラベルを追加 spica73.labels.add("Me") # ラベル追加.同じラベルは同じ色みたいなことができる. chiaki.labels.add("wife") # 七海千秋は俺の嫁 # 関係を追加 spica73.relationships.create("Love",chiaki) # 73spicaは七海千秋が好き |
これを実行してみると,内部で各処理が行われ見た目上は特に何もなく終わります.
WebUIの方に移って,クエリ入力欄に以下のように打ち込むことでグラフを表示することができます.
1 2 |
# 全てのノードを返す MATCH (n)-[r]-(m) RETURN n, r, m |
すると以下のような片思いのグラフが表示されます.
悲しい.
簡単なプログラム
取りあえず自分に関連する色々を表示するプログラムを作りました.
- neo4j.py -> 適当にファイル読み込んでクエリ投げる
- node.csv -> ノードになり得るキーワードを読み込みnodeを作る
- labels.csv -> 各ノードのラベルが1行にlabel,nodeで書いてある.よくよく考えたらnode.csvと一緒でもよかった.
- rel.csv -> 各ノードの関係を1行につきfrom,rel,toで書いとくと読み込んで表示できる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# coding:utf-8 from neo4jrestclient.client import GraphDatabase def main(): # Prepare # username,passwordは自分が設定したものに読み替える url = "http://username:password@localhost:7474/db/data/" gdb = GraphDatabase(url) label_csv = "labels.csv" rel_csv = "rel.csv" node_csv = "node.csv" # Delete Graph gdb.query("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r", data_contents=True) # Main Nodes node_dict ={"spica":gdb.nodes.create(name="73spica", age=23),"hobby":gdb.nodes.create(name="趣味"),"interest":gdb.nodes.create(name="興味"),"chara":gdb.nodes.create(name="特徴"),"food":gdb.nodes.create(name="食",),"others":gdb.nodes.create(name="他"),"school":gdb.nodes.create(name="学校"),"color":gdb.nodes.create(name="色"),"expert":gdb.nodes.create(name="専門"),"sports":gdb.nodes.create(name="スポーツ")} # Creating Nodes for line in open(node_csv,"r"): key = line.strip() node_dict[key] = gdb.nodes.create(name=key) # Adding Label for line in open(label_csv,"r"): label,node = line.strip().split(",") node_dict[node].labels.add(label) # Creating Relations for line in open(rel_csv,"r"): fr,rel,to = line.strip().split(",") node_dict[fr].relationships.create(rel,node_dict[to]) if __name__ == '__main__': print "Start." main() print "Finish." |
追記) 上記プログラム,has_keyなどでキーのチェックした方が良いですね.エラーで止まります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# node.csv 七海千秋 ダンガンロンパ .... # labels.csv Hobby,ダンガンロンパ Hobby,七海千秋 ... # rel.csv spica,Rel,hobby hobby,Rel,ダンガンロンパ .... |
今回はただただ繋がりを示したかっただけなので関係を全てRelとしてますが,ソーシャルグラフであればLike,とかinterestとか分けた方が良いと思われます.
デモ
こんな感じ.
こんな感じで簡単にソーシャルグラフを作ることができます(クソ情報しかグラフ化してないけどなんかセンシティブな情報がグラフ化されてないか怖い).
しかもノードをつかんでブルンブルンして遊べます自由に位置を変更したりすることもできます.楽しい.
余談
「自分に関するキーワードをたくさん挙げてね,書式は問わないよ」みたいなことを某所で言われたときに使ってみようかと思い立って使いました.Neo4jを知ったきっかけは研究室の先輩がWebトラッキングの研究でデータを可視化する際に使ったとゼミで言っていたからです.
最近可視化にちょっとはまってたりします.