League of Legendsの試合データから勝敗を判別する機械学習②

#前回
[前回](https://qiita.com/hyo_07/private/f106efbde82aeb47c8a0)は試合データがどのような形になっていたかの確認を行いました。今回はそのデータの中から一部を抽出したいと思います。

#抽出するデータ
①で取得した1試合のデータの画像を再度貼ります
![loldata.png](https://qiita-image-store.s3.amazonaws.com/0/278834/a98b4ab2-e721-4352-b74b-b1bd6cc72430.png)
これをみると(表示できていないところも多々あるが)、多重辞書(表現が合っているか不明)になっています。そしてこの中でも、
[participants]というキーに対する値が10個のリストになっていて(5vs5のゲーム)、その中の[stats]というキーの中に、それぞれのプレイヤーのその試合における情報が入っていることが分かりました。なので、今回はこれらのデータを抽出して取得をしました。

#データから欲しい部分だけ抽出
まず全体を示すと、

```lol.py
from riotwatcher import RiotWatcher
from time import sleep
import numpy as np

watcher = RiotWatcher("{APIキー}")

region = "jp1"
name = "{サモナーネーム}"

summoner = watcher.summoner.by_name(region, name)
ranked_state = watcher.league.positions_by_summoner(region, summoner["id"])
recentmatchlists = watcher.match.matchlist_by_account(region,summoner["accountId"])

matches = recentmatchlists['matches']
match_data = []
data_list =[]
result_lsit = []
decision_list = ["kills", "deaths", "assists", "largestKillingSpree", "largestMultiKill", "killingSprees", "longestTimeSpentLiving",
 "doubleKills", "tripleKills", "quadraKills", "pentaKills", "totalDamageDealt", "magicDamageDealt", "physicalDamageDealt", "trueDamageDealt",
  "largestCriticalStrike", "totalDamageDealtToChampions", "magicDamageDealtToChampions", "physicalDamageDealtToChampions",
   "trueDamageDealtToChampions", "totalHeal", "totalUnitsHealed", "damageSelfMitigated", "damageDealtToObjectives", "damageDealtToTurrets",
    "visionScore", "timeCCingOthers", "totalDamageTaken", "magicalDamageTaken", "physicalDamageTaken", "trueDamageTaken", "goldEarned",
     "goldSpent", "turretKills", "inhibitorKills", "totalMinionsKilled", "neutralMinionsKilled", "champLevel", "visionWardsBoughtInGame", "wardsPlaced",
      "wardsKilled", "firstBloodKill", "firstBloodAssist", "firstTowerKill", "firstTowerAssist", "firstInhibitorKill", "firstInhibitorAssist"]
      #欲しいデータのキー


for x in range(20):
    match_data.append(watcher.match.by_id(region, matches[x]['gameId']))
    sleep(10)
    #制限回避のためのディレイ

    if match_data[x]["gameMode"] == "CLASSIC":
        for data in  match_data[x]["participantIdentities"]:

            if data["player"]["summonerName"] == name:
                player_num = data["participantId"] - 1

                for n in ["firstBloodKill", "firstBloodAssist", "firstTowerKill", "firstTowerAssist", "firstInhibitorKill", "firstInhibitorAssist"]:
                    if match_data[x]["participants"][player_num]["stats"].get(n,0) == True:
                        match_data[x]["participants"][player_num]["stats"][n] = 1
                    if match_data[x]["participants"][player_num]["stats"].get(n,0) == False:
                        match_data[x]["participants"][player_num]["stats"][n] = 0
                    #TrueとFalseで表現されているものを、０と１に変換

                if match_data[x]["participants"][player_num]["stats"]["win"] == True:
                    match_data[x]["participants"][player_num]["stats"]["win"] = 1
                if match_data[x]["participants"][player_num]["stats"]["win"] == False:
                    match_data[x]["participants"][player_num]["stats"]["win"] = 0
                #同上

                data_list.append([match_data[x]["participants"][player_num]["stats"].get(i,0) for i in decision_list])
                result_lsit.append(match_data[x]["participants"][player_num]["stats"]["win"])
                #1試合分のデータを全データが入るリストの中に入れる

print(summoner)
print(data_list)
print(result_lsit)
```
まず追加されたものとしては最初にdecision_listですが、これは試合データの中からプレイヤーの視点からみてゲームに少しでも影響のある情報であると考えたもののキーを抽出しました。

次に

```lol.py
for x in range(20):
    match_data.append(watcher.match.by_id(region, matches[x]['gameId']))
    sleep(10)
```
は、①で行った1試合のデータの取得をfor文に入れたものである。試合データは一度に最大20試合分取得が出来て、それらがリストで返されることになっている。よってmatces[x]で20回for分を回すことにしました。また、このときのリストはインデックスが小さいほど新しいの試合。つまり、インデックスが0の試合が最新の試合です。
また、sleep(10)は、APIの使用制限にかからないように少し大きめだがディレイを発生させました。

このfor文で回す中身を見ていくと、

```lol.py
if match_data[x]["gameMode"] == "CLASSIC":
    for data in  match_data[x]["participantIdentities"]:
```
が最初にあります。このゲームはゲームルールが複数種類あるため、一番主流である、メインのゲームモードであるとき。という条件を入れました。
そして下のfor文で、要素が10個のリストとなっているmatch_data[x]["participantIdentities"]で回します。これは、今、このゲームには10人のプレイヤーがいて、この[participantIdentities]のバリューが、10人のプレイヤー情報が入っているためです。そのプレイヤー情報の中に、サモナーネーム(プレイヤー名)が入っています。よってこの部分でfor文を回すことで、プレイヤーのその試合におけるIDを検索しようと考えました。

次にその検索が次のようになります。

```lol.py
if data["player"]["summonerName"] == name:
    player_num = data["participantId"] - 1
```
そのプレイヤーがこの試合データにおいて、data["player"]["summonerName"] のバリューが name と同じ文字列をもつ場合という条件を挟みました。また、これ以降にこのプレイヤーをピンポイントで見つけるために、プレイヤーIDを取得し、それを player_num に入れました。
このとき、各プレイヤーのIDは１から１０と割り振られている一方、このデータはリストとしてバリューになっています。そこで、そのズレを治すために、IDから-1することで、リストのインデントとして使えるようにしました。

どのIDの情報を取得するかを分かったので、最初にリスト(decision_list)にしておいた欲しい情報のキーをfor文で回そうと思ったのですが、一部のバリューが真偽値で返されていました。実際に学習にかける上で真偽値でも良いのか分からなかったため、一応０と１にしておこうと思い、

```lol.py
for n in ["firstBloodKill", "firstBloodAssist", "firstTowerKill", "firstTowerAssist", "firstInhibitorKill", "firstInhibitorAssist"]:
    if match_data[x]["participants"][player_num]["stats"].get(n,0) == True:
        match_data[x]["participants"][player_num]["stats"][n] = 1
    if match_data[x]["participants"][player_num]["stats"].get(n,0) == False:
#TrueとFalseで表現されているものを、０と１に変換
```
それぞれTrue, Falseという値のとき、そのバリューを１と０に書き換えることをしました。
省いてしまいますが、この次のif文も勝敗が真偽値だったものを同じように書き換えています。

最後に、IDの特定や値の変換を行ったので、

```lol.py
data_list.append([match_data[x]["participants"][player_num]["stats"].get(i,0) for i in decision_list])
result_lsit.append(match_data[x]["participants"][player_num]["stats"]["win"])
#1試合分のデータを全データが入るリストの中に入れる
```
今、試合ごとのリストにしたいため、data_listというリストに、 decision_list でfor文を回したもので出来た試合データの情報をリスト内包表記でリスト化したものを追加し、2重リストの形で保存していきました。これで、各試合データがリスト化され、さらにそれを試合ごとのリストに出来ました。
relust_lit の方も同じです。こちらは機械学習にかける上での答えのラベルになるため、試合データとは別にリストに追加していきます。

#出力結果
これを出力した結果がこちらです
![loldata2.png](https://qiita-image-store.s3.amazonaws.com/0/278834/c67da680-c7e1-d950-3f9e-1df213ff58fb.png)

少々見づらいですが、3個の出力が出ています。
まず一番最初のものが、今回調べさせてもらった知人のサモナーネーム、ブラックハヤテ号さんのプレイヤー情報です。

2つ目が各試合データの一部分のバリューの値を直近20試合分リスト化したものです。今回は20試合分取得できましたが、もし違うゲームモードを直近20試合のうちに行っていたら、それを除いた19試合分のデータがリスト化されていました。また、真偽値となっていたものも、０と１に変換が出来ていることが分かります。

最後が勝敗のリストです。こちらも、真偽値を０と１の値に変換が出来ています。

#まとめ
今回は、機械学習を行うためのデータ集めを行いました。現状、機械学習のためのデータセットの作り方、データの整え方の知識が不十分なため、保存をしない、出力するだけのプログラムとなっていますが、次はこれらのデータを機械学習にかけられる形に整え、保存し、実際に機械学習を行うところまで行いたいと思います。

今回のコードは[こちら](https://github.com/hyo07/lolapi/blob/master/lol.py)においてあります。また、③で記してありますが、最後の部分に少々手が加わっていますので、詳しくはそちらを見てもらえると幸いです。

League of Legendsの試合データから勝敗を判別する機械学習③は[こちら](https://qiita.com/hyo_07/items/0051ed5acbde22567041)