TwitterのフォロワーをNetworkX, Cytoscapeで可視化

初投稿です．緊張してます．

# 概要
Twitterの指定したユーザのフォロワーたちを[Cytoscape](http://www.cytoscape.org/)で可視化してみました．
定番のテーマですね．ネットワークの操作には，導入の簡単さを考慮してNetworkXを使用します．
また，ここでは知り合いのアカウント4つのフォロワーを取得・可視化しています．

# 環境
- Python 3.6.2
    - tweepy 3.5.0
    - Networkx 2.1
- Cytoscape 3.5.1

# 流れ
1. Python, tweepyを用いてTwitterの指定ユーザのフォロワー一覧を取得します．
2. NetworkXを用いてフォロワー一覧をグラフオブジェクトに変換します．
3. gml形式で保存します．
4. Cytoscapeで保存したgmlファイルを読み込みます．

※ Twitter APIは操作できる前提とします．

# API認証

```python
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)

api = tweepy.API(auth, wait_on_rate_limit=True)
```

# フォロワー取得
```python
def getFollowers_ids(api, id):
    # Get Id list of followers
    followers_ids = tweepy.Cursor(api.followers_ids, id=id, cursor=-1).items()

    followers_ids_list = []
    try:
        followers_ids_list = [followers_id for followers_id in followers_ids]
    except tweepy.error.TweepError as e:
        print(e.reason)

    return followers_ids_list

```

# 取得したデータを辞書型に整形
NetworkXでは，辞書型のデータをそのままネットワークに変換することができるので，そのために整形をしています．Keyは「指定したユーザの`id`」，Valueは「フォロワーの`id`のリスト」です．

また，指定したユーザの情報がidのみだと不便なので，「screen_name」「フォロー数」「フォロワー数」も取得し，辞書型に整形しています．Keyは「ユーザの`id`」，Valueは「上記3つをキーに持つ辞書」です．

（idとscreen_nameは違うものなので注意．@~~~の部分がscreen_nameです．）

```python

center_to_followers = {}
node_attrs = defaultdict(dict)

# center account: @hoge, @hogehoge
CENTER_ACCOUNTS = ['hoge', 'hogehoge']

for center_screen_name in CENTER_ACCOUNTS:

    # get center account information (node attributes)
    center_info = api.get_user(screen_name=center_screen_name)

    # get id of center account
    center_id = center_info.id

    node_attrs[center_id]['screenName'] = center_screen_name
    node_attrs[center_id]['followersNum'] = center_info.followers_count
    node_attrs[center_id]['followNum'] = center_info.friends_count

    center_to_followers[center_id] = getFollowers_ids(api=api, id=center_screen_name)

    # set empty value to account attribute that is not center
    for follower_id in center_to_followers[center_id]:
        node_attrs.setdefault(follower_id, {'screenName': '', 'followersNum': '', 'followNum': ''})
```

# NetworkXのグラフオブジェクトに変換 / gml形式で保存
NetworkXにある`from_dict_of_lists()`を使用することでネットワークオブジェクトを作成できるので，先程の辞書からネットワークオブジェクトを作成．さらに，「screen_name」などを含むノード情報を，`set_node_attributes()`を用いてネットワークの各ノードに持たせます．

最後に，`write_gml()`を用いてgml形式で保存すればPythonの操作はおしまいです．

```python
graph = nx.from_dict_of_lists(center_to_followers)
nx.set_node_attributes(graph, node_attrs)
nx.write_gml(graph, 'twitter.gml')
```

# Cytoscapeで読み込み
Cytoscapeを起動して，先程作成したgmlファイルをドラッグ・ドロップで読み込みます．
恐らく，最初は，デカい1つのノードのような物が表示されると思うので，メニューバーから*__Layout -> Apply Preferred Layout__*を選択する事で，それっぽく見えるようになるかと思います．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244005/8db7af68-fa85-ca0f-5d36-5ebefea82491.png)

あとは，目的や好みに合わせてレイアウトを編集すればOK．
Cytoscapeはgmlファイルに含まれるノード情報などもしっかりと保持してくれているので，フォロワー数によってノードの大きさなどを変えることも可能です．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244005/9d3e9996-0e1c-63ff-6ea8-ac5f05cc4359.png)

下の画像は，以下の処理をしたものです．少し大きいノードが今回指定した知り合いの4つのアカウントですね．

- *__Style__*を*default*から*default black*に変更
- Control Panelから，*__Style -> Size -> Column, Mapping Type__* を変更してノードのサイズを変更
- *__View -> Show Tool Panel__*でスケールを変更
- *__Layout -> Bundle Edges -> All Nodes and Edges__*でエッジを束ねる
- *__Layout -> Circular Layout__*でレイアウトを変更

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244005/180d55ec-18dc-834b-aa04-a8b19d460b5c.png)

# あとがき
定番の可視化をやってみました．今回はgmlファイルを経由しましたが，Jupyter上で簡単にCytoscapeを操作できるようなので，その辺もおいおい触ってみたいです．
あと，編集時，画像サイズ制限知らなくて，ちょっと詰んでました．

# 参考
[TweepyでフォロワーのIDを全て取得してみた - Research Tips](http://tmngtm.hatenablog.com/entry/2016/11/10/133320)
[Cytoscape / cyRESTとpy2cytoscapeを用いたIPython Notebook上でのグラフ解析と可視化 Part 1 - Qiita](https://qiita.com/keiono/items/ed796643107bd03aff64)