読者です 読者をやめる 読者になる 読者になる

歩いたら休め

If the implementation is easy to explain, it may be a good idea.

【Python】日本の有名Pythonistaを特定するために、Twitterをネットワーク分析してオピニオンリーダーを見つけるライブラリを作った

twitter python networkx ネットワーク科学

私はプログラミング言語の中ではPythonが好きなのですが、日本人の有名なPythonistaはほとんど知りません。 そのため、Pythonの最新情報は、R言語やデータ分析に詳しい方から(主にPyData関連を)又聞きするような形でしか追えていません。

例えばGoogleで「日本 Pythonista」等のワードで検索しても、iOS用Python開発環境だったり「なぜ日本ではPythonが流行らないのか」みたいな記事ばかり引っかかって悲しい気持ちになります。 これがRubyであれば、Rubyの製作者のMatzを始め、著名なコミッターやRubyistの方がわらわら見つかるのですが。

そこで、Twitterをネットワーク分析して、多くのPythonユーザーが「信頼できる情報源」として見ているアカウントを見つけることにしました。

「多くのPythonistaにリツイートされているのは信頼できるPythonistaのアカウント」と仮定しました

Googleページランクに近い発想だと思います。

Twitterのユーザーは信頼できると思っているユーザーのツイートをリツイートする」という仮定を置いて、次のような手順でプログラムを書き始めました。

  1. Pythonのユーザーを何人か適当に選ぶ
  2. その人がリツイートしているアカウントをランダムに選び、クロールする作業を繰り返す
  3. 1, 2の手順を繰り返す
  4. 多くの人からリツイートされているアカウントがPythonユーザーに信頼されているアカウント

TwitterAPIを叩ける数は限られているため、Pythonのユーザー周辺のネットワークを探索するようにしました。

ところが、Pythonユーザーでも当然Pythonのことばかりツイートしている人は皆無です。 そのため、2の手順の際に(例えば一般的なニュースアカウントのリツイート先を辿って)コミュニティの外をクロールし始め、ほとんどのユーザーが0~1回しかリツイートされてない状態になってしまいました。

そのため、実際には「多くのPythonユーザーにリツイートされているユーザーは、Pythonユーザーである可能性が高い」という仮定を置いて、 以下のようなプログラムを書きました。

  1. Pythonについてツイートしているユーザーを何人か適当に選ぶ
  2. その人がリツイートしているアカウントをランダムに選び、クロールする
  3. リツイートされてた数の多い(多くのPythonユーザーから引用されている)ユーザーがリツイートしているアカウントをクロールする
  4. 2, 3の手順を繰り返す
  5. 多くの人からリツイートされているアカウントがPythonユーザーに信頼されているアカウント

学生時代に複雑ネットワークの本を読んでおいてよかったです。増田先生に感謝😭🙏

複雑ネットワーク―基礎から応用まで

複雑ネットワーク―基礎から応用まで

また余談ですが、

「(風邪などの)感染症は周囲に感染者が1人でもいればランダムに伝染するのでコミュニティ間を楽に伝播するが、文化や技術は、周囲の複数人が採用しなければ信頼されないため、コミュニティ間をなかなか伝播できない」

らしいので、複数人から引用されなければクロールされにくいよう設定している上の手順は、それなりにコミュニティ内部を重点的にクロールできる設定になっている気します(有向グラフでも同じなのかとか難しそうだけど)。たしかこの本にその話が書いてました。

ネットワーク・大衆・マーケット ―現代社会の複雑な連結性についての推論―

ネットワーク・大衆・マーケット ―現代社会の複雑な連結性についての推論―

分析のためのライブラリを作りました

コードの再利用性を高める&ブログで説明しやすくするため、Python3系でライブラリにしました。

超すごいデータサイエンティストのHadley Wickham先生が『Rパッケージ開発入門』の中で、「定型手順をライブラリ化するとめっちゃ楽。ていうか極論だけどデータ分析は全部ライブラリでやるべきかも」みたいなことを言ってた気がするので。

github.com

ライブラリ名がめっちゃわかりづらくて微妙な気がしますが…。

Rパッケージ開発入門 ―テスト、文書化、コード共有の手法を学ぶ

Rパッケージ開発入門 ―テスト、文書化、コード共有の手法を学ぶ

以下の様なコードで、クローリングを完了し、pandasのデータフレームに結果を格納します。

import pandas as pd
import leaderchecker as lc

# Twitterのアクセストークン等をセットする
tw_confing = {
    'token': 'your twitter access token',
    'token_secret': 'your twitter access token secret',
    'consumer_key': 'your twitter consumer key',
    'consumer_secret': 'your twitter consumer secret'
    }
oauth = lc.OAuth(**tw_config)
client = lc.LeaderChecker(oauth)

# "#pyconjp"で検索し、クロールの起点になるアカウントをセットする
client.search_seed_accounts(word='#pyconjp')

# 上記の手順でTwitterのRT関係をクロールしてネットワーク構造をセットする
# APIの実行回数の制限に引っかかることもあるので、例外が起きた場合は15分待って実行し直す、みたいな処理を書いたほうがいいかも
# (その場合、twitterライブラリのTwitterHTTPErrorが出ます)
# 「リンクを受け取っている数が上位5人ずつを、10回クロールする」という意味です
client.build_community_structure(trials=10, bulk=5)

# 各Twitterユーザーのネットワークの次数を計算して、データフレームに格納する
result = client.get_members_degree()
# ページランクを計算する関数も作ってます
# result = client.get_members_pagerank()
dataframe = pd.DataFrame(result)

最初の検索ワードを自由に選べるため、それなりに汎用的に使えるライブラリになっていると思います。 今度音楽のコミュニティでも同じようなことをやってみようかな。

分析結果

上のコードにもちょっと書いてますが、#pyconjpハッシュタグをツイートしているツイートしている人を起点にし、1464人のユーザーが見つかりました。

ちなみにpyconとはPythonのカンファレンスで、今年の9月にも早稲田大学で開催されます。

pyconjp.connpass.com

まず、単純にネットワークの次数(リツイートされた数)を計算してソートしてみました。

result = client.get_members_degree()
dataframe = pd.DataFrame(result)
dataframe.sort('degree', ascending=False)

上位5人を書くと、こんな感じでした。

screen_name degree
430 syuu1228 11
807 kotatsu_mi 9
934 naota344 8
643 gihyosd 8
1395 kosaki55tea 7

Pythonistaっぽいかどうかは置いといて、それなりの確度で抽出できた…のかなあ…。 SoftwareDesignの公式アカウント(@gihyosd)が出てますね。

次に、ページランクを計算してソートしてみました。 ただ、最初にネットワークでクロールする対象が偏っているため、ページランクを使うのは適切ではない可能性もありそうです。

ページランクを算出する際のダンピングファクター(alpha)は、とりあえず0.8で設定しました。

result = client.get_members_pagerank(alpha=0.8)
dataframe = pd.DataFrame(result)
dataframe.sort('pagerank', ascending=False)

こちらのほうが確度が高くなる…と予想していたのですが、NHKやCNNなどの一般的なニュースアカウントが出てきてしまいました。 たしかに「信頼できる情報源」ではありますが。

screen_name pagerank
368 nhk_nc11 0.001313
1068 CNN 0.000937
350 pskh 0.000937
1169 iwiwi 0.000911
1420 jmayer 0.000886

ただ、すごい人もそれなりにはひっかかっています。Pythonっぽいかは置いといて。

もしかすると、Pythonは他の言語も使うマルチリンガルな人も多い(数値計算ならRとかC++とか、WEBならRubyとか)などの理由があり、 Python自体のコミュニティが密ではなく、もっと広いプログラミングのコミュニティを抽出してしまったのかもしれません。

もっと密なコミュニティが見つけられるワードならもう少しうまくいくのかもしれません。

結論

それなりにいい感じだったけど、特にPythonっぽい人は抽出できなかった。

特定のコミュニティだけで使われているワードなどでも試したい。