乃木坂46起点のアーティスト関係図を描画する(Spotify API, Network X)

#はじめに
Spotify APIで乃木坂46の関連アーティストを呼び出し、PythonライブラリのNetwork Xを使って、アーティスト関係図を描画したいと思います。
Spotify APIの利用方法や基本的な機能は[こちら(Spotify APIで乃木坂46を分析したい)](https://qiita.com/g-k/items/f6f67128b1be962c9d33)に投稿しています。

##参考
Spotify APIで好きなアーティストの繋がりを可視化してディグる
https://blog.aidemy.net/entry/2018/08/31/142408

Spotipyのドキュメント（spotipyはSpotify APIをpythonで使用するためのライブラリ）
https://spotipy.readthedocs.io/en/latest/#

Spotify APIのリファレンス
https://developer.spotify.com/documentation/web-api/reference-beta/

##Python使用環境
・spotipy             2.4.4     
・numpy               1.15.4    
・networkx            2.3       
・matplotlib          3.0.2     
・numpy               1.15.4    

#アーティスト関係図の描画
##アーティスト関係図について
アーティスト関係図は乃木坂46を起点として、「乃木坂46の関連アーティスト」「乃木坂46の関連アーティストの関連アーティスト」という形式で辿っていくことで関係データを溜めていきます。それらを関係図の形で描画することで、乃木坂46を起点として「あるアーテイストを聞いている人が他によく聞いているアーティスト群」が一目でわかるのではないかという試みです。イメージはこんな感じです。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/12833120-9c1f-2c6a-ef6c-57f131b781c0.png)

##アーティスト関係図の描画実装
アーティスト関係図を描画するコードを実装します。
手順としては、まず起点となるアーティストのidからその関連アーティストのデータを取得します。
さらにその取得したアーティストの関連アーティストを辿って...という感じでぐるぐる回してデータを蓄積します。その後そのデータを用いて、networkxで関係図を描画すれば完成です。
下記が作成したコードです。至らない箇所も多いコードとは思いますがご了承ください。。。
事前に日本語が文字化けしないようにフォントを設定済みです。必要な方は[こちら](https://qiita.com/yniji/items/3fac25c2ffa316990d0c)をご参照ください。

```python
import spotipy
import matplotlib.pyplot as plt
import networkx as nx
from spotipy.oauth2 import SpotifyClientCredentials

client_id = 'ここに自分のクライアントIDを記載'
client_secret = 'ここに自分のシークレットキーを記載'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotipy.Spotify(client_credentials_manager=client_credentials_manager)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)


class Spotify_Artists_info:
    
    def __init__(self, name):
        self.name = name
        self.related_artist = None
       
    #指定した名前のアーティストのidを取得する関数
    def get_artist_uri(self):
        
        row = spotify.search(q='artist:' + self.name, type='artist')['artists']['items'][0]['uri']
        uri = row.split(':')[2]
        
        #指定した名前のアーティストのuriを返す
        return uri

    #関連アーティストのデータを取得する関数
    #sizeで何階層まで関連アーティストを辿るのかを指定
    def relation_list(self, size):
        
        related_artist = []

        #まず、指定のアーティストの直接の関連アーティストのデータを取得する
        for i in spotify.artist_related_artists(self.get_artist_uri())['artists']:
            related_artist.append([spotify.artist(self.get_artist_uri())['name'], i['name'], i['uri'].split(':')[2]])
         
        #第二階層以上を辿る場合はここからぐるぐる回す
        if size > 1:
            count = 0
            
            size = size-1

            for i in range(size):
                head = count
                tail = len(related_artist)
                for uri in np.array(related_artist)[:,2][head:tail]:
                    key_artist = spotify.artist(uri)['name']
                    for x in spotify.artist_related_artists(uri)['artists']:
                        related_artist.append([key_artist,x['name'], x['uri'].split(':')[2]])
                count += tail
                
            self.related_artist = related_artist
        
        else:
            self.related_artist = related_artist
     
    #描画の際のノードの色を変化させる関数
    def fnc_color(self, siz):
        colorlist = ['tomato', "moccasin", "palegreen", "pink", "lightblue", "thistle","lightgrey", "w"]

        if siz >=1000:
            return colorlist[0]
        elif siz >=500:
            return colorlist[1]
        elif siz  >=250:
            return colorlist[2]
        elif siz >= 100:
            return colorlist[3]
        elif siz >= 50:
            return colorlist[4]
        else:
            return colorlist[5]
     
    #アーティストの関係図を描画する関数
    def generate_relation_map(self):
        for i in self.related_artist:
            G.add_edge(i[0], i[1])

        plt.figure(figsize = [50, 50])

        pos = nx.spring_layout(G, seed = 1, k = 0.2)
        #フォントは日本語が文字化けしないように、事前にダウンロード済み
        nx.draw_networkx_labels(G, pos, font_color='k', font_family='IPAexGothic')

        nx.draw_networkx_nodes(G, pos, alpha=0.7, node_shape="o",
                             linewidths = 1,
                               #次数中心性(そのノードから何本線が出ているか)を元にノードの大きさとサイズを指定![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/ab24738e-c6df-eb27-aefc-59e74165a48d.png)

                               node_color = list(map(self.fnc_color  ,[nx.degree_centrality(G)[i]*20000 for i in G.node])),
                               node_size = [nx.degree_centrality(G)[i]*20000 for i in G.node])

        nx.draw_networkx_edges(G, pos, alpha=0.3)

```


##描画
では、上記を用いて実際に乃木坂46を起点としてアーティスト関係図を描画してみます。
今回は、乃木坂を起点として第2階層までの描画とします。ちなみに階層を増やす毎にデータは指数関数的に増えていくため、その分非常に時間がかかります。

```python
s = Spotify_Artists_info('Nogizaka46')
s.relation_list(2)
s.generate_relation_map()
```

描画した結果がこちら、
**よくわからんけどなんかすごい。。。**

![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/67141e99-fd74-0fb1-5bad-3f128cf470d1.png)


#アーティスト関係図の中身を分析
上記のアーティスト関係図ですが、よくよく見るとノード（丸のこと）が密集している箇所がいくつかあるのがわかります。
それぞれのクラスターについて少し詳しくみていきます。

![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/50845036-d359-71e4-2de1-be868d561c00.png)

##①アイドルクラスター
まず、1つ目のクラスターを見ていきます。少し重なっている部分が見にくくて恐縮ですが、４８系グループを中心にアイドルグループが集まっていることがわかります。48系やその派生ユニットだけでなく、「SUPER GIRLS」や「私立恵比寿中学」など他系統のアイドルグループ存在しています。そんな中、**乃木坂46は少しクラスターから外れているのがお分りでしょうか。**(画像の右端にあります。)前回の[投稿](https://qiita.com/g-k/items/f6f67128b1be962c9d33)にも記載しましたが、乃木坂46のファン層は所謂アイドルファン層のみ、という状況を脱しつつあることがわかります。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/f1ccda50-439e-99fd-ef4f-b6c2b613ccd2.png)

##②人気J-POPクラスター
続いて、乃木坂46が属しているクラスターです。中には、「SEKAI NO OWARI」や「miwa」、「GReeeeN」や「Superfly」など、**既に人口に膾炙しているような人気J-POPアーティストが目立ちます。**（筆者はあまり音楽知識がないため、本当はもっと適切な定義付けが可能かもしれません。また、「SEKAI NO OWARI」はJ-POPなのか、みたいな問題もあるような気がするので、何となく大衆のレベルで認知度がある、というくくりの方がよいかもしれません。）また、その中に乃木坂46が入っているのを見ると、やはりアイドルと枠を脱して大衆レベルの認知度を獲得しつつあるのかとなと思います。

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/a3d61729-5cd8-6525-d02a-199dc9d9f143.png)

##③EXILEクラスター
3つ目は、「EXILE」や「EXILE TRIBE」、「E-girls」など株式会社LDH JAPAN（EXILEのHIROが創業）に所属するグループのクラスターです。**面白いのは、このクラスターがJ-POPクラスタとあまり近い位置にない**、という点です。筆者としては、「EXILE」や「E-girls」はもっとJ-POP寄りのところにあっても良いのかな、という感覚なのですが、実際は割とはっきりファン層は分かれており、EXILE系グループを支持する層というのが明確に存在するということでなんでしょう。

![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395230/bba83218-99ba-898f-90e0-0c8b9cce4a67.png)

もうひとつクラスターがあるのですが、筆者の音楽スキルが足りないため定義づけは諦めました。。。みなさんの方で色々試してみてどんな関係図が現れるのか試していただければ楽しいと思います！

#おわりに
やっぱりSpotify APIは色々できて楽しいで、他の切り口の分析にもチャレンジしていければと思います。