ぱそきいろのIT日記

ぱそきいろがITに関する記事を書いていきます。

【Python】ポケモンでクラスター分析

こんにちは、ぱそきいろです。
ネットサーフィンしてたら、ポケモンのデータをまとめたJSONがありました。
github.com
Read me には

This repository provides a basic dataset of all Pokemons.

とあります。
名前と種族値がまとめられてるJSONファイルや、それぞれのポケモンの画像があります。

今回はポケモンを種族値でクラスター分析して、一覧で表示したいと思います。
よろしくお願いします。

ポケモンデータ

まずは Python でデータを読み込んで中身を見てみます。

s=open("./pokemon.json-master/pokedex.json","r")
json_load=json.load(s)

pprint.pprint(json_load[0],width=40)

分類するデータはこんな感じです(フシギダネのデータ)。

{'base': {'Attack': 49,
          'Defense': 49,
          'HP': 45,
          'Sp. Attack': 65,
          'Sp. Defense': 65,
          'Speed': 45},
 'id': 1,
 'name': {'chinese': '妙蛙种子',
          'english': 'Bulbasaur',
          'french': 'Bulbizarre',
          'japanese': 'フシギダネ'},
 'type': ['Grass', 'Poison']}
クラスター分析

クラスター分類のうち「非階層的クラスタ分析」をしていきます。

詳しくはここを参考にして実装していきます。
pythondatascience.plavox.info

#データを使いやすいように整形
name=[]
attack=[]
defense=[]
hp=[]
spattack=[]
spdefense=[]
speed=[]

for i in range(len(json_load)):
    name.append(json_load[i]["name"]["japanese"])
    attack.append(json_load[i]["base"]["Attack"])
    defense.append(json_load[i]["base"]["Defense"])
    hp.append(json_load[i]["base"]["HP"])
    spattack.append(json_load[i]["base"]["Sp. Attack"])
    spdefense.append(json_load[i]["base"]["Sp. Defense"])
    speed.append(json_load[i]["base"]["Speed"])

#numpyに変形
myarray=np.array([attack,defense,hp,spattack,spdefense,speed],np.int32)
myarray=myarray.T
clusternum=20
#KMeansでクラスター分類
pred=KMeans(n_clusters=clusternum).fit_predict(myarray)
クラスター数 20 で分析

とりあえず、クラスター数 20 で分類してみます。
可視化した結果が以下です。
f:id:takabsk55:20200506234257p:plain
f:id:takabsk55:20200506234317j:plain

とりあえず、特徴的な物を見ていきたいと思います。
分かりやすそうな以下の4つを見ていきます。
f:id:takabsk55:20200507001552j:plain

ステータス低め
なんというか、弱そうですねw
キャタピー枠というか、昆虫枠が入ってますね。
f:id:takabsk55:20200507001706p:plain


ステータス高め
こっちは一転して強そうなポケモンばっかりですね。
アルセウス以降の半分くらいは分からない。。。
インフレしてるんですかねぇ。。。
f:id:takabsk55:20200507001954p:plain


HP高め
HPが特徴的に高いクラスにラッキーとハピナスの 2 体が分類されてました。
さすがジョーイさんのポケモンという感じですね。
f:id:takabsk55:20200507002210p:plain


防御高め
防御が特徴的に高いクラスにはツボツボだけが分類されました。
詳しくないので、ググると防御力が高いというだけ有名みたいです。
f:id:takabsk55:20200507002819p:plain

適切なクラス数を探す

と、ここでクラスター数が 20 でいいのか思いました。
調べてみると最適なクラスター数を調べる方法がありました。
qiita.com
エルボー法というのがあるみたいなので、試してみます。
ポケモンの数が 800 ちょっとあるので、2~800の間で調べます。
時間がかかるので適当に打ち切って結果を見ます。

for i  in range(2,800):         # 1~10クラスタまで一気に計算
    print(i)
    km = KMeans(n_clusters=i,
                init='k-means++',     # k-means++法によりクラスタ中心を選択
                n_init=10,
                max_iter=300,
                random_state=0)
    km.fit(myarray)                         # クラスタリングの計算を実行
    distortions.append(km.inertia_)   # km.fitするとkm.inertia_が得られる

    plt.plot(range(1,i),distortions,marker='o')
    plt.xlabel('Number of clusters')
    plt.ylabel('Distortion')
    plt.savefig("elbo")

f:id:takabsk55:20200507004640p:plain
なんとなく 50 クラスくらいでガクッと下がってる気がします。
50 クラスでクラスター分類してみます。

クラスター数50で分類

f:id:takabsk55:20200507011232p:plain
f:id:takabsk55:20200507011100p:plain
f:id:takabsk55:20200507011112p:plain

また、特徴的なクラスを見ていきます。

HP高め、防御高めはやっぱりこのクラスに分かれるみたいです。


f:id:takabsk55:20200507002210p:plainf:id:takabsk55:20200507002819p:plain

若干弱そうなクラスですが、御三家ポケモンが多い気がします。
f:id:takabsk55:20200507011521p:plain

ハサミが多いクラス笑
f:id:takabsk55:20200507011652p:plain

岩タイプというか、見た目がゴツいクラス。
f:id:takabsk55:20200507011808p:plain

格闘家が多いクラス。
f:id:takabsk55:20200507011907p:plain

まとめ

種族値で特徴がありそうということがわかりました。
私がポケモンに詳しかったらもうちょっといい分析ができたのかもしれませんが、今は見た目でしか分析できません、、、
何か気づいたことがありましたら、コメントいただけると嬉しいです。
ありがとうございました。