LoginSignup
4
1

More than 3 years have passed since last update.

実例で動かすグラフアルゴリズムとグラフデータベース、02_アルゴリズム編、PageRankで重要なアカウントを探す

Last updated at Posted at 2020-09-10

前編:
https://qiita.com/s_zh/items/3b183e258bcd6506e8cb

後編:
https://qiita.com/s_zh/items/75b129f8279e290fe705

Colabはこちらです。

politician_02_PageRank.png

カウントベースで小手調べ

まずナイーブに重要なアカウントはたくさんフォローされると考えて、よくフォローされているアカウントを調べてみます。

from neo4j import GraphDatabase
from tqdm.notebook import tqdm
import json

import pandas as pd
auth_path = './data/neo4j_graph/auth.json'
with open(auth_path, 'r') as f:
    auth = json.load(f)

# ローカルの場合は通常 uri: bolt(or neo4j)://localhost:7687, user: neo4j, pd: 設定したもの
# サンドボックスの場合は作成画面から接続情報が見られます
uri = 'neo4j://localhost:7687'
driver = GraphDatabase.driver(uri=uri, auth=(auth['user'], auth['pd']))
# Sandboxの場合はこんな感じ
# uri = 'bolt://54.175.38.249:35275'
# driver = GraphDatabase.driver(uri=uri, auth=('neo4j', 'spray-missile-sizing'))

クエリ結果の数が多くなると表示の問題でNeo4j Browserが固まりやすくなりますが、プログラムなら問題なく扱えることがあります。

with driver.session() as session:
    res = session.run('''
    MATCH (u:User)<-[r:FOLLOW]-(u2:User)--(g:Group)
    RETURN u.userId as id, u.screenName as screen_name, u.name, count(DISTINCT r) as count
    ORDER BY count DESC
    ''')

res = list(res)
res_df = pd.DataFrame.from_dict([r.data() for r in res])
print(res_df.shape)
res_df.head(10)
(19944, 4)
id screen_name u.name count
0 204245399 None None 139
1 104388107 konotarogomame 河野太郎 136
2 468122115 AbeShinzo 安倍晋三 129
3 245677083 None None 123
4 265205959 None None 118
5 89631948 ecoyuri 小池百合子 110
6 96684891 kharaguchi 原口 一博 110
7 124415804 None None 109
8 94482602 SekoHiroshige 世耕弘成 Hiroshige SEKO 108
9 169480493 None None 108

政治家アカウント以外のアカウントはIDしか情報がないのでscreen_nameやnameがnullとなっています。まず政治家について見てみます。政治家によくフォローされる政治家アカウントランキングです。

res_df[res_df.screen_name.notnull()].head(10)
id screen_name u.name count
1 104388107 konotarogomame 河野太郎 136
2 468122115 AbeShinzo 安倍晋三 129
5 89631948 ecoyuri 小池百合子 110
6 96684891 kharaguchi 原口 一博 110
8 94482602 SekoHiroshige 世耕弘成 Hiroshige SEKO 108
10 58359180 jimin_koho 自民党広報 107
11 94050482 ichita_y 山本一太 105
12 112551613 SatoMasahisa 佐藤正久 104
16 106595422 TAIRAMASAAKI 平将明 97
17 80985167 renho_sha 蓮 舫 ・ 立 憲 民 主 党 ( り っ け ん ) 97

首位3名は順当な感じがしますね、原口さんは最近あまりニュースで聞かない印象ですが、元総務大臣ということで、(すくなくともTwitter上では)影響力がある、かもしれません。

次に政治家以外のアカウントについてですが、こちらは現在idしかなくて、idはtwitterがユーザアカウントに割り当てるもので、APIを使えば詳細を調べられますが、IDからユーザ情報、あるいはユーザ情報からIDを調べるツールもあります(https://idtwi.com/)。ここでは上位ユーザについての情報を追加収集しました。[こちら](https://github.com/lightondust/topics_by_jupyter_notebook/raw/master/data/neo4j_graph/politicians_0909_additional.json)からダウンロードできます。

additional_data_path = './data/neo4j_graph/politicians_0909_additional.json'

with open(additional_data_path, 'r') as f:
    additional_user_data = json.load(f)
for idx, item in res_df[res_df['screen_name'].isnull()].head(20).iterrows():
    u_id = item['id']
    count = item['count']
    for u in additional_user_data:
        if u['id'] == u_id:
            user = u
    print('{}, {}, {}, {}'.format(u_id, user['screen_name'], user['name'], count))
204245399, nhk_news, NHKニュース, 139
245677083, hashimoto_lo, 橋下徹, 123
265205959, Kantei_Saigai, 首相官邸(災害・危機管理情報), 118
124415804, namatahara, 田原総一朗, 109
169480493, nikkei, 日本経済新聞 電子版, 108
412940784, kantei, 首相官邸, 103
99008565, masason, 孫正義, 100
109488235, Yomiuri_Online, 読売新聞オンライン, 97
180585090, MHLWitter, 厚生労働省, 94
42816371, asahi, 朝日新聞(asahi shimbun), 93
25073877, realDonaldTrump, Donald J. Trump, 89
92686016, kenichiromogi, 茂木健一郎, 88
297254593, kogashigeaki, 古賀茂明@フォーラム4, 87
46282367, mainichijpnews, 毎日新聞ニュース, 86
94701166, YoichiTakahashi, 高橋洋一(嘉悦大), 85
148961902, HeizoTakenaka, 竹中平蔵, 83
97244324, hatoyamayukio, 鳩山友紀夫(由紀夫)Yukio Hatoyama, 82
48264099, asao_keiichiro, あさお慶一郎 前衆議院議員, 81
90521746, hmikitani, 三木谷浩史 H. Mikitani, 80
4171231, tsuda, 津田大介, 80

案の定ニュース新聞系や関係の深いキャスターが出てきましたが、孫さんや三木谷さんなど社長が上位にランクインしたのが以外です。また橋下さん、竹中さん、鳩山さんなど元政治家が出てくるのも面白いですね。

カウントベースで面白い結果が出ていますが、カウントベースだとたくさん人をフォローしている人がフォローしていても、本当に数人しか重要な人しかフォローしない人がフォローしていても、同じ1としてカウントされるので、本当に重要なノードが得られるとは限りません。次にPageRankを使って重要なユーザを探していきます。その前にPageRankなどのアルゴリズムを使うためのNeo4jのGraph Data Science Librayについて説明します。

Neo4j Graph Data Science Library

Neo4jはPageRankなどのグラフアルゴリズムを実行するためにGraph Data Science Libraryが用意されています。データベースには様々なタイプのデータや繋がりを登録したいが、実際にグラフアルゴリズムを使うときにはその中の一部の種類のノードとリレーションシップにフォーカスしたり、部分グラフに注目したり、あるいは既存のグラフから加工して新しいグラフを作った上でアルゴリズムを適応したいことがよくあります。そういうときにクエリと組み合わせて対象となるグラフを抽出・構成したり、事前にアルゴリズムに必要なリソースを見積もったりする便利な機能などが用意されています。

インストールに関しては、Neo4j Desktopの場合は次のように「Manage」をクリックして、「Plugins」タブからインストールします。Neo4j Sandboxの場合は最初から入っているため、インストールは不要です。

politician_02_install_gds1.png
politician_02_install_gds2.png

アルゴリズムを適応するためのグラフを定義します。

データベースにはカテゴリとグループノードがありますが、PageRankを考える場合はUserノードとFOLLOW関係に集中します。実際に作る前にグラフを作るためのリソースを次のように見積もります。

CALL gds.graph.create.estimate('User', 'FOLLOW') YIELD nodeCount, relationshipCount, requiredMemory
with driver.session() as session:
    res = session.run('''
    CALL gds.graph.create.estimate('User', 'FOLLOW') YIELD nodeCount, relationshipCount, requiredMemory
    ''')
res = list(res)
print(res)
[<Record nodeCount=19945 relationshipCount=166491 requiredMemory='[991 KiB ... 1055 KiB]'>]

特に問題がなければ実際に作ります。グラフ名(「follow-net-all」)をつけます。

CALL gds.graph.create('follow-net-all', 'User', 'FOLLOW')
with driver.session() as session:
    res = session.run('''
    CALL gds.graph.create('follow-net-all', 'User', 'FOLLOW')
    ''')

また、全アカウントじゃなくて政治家アカウントのみで計算したいことがあるかもしれません。その場合クエリを使ってネットワークを定義します。具体的にはノードのid、リレーションの始点と終点をリターンします。必要あればリレーションシップのウェイトを指定することもできます

with driver.session() as session:
    res = session.run('''
    CALL gds.graph.create.cypher.estimate( 
    'MATCH (g:Group)--(u:User) RETURN id(u) AS id', 
    'MATCH (:Group)--(u:User)-[r:FOLLOW]->(u2:User)--(:Group) WITH DISTINCT r, u, u2 RETURN id(u) AS source, id(u2) AS target')
    ''')
res = list(res)
print(res)
[<Record requiredMemory='299 KiB' treeView="HugeGraph: 299 KiB\n|-- this.instance: 72 Bytes\n|-- nodeIdMap: 35 KiB\n    |-- this.instance: 32 Bytes\n    |-- Neo4j identifiers: 3088 Bytes\n    |-- Mapping from Neo4j identifiers to internal identifiers: 32 KiB\n    |-- Node Label BitSets: 0 Bytes\n|-- adjacency list for 'RelationshipType{name='__ALL__'}': 256 KiB\n    |-- this.instance: 24 Bytes\n    |-- pages: 256 KiB\n|-- adjacency offsets for 'RelationshipType{name='__ALL__'}': 8224 Bytes\n    |-- this.instance: 16 Bytes\n    |-- page: 8208 Bytes\n" mapView={'name': 'HugeGraph', 'components': [{'name': 'this.instance', 'memoryUsage': '72 Bytes'}, {'name': 'nodeIdMap', 'components': [{'name': 'this.instance', 'memoryUsage': '32 Bytes'}, {'name': 'Neo4j identifiers', 'memoryUsage': '3088 Bytes'}, {'name': 'Mapping from Neo4j identifiers to internal identifiers', 'memoryUsage': '32 KiB'}, {'name': 'Node Label BitSets', 'memoryUsage': '0 Bytes'}], 'memoryUsage': '35 KiB'}, {'name': "adjacency list for 'RelationshipType{name='__ALL__'}'", 'components': [{'name': 'this.instance', 'memoryUsage': '24 Bytes'}, {'name': 'pages', 'memoryUsage': '256 KiB'}], 'memoryUsage': '256 KiB'}, {'name': "adjacency offsets for 'RelationshipType{name='__ALL__'}'", 'components': [{'name': 'this.instance', 'memoryUsage': '16 Bytes'}, {'name': 'page', 'memoryUsage': '8208 Bytes'}], 'memoryUsage': '8224 Bytes'}], 'memoryUsage': '299 KiB'} bytesMin=306456 bytesMax=306456 nodeCount=381 relationshipCount=58 heapPercentageMin=0.1 heapPercentageMax=0.1>]
with driver.session() as session:
    res = session.run('''
    CALL gds.graph.create.cypher( 
    'follow-net-politicians', 
    'MATCH (g:Group)--(u:User) WITH DISTINCT u as u RETURN id(u) AS id', 
    'MATCH (:Group)--(u:User)-[r:FOLLOW]->(u2:User)--(:Group) RETURN id(u) AS source, id(u2) AS target')
    ''')

作ったグラフの一覧を見てみましょう。

with driver.session() as session:
    res = session.run('''
    CALL gds.graph.list
    ''')
res = list(res)
[print(r) for r in res]
<Record graphName='follow-net-all' memoryUsage='5635 KiB' sizeInBytes=5770392 nodeProjection={'User': {'properties': {}, 'label': 'User'}} relationshipProjection={'FOLLOW': {'orientation': 'NATURAL', 'aggregation': 'DEFAULT', 'type': 'FOLLOW', 'properties': {}}} nodeQuery=None relationshipQuery=None nodeCount=19945 relationshipCount=166491 degreeDistribution={'p99': 170, 'min': 0, 'max': 2349, 'mean': 8.347505640511406, 'p90': 0, 'p50': 0, 'p999': 1612, 'p95': 0, 'p75': 0} creationTime=neo4j.time.DateTime(2020, 9, 15, 21, 9, 17.393649, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) modificationTime=neo4j.time.DateTime(2020, 9, 15, 21, 9, 17.515731999) schema={'relationships': {'FOLLOW': {}}, 'nodes': {'User': {}}}>
<Record graphName='follow-net-politicians' memoryUsage='462 KiB' sizeInBytes=473832 nodeProjection=None relationshipProjection=None nodeQuery='MATCH (g:Group)--(u:User) WITH DISTINCT u as u RETURN id(u) AS id' relationshipQuery='MATCH (:Group)--(u:User)-[r:FOLLOW]->(u2:User)--(:Group) RETURN id(u) AS source, id(u2) AS target' nodeCount=346 relationshipCount=13756 degreeDistribution={'p99': 193, 'min': 0, 'max': 239, 'mean': 39.75722543352601, 'p90': 88, 'p50': 28, 'p999': 239, 'p95': 128, 'p75': 57} creationTime=neo4j.time.DateTime(2020, 9, 15, 21, 9, 18.764751, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) modificationTime=neo4j.time.DateTime(2020, 9, 15, 21, 9, 18.931898, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) schema={'relationships': {'__ALL__': {}}, 'nodes': {'__ALL__': {}}}>





[None, None]

作成したグラフを削除するのは次のように行います。

CALL gds.graph.drop('follow_net_all');

PageRank

いよいよPageRankです。PageRankはGoogleの創業者たちが論文で提唱し、それをきっかけに創業したことで有名です。ざっくり言えば、重要な人にフォローされている人が重要である、との仮定に基づいてノードの重要度をスコアとして算出するものです。仮想ユーザをウェブ上にランダムにリンクを辿らせて遷移していった時に、そのユーザが各ノードに止まる確率のようなものです。

さっそく実行してみます。

CALL gds.pageRank.stream('follow-net-all') YIELD nodeId, score
WITH gds.util.asNode(nodeId) as u, score
RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
ORDER BY score DESC LIMIT 10
with driver.session() as session:
    res = session.run('''
    CALL gds.pageRank.stream('follow-net-all') YIELD nodeId, score
    WITH gds.util.asNode(nodeId) as u, score
    RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
    ORDER BY score DESC LIMIT 200
    ''')
res = list(res)
res_df = pd.DataFrame([r.data() for r in res])

res_df
id name screen_name score
0 2291282737 細川護熙 morihirotokyo 0.452028
1 2298092184 小泉純一郎 J.Koizumi J_Koizumi_Japan 0.346655
2 2481369336 None None 0.342734
3 135029283 谷垣禎一 Tanigaki_S 0.339184
4 104388107 河野太郎 konotarogomame 0.325671
... ... ... ... ...
195 759251 None None 0.176333
196 61324547 くしぶち万里 元衆議院議員 kushibuchi 0.176177
197 345178332 衆議院議員森山浩行@立憲民主党堺(りっけん) MORIYAMAhiro 0.176125
198 1195640294261182466 None None 0.176123
199 613201682 None None 0.176091

200 rows × 4 columns

今が人気だけじゃなくて、陰の実力者のアカウントもすこしあぶり出された、というような気もしますね。圧倒的重要さを誇るのは細川さん(二位とのスコア差が大きい)です。細川さんも小泉さんも元総理という重要なポジションであり、そしてカウントベースではむしろ下位に位置していることを考えれば、PageRankがよく機能していると言えるかもしれません。

政治家以外のアカウントを見てみます。

for k, item in res_df[res_df.name.isnull()].iterrows():
    user = {}
    u_id = item['id']
    for u in additional_user_data:
        if u['id'] == u_id:
            user = u
    print('{}, {}, {}, {}, {}'.format(k, u_id, user.get('screen_name'), user.get('name'), item['score']))
2, 2481369336, None, None, 0.3427342087764733
7, 245677083, hashimoto_lo, 橋下徹, 0.3104444960829783
10, 305320802, None, None, 0.29620774772489844
15, 265205959, Kantei_Saigai, 首相官邸(災害・危機管理情報), 0.26993426864236714
18, 99008565, masason, 孫正義, 0.25991508577836087
19, 25073877, realDonaldTrump, Donald J. Trump, 0.25841955984103876
21, 204245399, nhk_news, NHKニュース, 0.2536393801962411
23, 69861141, None, None, 0.25213300565757085
28, 124415804, namatahara, 田原総一朗, 0.23418672573544158
33, 42816371, asahi, 朝日新聞(asahi shimbun), 0.22684923383383965
35, 903338594, sugawitter, 菅 義偉, 0.22650765601559872
36, 412940784, kantei, 首相官邸, 0.22143552415051596
37, 169480493, nikkei, 日本経済新聞 電子版, 0.2214105514823688
39, 48264099, asao_keiichiro, あさお慶一郎 前衆議院議員, 0.22006568025766313
40, 275355095, None, None, 0.2186452617306928
41, 297254593, kogashigeaki, 古賀茂明@フォーラム4, 0.2180277926388264
43, 148961902, HeizoTakenaka, 竹中平蔵, 0.2163264090153946
44, 90521746, hmikitani, 三木谷浩史 H. Mikitani, 0.21538645175146418
45, 97244324, hatoyamayukio, 鳩山友紀夫(由紀夫)Yukio Hatoyama, 0.21532410236155686
47, 94701166, YoichiTakahashi, 高橋洋一(嘉悦大), 0.21393892916563398

データがないアカウントはフォローしている政治家アカウントがすくないものの、重要な政治家アカウントにフォローされているということですね。高い順で「一般社団法人自然エネルギー推進会議」と「古川元久事務所」です。「一般社団法人自然エネルギー推進会議」は名前だけからするとなにやら目立たないけれど有力者とつながってそうな匂いを感じてしまいます。「古川元久事務所」は政治家のアカウントですが、スクレイピング元のデータに欠損がありました。これは逆に考えれば、グラフデータのラベルに欠損がつきものであるが、グラフアルゴリズムを使うことで一部のラベルだけから効率よく残りの類似ノードを見つけられるということかもしれません。

次にDamping Factorを変えてみます。Damping Factorはdefaultの0.85で設定されています。詳細の説明は割愛しますが、循環参照(もともと論文の場合は先行研究しか引用しないので通常循環参照が生じない)があるとスコアがそこに集中したり、収束しないことがありますが、それを抑えるのがDumping Factorです。Dampling Factorの値が大きい(1に近い)と抑えが効かず値が収束しにくかったり、循環参照のスコアが不正に大きくなりがちだが、小さいとスコアが伝搬せずグラフの構造を反映できなくなってしまいます。0.85で使うことが多いです。

with driver.session() as session:
    res = session.run('''
    CALL gds.pageRank.stream('follow-net-all', {dampingFactor: 0.75}) YIELD nodeId, score
    WITH gds.util.asNode(nodeId) as u, score
    RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
    ORDER BY score DESC LIMIT 20
    ''')
res = list(res)
res_df = pd.DataFrame([r.data() for r in res])

res_df
id name screen_name score
0 2291282737 細川護熙 morihirotokyo 0.630261
1 135029283 谷垣禎一 Tanigaki_S 0.523063
2 104388107 河野太郎 konotarogomame 0.502890
3 2298092184 小泉純一郎 J.Koizumi J_Koizumi_Japan 0.492805
4 58359180 自民党広報 jimin_koho 0.492129
5 468122115 安倍晋三 AbeShinzo 0.491159
6 2481369336 None None 0.487239
7 245677083 None None 0.481302
8 94050482 山本一太 ichita_y 0.465500
9 122343424 松本純 junmatsumoto411 0.462421
10 305320802 None None 0.461928
11 914762049481084929 立憲民主党(りっけん) CDP2017 0.460617
12 89631948 小池百合子 ecoyuri 0.460385
13 94482602 世耕弘成 Hiroshige SEKO SekoHiroshige 0.449965
14 112551613 佐藤正久 SatoMasahisa 0.436635
15 265205959 None None 0.423003
16 134715633 松井一郎(大阪市長) gogoichiro 0.413342
17 106595422 平将明 TAIRAMASAAKI 0.411991
18 99008565 None None 0.409122
19 83774916 平井卓也(ひらいたくや) hiratakuchan 0.405061

多少順番が入れ替わった感じですね。

次にネットワークを政治家ノードに限定して算出します。

with driver.session() as session:
    res = session.run('''
    CALL gds.pageRank.stream('follow-net-politicians') YIELD nodeId, score
    WITH gds.util.asNode(nodeId) as u, score
    RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
    ORDER BY score DESC LIMIT 20
    ''')
res = list(res)
res_df = pd.DataFrame([r.data() for r in res])

res_df
id name screen_name score
0 58359180 自民党広報 jimin_koho 4.628814
1 112551613 佐藤正久 SatoMasahisa 4.434653
2 89631948 小池百合子 ecoyuri 3.974174
3 134715633 松井一郎(大阪市長) gogoichiro 3.398299
4 145599783 吉村洋文(大阪府知事) hiroyoshimura 3.087031
5 468122115 安倍晋三 AbeShinzo 2.958654
6 104388107 河野太郎 konotarogomame 2.634810
7 2291282737 細川護熙 morihirotokyo 2.615294
8 2298092184 小泉純一郎 J.Koizumi J_Koizumi_Japan 2.547026
9 94050482 山本一太 ichita_y 2.519077
10 914762049481084929 立憲民主党(りっけん) CDP2017 2.296642
11 96684891 原口 一博 kharaguchi 2.228331
12 94482602 世耕弘成 Hiroshige SEKO SekoHiroshige 2.205480
13 135029283 谷垣禎一 Tanigaki_S 2.131317
14 106595422 平将明 TAIRAMASAAKI 2.000736
15 2590575655 ここりん(公式) nipponkokoro 1.966871
16 83774916 平井卓也(ひらいたくや) hiratakuchan 1.852419
17 76031812 浅田 均(参議院議員) asalogue 1.826080
18 119577038 公明党 komei_koho 1.756745
19 80985167 蓮 舫 ・ 立 憲 民 主 党 ( り っ け ん ) renho_sha 1.713555

また、全政治家ではなく、自民党内での重要性を見てみます。

with driver.session() as session:
    res = session.run(  
        '''
        CALL gds.graph.create.cypher(  
        'follow-net-parties',  
        'MATCH (g:Group {name:"自由民主党"})--(u:User) RETURN id(u) AS id',  
        'MATCH (g:Group {name:"自由民主党"})--(u:User)-[r:FOLLOW]->(u2:User)--(g) WITH DISTINCT r, u, u2 RETURN id(u) AS source, id(u2) AS target') 
        ''')
with driver.session() as session:
    res = session.run('''
    CALL gds.pageRank.stream('follow-net-parties') YIELD nodeId, score
    WITH gds.util.asNode(nodeId) as u, score
    RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
    ORDER BY score DESC LIMIT 20
    ''')
res = list(res)
res_df = pd.DataFrame([r.data() for r in res])

res_df
id name screen_name score
0 112551613 佐藤正久 SatoMasahisa 2.940377
1 58359180 自民党広報 jimin_koho 2.151208
2 135029283 谷垣禎一 Tanigaki_S 1.994588
3 468122115 安倍晋三 AbeShinzo 1.799998
4 104388107 河野太郎 konotarogomame 1.745840
5 83774916 平井卓也(ひらいたくや) hiratakuchan 1.619778
6 94050482 山本一太 ichita_y 1.603370
7 94482602 世耕弘成 Hiroshige SEKO SekoHiroshige 1.591588
8 106595422 平将明 TAIRAMASAAKI 1.451602
9 122343424 松本純 junmatsumoto411 1.385155
10 78646435 片山さつき katayama_s 1.111217
11 148169494 柴山昌彦 shiba_masa 1.076998
12 91760590 牧島かれん makishimakaren 1.043077
13 95405735 あいさわ一郎 ichiroaisawa 0.938201
14 99275472 熊谷 ゆたか kumagai_yutaka 0.925106
15 137884361 三原じゅん子 miharajunco 0.920131
16 202979703 茂木敏充 moteging 0.903428
17 12458472 新藤 義孝 shindo_y 0.842672
18 246575371 山本ともひろ℗ ty_polepole 0.841348
19 135884288 宮川典子 norikomiya 0.834485

民進党内を見てみます

with driver.session() as session:
    res = session.run('''
        CALL gds.graph.drop('follow-net-parties')
    ''')
    res = session.run(  
        '''
        CALL gds.graph.create.cypher(  
        'follow-net-parties',  
        'MATCH (g:Group {name:"自由民主党"})--(u:User) RETURN id(u) AS id',  
        'MATCH (g:Group {name:"自由民主党"})--(u:User)-[r:FOLLOW]->(u2:User)--(g) WITH DISTINCT r, u, u2 RETURN id(u) AS source, id(u2) AS target') 
        '''.replace('自由民主党', '民進党'))
with driver.session() as session:
    res = session.run('''
    CALL gds.pageRank.stream('follow-net-parties') YIELD nodeId, score
    WITH gds.util.asNode(nodeId) as u, score
    RETURN u.userId as id, u.name AS name, u.screenName as screen_name, score
    ORDER BY score DESC LIMIT 20
    ''')
res = list(res)
res_df = pd.DataFrame([r.data() for r in res])

res_df
id name screen_name score
0 107039196 福山哲郎・立憲民主党(りっけん) fuku_tetsu 1.718304
1 174604776 川内 博史 kawauchihiroshi 1.580158
2 80985167 蓮 舫 ・ 立 憲 民 主 党 ( り っ け ん ) renho_sha 1.341613
3 772827848985841664 前原誠司 Maehara2016 1.272803
4 536910778 細野豪志 Goshi Hosono hosono_54 1.163544
5 96785342 玉木雄一郎(国民民主党代表) tamakiyuichiro 1.158696
6 34773800 逢坂誠二 立憲民主党(りっけん) seiji_ohsaka 1.133889
7 96684891 原口 一博 kharaguchi 1.051628
8 116097539 小西ひろゆき (参議院議員) konishihiroyuki 1.026933
9 107846407 馬淵澄夫 mabuchi_sumio 0.962776
10 45708362 階猛(しな たけし) shinatakeshi 0.958277
11 116426900 山井和則 yamanoikazunori 0.954659
12 95338477 有田芳生 aritayoshifu 0.930065
13 279935870 長妻昭りっけん立憲民主党 nagatsumaakira 0.886719
14 55165402 金子洋一・前参議院議員(神奈川県選出) Y_Kaneko 0.856139
15 157592722 あべともこ(衆議院議員・神奈川12区・立憲民主党) abe_tomoko 0.822089
16 711473829759946752 民進党 MinshintoNews 0.796128
17 160175660 長島昭久 Akihisa NAGASHIMA, MP nagashima21 0.781087
18 2904204817 山尾しおり ShioriYamao 0.774538
19 114697823 柚木みちよし yunoki_m 0.745531

最後に重要なノードの大きさをPageRankの値に比例し、リンクの太さをスコアの流れの大きさに比例するようにした図を載せます(政治家のみのネットワークで、PageRank上位25程度のノードを表示、作図はNeo4j Bloomを使用)。

politician_02_PageRank.png

備考

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