League of Legend RiotAPIでデータサイエンスを勉強しよう【その2】
前回の記事で手に入れた、各試合のデータ(68試合分)から、勝敗にはどんな要因が関係しているのかを探ります。
APIで得られたデータをCSVに
前回、APIを繰り返し使用することで、ディクショナリのリストとしてデータを取得しました。
これをcsvファイルにして、保存しておきましょう。
ここでは、よくデータ分析に使われているpandasモジュールを使ってcsvファイルとして出力してます。
import pandas as pd
#statsListというリストにLoLの試合データを前回保存しました。
#これをpandasのデータフレーム型に変更します。
stats_df = pd.DataFrame(statsList)
#stats_dfの中でもあまり試合に関係なさそうなカラム(例えばダブルキルの数とか)をdrop()によってそぎ落としています。
df = stats_df.drop(["perk0",
"perk0Var1",
"perk0Var2",
"perk0Var3",
"perk1",
"perk1Var1",
"perk1Var2",
"perk1Var3",
"perk2",
"perk2Var1",
"perk2Var2",
"perk2Var3",
"perk3",
"perk3Var1",
"perk3Var2",
"perk3Var3",
"perk4",
"perk4Var1",
"perk4Var2",
"perk4Var3",
"perk5",
"perk5Var1",
"perk5Var2",
"perk5Var3",
"perkPrimaryStyle",
"perkSubStyle",
"combatPlayerScore",
"doubleKills",
"firstBloodAssist",
"firstBloodKill",
"firstInhibitorAssist",
"firstInhibitorKill",
"firstTowerAssist",
"firstTowerKill",
"inhibitorKills",
"item0",
"item1",
"item2",
"item3",
"item4",
"item5",
"item6",
"killingSprees",
"largestCriticalStrike",
"largestKillingSpree",
"largestMultiKill",
"neutralMinionsKilled",
"neutralMinionsKilledEnemyJungle",
"neutralMinionsKilledTeamJungle",
"objectivePlayerScore",
"participantId",
"pentaKills",
"playerScore0",
"playerScore1",
"playerScore2",
"playerScore3",
"playerScore4",
"playerScore5",
"playerScore6",
"playerScore7",
"playerScore8",
"playerScore9",
"quadraKills",
"timeCCingOthers",
"totalHeal",
"totalPlayerScore",
"totalScoreRank",
"totalTimeCrowdControlDealt",
"totalUnitsHealed",
"tripleKills",
"trueDamageDealt",
"trueDamageDealtToChampions",
"trueDamageTaken",
"turretKills",
"unrealKills",
"wardsKilled",
"sightWardsBoughtInGame"
], axis=1)
#スリムになったデータをCSVファイルとして保存します。
df.to_csv(path_or_buf = 'LoL.csv', index = False)
これで、jupyternotebookを開くたびにAPIを使う必要がなくなりました。
データをpandasで見てみよう
新しくjupyternotebookを開いて、さっき保存したデータを読み込んでみましょう。
import pandas as pd from pandas import Series, DataFrame import numpy as np import matplotlib.pyplot as plt #seabornは簡単にきれいなグラフを書くためのモジュールです。 import seaborn as sns %matplotlib inline #ファイルを読み込み、データフレームを生成します。 lol_df = pd.read_csv('LoL.csv') #データフレームのwinデータをカウントプロットで見てみます。 sns.countplot('win',data = lol_df)
こんな感じで勝敗のデータが簡単にプロットできます。
データ解析「相関を見てみよう」
勝敗と関係ありそうなデータは、KDAや、与えたダメージ、オブジェクトへのダメージなどでしょうか。これを探るため、相関を見てみましょう。
相関とはデータ間の関連の強さを示す数値です。
相関係数は-1から1までの実数をとります。例えばassistの数と勝敗の相関をとったとき、
1, 相関係数が1に近ければ、assist数の多い試合で勝利していることになります。
2, 相関係数が-1に近ければ、assist数が少ない試合で勝利していることになります。
3, 相関係数の絶対値が0に近ければ、assist数と勝敗には関連性が無いといえます。
#Winを1、Loseを0とするように関数を作ります。 def f(data): if data == True: return 1 else: return 0 #データフレームのwinに対して上記の関数をapply()して、あらたなnumWinという列を追加します。 lol_df['numWin'] = lol_df['win'].apply(f) #データフレーム内の全データ間を総当り的に相関係数を求めます。 #corr()とするだけですので簡単です。 corr_df = lol_df.corr() #corr_dfのwinの列を見てみます。 corr_df.win
assists 0.330392 champLevel 0.150457 damageDealtToObjectives 0.570940 damageDealtToTurrets 0.583484 damageSelfMitigated -0.243319 deaths -0.450515 goldEarned 0.290285 goldSpent 0.137464 kills 0.224459 longestTimeSpentLiving 0.203687 magicDamageDealt 0.102760 magicDamageDealtToChampions 0.130534 magicalDamageTaken -0.278148 physicalDamageDealt 0.083411 physicalDamageDealtToChampions 0.018560 physicalDamageTaken -0.174446 totalDamageDealt 0.091768 totalDamageDealtToChampions 0.041253 totalDamageTaken -0.297823 totalMinionsKilled 0.074603 visionScore 0.187652 visionWardsBoughtInGame 0.082334 wardsPlaced 0.115123 win 1.000000 numWin 1.000000
勝敗と、その他データとの相関係数を見ることができました。
例えば、deathsとの相関は-0.450515ですから、physicalDamageTakenの-0.174446よりも、-1に近いです。これは、後者に比べてdeathsの少ない試合の方が勝敗に影響しているということです。
winとwinとの相関係数が1なのはあたりまえです。同じ数値なのですから。numWinも同様。
正直相関高いデータがない!
しいていうなら0.5くらいあるdamageDealtToObjectivesとdamageDealtToTurrets 、-0.5くらいのdeathsが有効なデータなのでしょうか。
ヒートマップでもうちょいみやすくしてみましょう。まぁ、この場合あまり見やすくはないんですが。
sns.heatmap(corr_df)
右端もしくは下端のデータがwinとそれぞれのデータとの相関係数です。1に近いほど赤く、-1に近いほど青く、0に近いほど白い。
マップの左上当たりに目を向けると、goldSpentとgoldEarnedとの相関は、色が濃くなっていますね。 似たような数値ですし当たり前ですね。
そのほかにchampLevelとgoldSpentの相関なんかも高いですね。これもイメージがわきますね。
このデータから何がわかるのか
さて、ではこのデータから何がわかるか。
相関係数から判断すると、オブジェクトにダメージをあたえることを優先してkillされなければ、勝率はあがる!しかしそういうわけではない!!
これはあくまで相関で、killされてない試合が勝率高いのかもしれませんが、killされてないから勝ててるとは言えません。勝ててるからkillされないのかもしれません。相関は因果関係ではありません。
オブジェクトダメージだって、そりゃ勝った試合はネクサスまで壊してるんだから、負けた試合に比べてダメージ量多いのは当たり前ですよね。
正直何もわかりませんでした。
結局これといって結論を出せませんでした。なるべくdeathを抑えるべきだということは何となくわかりましたが、あたりまえですよねそんなの。
lolがオブジェクトを奪うゲームだという裏付けには少し加担できているかもしれません。相手をkillするゲームではないってうまいプレイヤーさんは言いますよね。
今後どう進めていくか
さて、難しいですね。勝利の仕組みを解き明かす方法はないのでしょうか。 てか、ワードが全く相関ないのはびっくり。ある程度の数置かないと勝敗にかかわってこないのかな。それとも毎回同じくらいのワードしか置けてないってことなのかな。
改善点としては、
1, CSを見てないこと。
2, もっと時系列データに注目すること
こんくらいしか今思いついてません。 こんなデータに注目してみたら?とかあったらぜひコメントください。
読んでいただき、ありがとうございました。