[PYTHON] Pokemon x Data Science (2) --Trial version of thinking about party construction of Pokemon sword shield from network analysis

-Pokemon x Data Science (1) --I analyzed the rank battle data of Pokemon Sword Shield and visualized it on Tableau -[This time] Pokemon x Data Science (2) --Trial version of thinking about party construction of Pokemon sword shield from network analysis -Pokemon x Data Science (3) --Thinking about party construction of Pokemon sword shield from network analysis Where is the center of the network

Hello, is about the continued visualization of Pokemon in the previous article](https://qiita.com/b_aka/items/7d2b768dfa7817f34fc2).

It is no exaggeration to say that in a Pokemon battle environment, how to build a party is the key, and that determines the outcome.

This time, when thinking about building the party, I would like to use the power of the network to understand the relationship between Pokemon.

The full code is from here

Data import

For the data, we will use the ranking ALL_SEASON_TEMOTI_POKEMON.csv that was adopted together with the data created in the previous article. (* It will be created automatically when you execute main.py of here.)

The path to this data

file_path = 'ALL_SEASON_TEMOTI_POKEMON.Path to csv'

Then, define the following function

import pandas as pd

def make_edge_list(file_path):
    df = pd.read_csv(file_path, encoding='utf-8')
    df = df.groupby(['Pokemon','Pokemon with a high combination rate'])['Rank_Pokemon with a high combination rate'].mean()
    df = pd.DataFrame(df).reset_index()
    df.columns = ['From', 'To', 'Weight']
    df['Weight'] = 10-df['Weight']
    return df

Run!

network = make_edge_list(file_path)

If you can get the following data, you are successful. Since a directed graph (with orientation at the edge) is drawn, the start and end points of the node and the weight of the edge are the minimum required. This time, a certain Pokemon is the start point of the edge (From), the Pokemon that is often adopted together is the end point of the edge (To), and the weight of the edge is the reciprocal of the average rank.

From To Weights
Durant Achilleine 6.60
Durant Yessan 3.00
Durant Windy 4.22
... ... ...

35732 rows × 3 columns

Data processing

If you throw this data into the network as it is, it will be difficult because there are too many nodes and edges (it will be extremely difficult to visualize while the calculation time is gone), so narrow down the data. Hurry Save the recruitment ranking in Season 12 as csv with the following code.

import urllib.request
import json
import datetime

def make_pokemon_rank(ids):
    for season_number in ids['list'].keys():
        for  season_id in ids['list'][season_number].keys():
            rst = ids['list'][season_number][season_id]['rst']
            ts2 = ids['list'][season_number][season_id]['ts2']
            url = f'https://resource.pokemon-home.com/battledata/ranking/{season_id}/{rst}/{ts2}/pokemon'
            file_name = f'Season{season_number}_{"Single" if season_id[4]=="1" else "Double"}_Recruitment rate ranking.json'
            if get_response_pokemon_rank(url, file_name):
                with open('log', 'a') as f:
                    print(f'{datetime.datetime.now()} | Generated: {file_name}', file=f)

def get_response_pokemon_rank(url, file_name):
    try:
        with urllib.request.urlopen(url) as response:
            body = json.loads(response.read())
            with open(f'{file_name}', 'w') as f:
                json.dump(body, f, indent=4)  
        return True
    except urllib.error.URLError as e:
        print(e.reason)
        return False

def translate_pokemion_name(num, form):
    if num == 876:
        if form == 0:
            name = "Yessan ♂"
        else: 
            name = "Yessan ♀"
    elif num == 479:
        if form == 0:
            name = "Rotom (default)"
        elif form == 1:
            name = "Rotom (Tue)"
        elif form == 2:
            name = "Rotom (Wednesday)"
        elif form == 3:
            name = "Rotom (ice)"
        elif form == 4:
            name = "Rotom (flying)"
        elif form == 5:
            name = "Rotom (grass)"
    else:
        name = pokedex['poke'][int(num) -1]
    return name

Datachunk \ IDs.json in this repository -transformer / blob / main / datachunk / IDs.json) and [datachunk \ bundle.json](https://github.com/moxak/pokemon-rankbattle-data-transformer/blob/main/datachunk/bundle. Load json).

ids = "";
with open('.//datachunk//IDs.json', 'r', encoding='utf-8') as json_open:
    ids = json.load(json_open)

pokedex = "";
with open('.//datachunk//bundle.json', 'r', encoding='utf-8') as json_open:
    pokedex = json.load(json_open)

Do the following to get ranking data for seasons 1-12.

make_pokemon_rank(ids)

Transform the adoption rate ranking from json to csv.

season_num = 12
rule = 'Single'
with open(f'Season{season_num}_{rule}_Recruitment rate ranking.json', 'r', encoding='utf-8') as json_open:
    data = json.load(json_open)

seasons = []
rules = []
pokemons = []
ranks = []
for index, pokemon in enumerate(data):
    seasons += [season_num]
    rules += [rule]
    pokemons += [translate_pokemion_name(pokemon['id'], pokemon['form'])]
    ranks += [index+1]
df_a = pd.DataFrame(data=[seasons, rules, pokemons, ranks]).T
df_a.columns = ['Season', 'Rule', 'Pokemon', 'Rank']
df_a.to_csv(f'Season{season_num}_{rule}_Ado_Rank.csv', index=False)

After that, we will read this data and narrow down to the top 150 in the recruitment rate ranking as of season 12.

top150_list = list(df_a['Pokemon'])

network_top150 = network[network['From'].isin(top150_list[:150])]
network_top150 = network_top150[network_top150['To'].isin(top150_list[:150])]

Visualization with Networkx

Please refer to here for how to operate Networkx in Python.

import matplotlib.pyplot as plt
import networkx as nx
plt.rcParams['font.family'] = 'IPAexGothic'

network_np = network_top150.values
G = nx.DiGraph()
G.add_weighted_edges_from(network_np)
pos=nx.spring_layout(G)
fig = plt.figure(figsize=(40, 40), dpi=100,facecolor='w', linewidth=0, edgecolor='w')
nx.draw_networkx(G,pos,font_size=16,font_family='IPAexGothic')
fig.show()

networkx.png

I can't read anything ... crying

The number of node edges is tremendous, and spring_layout (), which makes the Networkx graph "good", seems to be incompatible with this dataset.

It seems that it will change if you play with the attributes related to Networkx drawing, but in any case, I felt that there was a limit to visualizing the network with python, so I will try Cytoscape.

Visualization with Cytoscape

Then try Cytoscape.

This article describes how to use Cytoscape in great detail.

First, read the data. Execute the following code to output the file.

make_edge_list(file_path).to_csv("FILE-NAME.csv", index = False)

Start Cytoscape and import the csv file output earlier from file> import> Network from File in the upper left.

スクリーンショット2020-11-05021410.png

You should see a screen like the one below. Since this is a directed graph, I will specify what each node means. Since From is the node that is the start point of the edge, Source Node, and To is the node that is the end point of the edge, so Target Node and Weight are the weights of the edge, so they are called Edge Attribute.

スクリーンショット2020-11-05021707.png

When I played around with the top tab Layout and the left tab Style, I got something very close to what I was looking for.

You can see that the battle environment revolves around Aceburn, Patch Ragon, Drapart, and Togekiss, which are near the center of the graph and have many edges extended.

tableau_viz_test.csv1.png

Cytoscape supports interactive operations such as moving nodes by dragging, and it is very good that you can perform intuitive trial and error in that you can perform various operations such as changing styles with GUI operations.

Next time, I would like to analyze using this network. See you again.

Source

-I analyzed the rank battle data of Pokemon sword shield and visualized it on Tableau --Qiita -[Python] Summary of basic usage of NetworkX 2.0 --Qiita -Visualize railway line data as a graph with Cytoscape 3

© 2020 Pokémon © 1995-2020 Nintendo / Creatures Inc./GAME FREAK inc. Pokemon, Pokemon, and Pokémon are registered trademarks of Nintendo, Creatures, and Game Freak.

Recommended Posts

Pokemon x Data Science (2) --Trial version of thinking about party construction of Pokemon sword shield from network analysis
Pokemon x Data Science (3) --Thinking about Pokemon Sword Shield Party Construction from Network Analysis Where is the center of the network?