データサイエンスでDota2強くなるかも説(7)~簡易解析/描画【Jsonファイル版】~

Dota2データサイエンス

はじめに

最近,Dota2を始めましたが全く勝てません
ハードボットにボコボコにされます.

色々と調べても「死ぬな」くらいのことしか分らず苦戦しています.

データサイエンスでDota2強くなるかも説

そこで,データサイエンスの力を借りて,どのような状況なら勝っているか?や前回に比べてどのように振舞ったから勝てたのか?ということを数値化して分析していけば強くなるのでは!と考えました.本企画はその仮説を検証していく企画です.

file

前回までのあらすじ

環境構築編

Dota2の情報をPythonで取得できるような環境を作成し*1,データを取得+定期的に保存する機構を作りました*2

データ解析~ミディアムとハード編~

実際にBotとの対戦をプロットしてみて客観的に解析してみたところ*3,ミディアムボットとの対戦をしてもハードボットとの対戦ではそこまで効果がない可能性が発見されました*4

データ解析~ハード編~

ハードボットとの対戦を解析してみた結果,勝利している方が敗北している試合よりもレベル,ゴールドを多く稼いでいると思っていたのですが,その仮説とは相反した結果が得られ味方の振る舞いの影響が大きく,自分の行動は勝利に直結していないという悲しい結果になりましたそこで,原点に立ち返って,環境データを考慮して解析をしてみようと思い,環境データを含むデータの取得機構を検討&実装していました*5..

そこで,原点に立ち返って,環境データを考慮して解析をしてみようと思い,環境データを含むデータの取得機構を検討&実装していました*6

今回の概要

今回は,前回取得したデータを整形し簡易的に描画するまでをやってみます.

準備

GSI環境

GSI環境が整っていることを確認しておいてください.
まだの方はこちらの記事参照

データサイエンスでDota2強くなるかも説(1)~環境設定~
Dota2の情報をPythonで取得するまでをやっていきます.

Dota2 解析プログラム

今回はログファイルを読み込んで簡易的に描画する処理までやっていきます.

Import

import glob
import pandas as pd
import json

import seaborn as sns
from matplotlib import pyplot as plt
import matplotlib as mpl

from tqdm.notebook import tqdm

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

ロガーの設定

from logging import getLogger, Formatter, StreamHandler, FileHandler, DEBUG, INFO

def get_module_logger(module):
    logger = getLogger(module)
    logger = _set_handler(logger, StreamHandler(), True)
    logger.setLevel(DEBUG)
    logger.propagate = False
    return logger

def _set_handler(logger, handler, verbose):
    if verbose:
        handler.setLevel(DEBUG)
    else:
        handler.setLevel(INFO)
    handler.setFormatter(Formatter('%(asctime)s %(name)s:%(lineno)s %(funcName)s [%(levelname)s]: %(message)s'))
    logger.addHandler(handler)
    return logger

logger = get_module_logger("Dota2Analysis")
logger.info('message')
    2022-09-10 22:13:04,229 Dota2Analysis:21 <cell line: 21> [INFO]: message
    2022-09-10 22:13:04,229 Dota2Analysis:21 <cell line: 21> [INFO]: message

seabornのテーマの設定

#sns.palplot(sns.color_palette("RdBu_r", 24))
#sns.set_palette("RdBu_r")
#sns.set(style='darkgrid')
#sns.set_style('whitegrid')
mpl.style.use('fivethirtyeight')

パラメータ設定

ここで,ログフォルダとログデータを整形した後の出力フォルダを指定します.

log_dir         = "logs"
datasets_dir    = "data"

ログフォルダ一覧の取得

data_file_list = glob.glob(log_dir + "/*")
data_file_list

各試合のフォルダを取得します.

    ['logs\\20220909_232301_W',
     'logs\\20220910_001319_W',
     'logs\\20220910_011144_W']

ログファイル一覧の取得

json_file_list = {}
for data_path in data_file_list:
    data_name = data_path.split("\\")[-1]
    json_file_list[data_name] = glob.glob(data_path + "/*json")

便利関数の定義

辞書から参照する関数

ログデータは辞書型で保存されており,さらに,深さも異なります.
そこで,深さを可変にできるような関数を定義します.

def get_json_value(json_data, *args):
    if(args[0] in json_data):
        if(args[1] in json_data[args[0]]):
            if(len(args)==2):
                target_data = json_data[args[0]][args[1]]
                return target_data

            if(args[2] in json_data[args[0]][args[1]]):
                if(len(args)==3):
                    target_data = json_data[args[0]][args[1]][args[2]]
                    return target_data

                if(args[3] in json_data[args[0]][args[1]][args[2]]):
                    if(len(args)==4):
                        target_data = json_data[args[0]][args[1]][args[2]][args[3]]
                        return target_data

    return -1

Jsonファイルの読み込み関数

全ファイルを走査するような形式になっています.


def get_json_data(json_file_list, *args):
    # print(">>>> args >>>>>>>>>")
    print(args)

    df_data_list = []

    df_data_all = pd.DataFrame({}, columns=["clock_time"])
    # # df_data_all.columns = ["clock_time"]

    for data_name in tqdm(json_file_list.keys()):
        file_list = json_file_list[data_name]

        target_name = "_".join(args) + "-" + data_name

        clock_time_list = []
        target_data_list = []

        for file_path in tqdm(file_list):

            with open(file_path) as f:
                json_data = json.load(f)

                clock_time = get_json_value(json_data, "map", "clock_time")
                # print(clock_time)
                clock_time_list.append(clock_time)

                target_data = get_json_value(json_data, *args)
                # print(target_data)
                target_data_list.append(target_data)

        df_data = pd.DataFrame([clock_time_list, target_data_list]).T
        df_data.columns = ["clock_time", target_name]

        # print(df_data)

        df_data_list.append(df_data)

    # df_data_merge = pd.concat(df_data_list, axis=1)
    for i in range(len(df_data_list)):
        df_data_all = pd.merge(df_data_all, df_data_list[i], on='clock_time', how='outer')

    # print(df_data_all)
    # print("---------------------")
    # print(df_data_all.columns)

    return df_data_all

簡易実装版

Levelデータの取得

json2df = get_json_data(json_file_list, "hero", "level")
# json2df = pd.merge(json2df , get_json_data(json_file_list, "hero", "health"), on='clock_time', how='outer')
json2df.to_csv(datasets_dir + "/hero_level.csv", index=False)
    >>>> args >>>>>>>>>
    ('hero', 'level')

      0%|          | 0/3 [00:00<?, ?it/s]

      0%|          | 0/2551 [00:00<?, ?it/s]

      0%|          | 0/1872 [00:00<?, ?it/s]

      0%|          | 0/1714 [00:00<?, ?it/s]

Levelデータの読み込み


hero_level = pd.read_csv(datasets_dir + "/hero_level.csv", index_col=0)
hero_level.head(5)
hero_level-20220909_232301_W hero_level-20220910_001319_W hero_level-20220910_011144_W
clock_time
-74 -1 -1.0 -1.0
-73 -1 -1.0 -1.0
-72 1 1.0 1.0
-71 1 1.0 1.0
-70 1 1.0 1.0

Levelデータの描画

plt.figure(figsize=(20,8))
sns.lineplot(data=hero_level, lw=2)

プログラム一式

GitHub - HamaruKi0303/Dota2-GSI-Science
Contribute to HamaruKi0303/Dota2-GSI-Science development by creating an account on GitHub.

おわりに

無事に簡易的に描画することまでできました.次回は,もう少し作りこんだ解析をしていきたいと思います.

参考サイト

コメント

タイトルとURLをコピーしました