見出し画像

Microsoft365のデータを使ってソーシャルグラフを書いてみた

はじめに

SHIFT コーポレートプラットフォーム部 米沢です。 本日はMicrosoft365のデータを使ってソーシャルグラフを書いてみたというテーマで綴ろうと思います。

想定読者

  • Microsoft365のデータの利活用を考えている方

  • ソーシャルグラフに興味がある方

  • d3を使って大規模なグラフを描画しようと考えている方

きっかけ

人事部から従業員同士のつながりをとれないかというリクエストを受けたのがきっかけです

なんかぱっと、人と人のつながりが見えて、関係性が強いところ関係性が弱いところ を分析できるプラットフォームがあればいいかなーということで、まず作ってみました。経営幹部や人事メンバに共有して、こういう活用できそうだよねーってのもイメージできたので、今後それに向けてビルドアップしていきます。今日はそのはじめの一歩を綴ります。

お品書き

今回ご用意したものは以下のものです。

ユーザの関連性を取得するには、people APIで取得します。その中のスコア(relevanceScore)を利用します 詳しくはこちら

グラフDBといえば、Neo4jが有名どころですが、今回はMemgraphを採用しました。InMemoryでやりたかったので

ベレの法則に基づくシミレーション機能がインプリされたd3ライブラリ

作ったもの

中心に関連性が強い人、外縁に関連性が薄い人が並ぶようにしたネットワークグラフができました。👏

マウスホバーするとその関連線が見えるような仕組みです。まだ作りたてホヤホヤですが、ここから従業員のコミュニケーション密度とかを評価して人事施策に繋がるような機能を追加していけたらいいなーという話は内部ではしています。

d3-forceは、実質初期描画状態を構築するためだけに利用しています。

実装する中、いくつかポイントがありました。

■d3-forceの制約条件 (構築にあたり、この記事を参考にしました)

今回、真ん中に関連度が強いひとを極力寄せたかったので、四苦八苦した結果以下の制約の組合せを採用しました。大規模なデータを取り扱い上において、相性が良かったです。

  • link   - リレーションによる強さを表現 / バネの弾性に相当
    採用 => 関連性が強いほど惹かれ合うように

  • collide   - ノード間の反発力 / 1ノードのテリトリを定義、重なりの排除が可能
    採用 =>ノードが重なりすぎないように

  • charge  - ノード間の引力 / 万有引力に相当
    不採用 => linkの影響を重視したため

  • center   - 場の引力の中心 / 指定座標の中心に整列
    不採用 => linkとのバランスがとれなかったため

  • x , y       - 場の引力の中心 /  x 軸・y軸上に整列
    不採用 => 中心に寄せたかったため

  • r         - 場の引力の中心 /   centerと同様だが、半径rの円の外周に整列
    不採用 => 中心に寄せたかったため

実は私、学生時代制御工学を勉強していてシミュレーションの経験や、過去の案件でもGUROBIとかLocalSolverとか数理計算の経験はありました。馴染みはありましたが、やはり各制約条件間のバランスも難しく、最終的には中心に一番関連性が強いノードを置き、最低限の制約を加えることで、上の図にたどり着きました。
#数値計算の現実世界での適用において、初期値は最大の制約条件と個人的
 には考えています。いいすぎかも。

■ノード/リンクが多い場合は、CANVASで描画を

今回使ったデータはノード数/リンク数もそれなりの数(5,000/50,000)でした。SVGでは描画が激重だったので、CANVASを利用しました。SVGもCANVASもd3上では、描画手法の違いで、tickというイベント(シミュレーション施行毎に呼び出されるイベント)を受けて、描画を行います。d3にノード情報を投入するとtick毎に各ノードの位置情報がシミュレーション結果で更新されるので、それに基づいて描画します。
※👇にCAVAS描画時に例を載せておきます。ノード毎に円を描画

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d")
var ndata = [・・・・・・・・]
var radius = 5;
var simulation = d3.forceSimulation();
simulation.nodes(ndata).on('tick',function(){
     ndata.forEach(function(node){
       context.beginPath();
       context.moveTo( node.x + radius, node.y );
       context.arc(node.x, node.y, radius, 0, 2 * Math.PI);
       context.fill();
       context.stroke();
     })
});

#後日談ですが、リンクの描画を止めたら軽快に動くようになりました。 
 SVGでも描画できたかもとはおもっています。

■Cypherクエリ(グラフDB)とSQLの対比

Cypherクエリは、グラフデータを扱うための専用クエリです。SQLと集合を扱う言語としては一緒ですが、データの関連性の検索に特化したクエリです。例としてSQLとCypherクエリの違いを示します。

例:UserとDepartmentというデータがあり、idでリレーションがある

MATCH分がSQLでいうところのJOIN句で、 (ノード) と  [リレーション] を使った結合状態を示します。WHERE句は同様です。RETURN句がSELECTと同じ内容です。MATCH句でノードとリレーションの関係性を階層検索もできるため、階層クエリ等をシンプルに高速に実現できます。


終わりに

今回、Microsoft365のデータを活用してソーシャルグラフを書いてみました。もし同じことをやってみたいと思う方は参考にしていただけたらとおもいます。

最後に、コーポレートプラットフォーム部ではメンバを絶賛募集中です。ご興味ありましたカジュアル面談も可能ですので、ぜひぜひ門を叩いてください。

__________________________________

執筆者プロフィール:米沢 毅
独立系ソフトウェアハウスでSEを5年、ITコンサル会社でアーキテクトを8年経験。その後SHIFTに2014にJoin。テスト実行管理ツール CATの開発マネージャを経て、2018年に情報システム部に異動、部長に着任。情報システム並びにセキュリティを管掌。未だに開発が好きで手を動かしています。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/