-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
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
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])]
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()
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.
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.
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
.
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.
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.
-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.