我收集了一个大型的口袋妖怪数据集,我的目标是根据我构建的比率确定"前 10 名团队" -口袋妖怪 BST(基础统计总数(:平均弱点。对于那些关心的人,我将平均弱点计算为口袋妖怪对每种类型的弱点之和(0.25 飞行 + 1 水 + 2 钢铁 + 4 火焰等(,然后将其除以 18(游戏中可用的类型总数(。
举个简单的例子 - 以下三个口袋妖怪的团队:Kingler,Mimikyu,Magnezone将产生1604.1365384615383的团队比例。
由于数据将用于竞技游戏,因此我删除了所有未完全进化的口袋妖怪以及传奇/神话口袋妖怪。 这是我到目前为止的过程:
- 创建完全进化的口袋妖怪团队的所有可能组合的集合
- 使用 for 循环遍历每个组合
- 前 10 种组合将自动添加到列表中
- 从第 11 个组合开始,我将当前团队迭代添加到列表中,按降序对列表进行排序,然后删除比率最低的团队。这可确保每次迭代后仅保留前 10 名。
显然,这个过程将需要很长时间才能运行。我想知道是否有更有效的方法来运行它。最后,请参阅下面的代码:
import itertools
import pandas as pd
df = pd.read_csv("Downloads/pokemon.csv") # read in csv of fully-evolved Pokemon data
# list(df) # list of df column names - useful to see what data has been collected
df = df[df["is_legendary"] == 0] # remove legendary pokemon - many legendaries are allowed in competitive play
df = df[['abilities', # trim df to contain only the columns we care about
'against_bug',
'against_dark',
'against_dragon',
'against_electric',
'against_fairy',
'against_fight',
'against_fire',
'against_flying',
'against_ghost',
'against_grass',
'against_ground',
'against_ice',
'against_normal',
'against_poison',
'against_psychic',
'against_rock',
'against_steel',
'against_water',
'attack',
'defense',
'hp',
'name',
'sp_attack',
'sp_defense',
'speed',
'type1',
'type2']]
df["bst"] = df["hp"] + df["attack"] + df["defense"] + df["sp_attack"] + df["sp_defense"] + df["speed"] # calculate BSTs
df['average_weakness'] = (df['against_bug'] # calculates a Pokemon's 'average weakness' to other types
+ df['against_dark']
+ df['against_dragon']
+ df['against_electric']
+ df['against_fairy']
+ df['against_fight']
+ df['against_fire']
+ df['against_flying']
+ df['against_ghost']
+ df['against_grass']
+ df['against_ground']
+ df['against_ice']
+ df['against_normal']
+ df['against_poison']
+ df['against_psychic']
+ df['against_rock']
+ df['against_steel']
+ df['against_water']) / 18
df['bst-weakness-ratio'] = df['bst'] / df['average_weakness'] # ratio of BST:avg weakness - the higher the better
names = df["name"] # pull out list of all names for creating combinations
combinations = itertools.combinations(names, 6) # create all possible combinations of 6 pokemon teams
top_10_teams = [] # list for storing top 10 teams
for x in combinations:
ratio = sum(df.loc[df['name'].isin(x)]['bst-weakness-ratio']) # pull out sum of team's ratio
if(len(top_10_teams) != 10):
top_10_teams.append((x, ratio)) # first 10 teams will automatically populate list
else:
top_10_teams.append((x, ratio)) # add team to list
top_10_teams.sort(key=lambda x:x[1], reverse=True) # sort list by descending ratios
del top_10_teams[-1] # drop team with the lowest ratio - only top 10 remain in list
top_10_teams
在您的示例中,每个口袋妖怪都有一个bst_weakness比率,对于团队价值的计算,您没有考虑到成员相互抵消弱点,而是简单地总结 6 名成员的比例?如果是这样,最好的团队不应该是拥有 6 个最佳个人口袋妖怪的团队吗?我不明白为什么你需要在你的情况下组合。
尽管如此,我想您可以在进入组合学之前从列表中删除很多口袋妖怪。 如果你有一个布尔数组(n_pokemons,n_types(指示每个口袋妖怪的弱点,你可以检查是否有一个口袋妖怪具有相同的弱点,但更好的bst值。
# Loop over all pokemon and check if there are other pokemon
# ... with the exact same weaknesses but better stats
# -name -weaknesses -bst
# pokemon A [0, 0, 1, 1, 0, ...], bst=34.85 -> delete A
# pokemon B [0, 0, 1, 1, 0, ...], bst=43.58
# ... with a subset of the weaknesses and better stats
# pokemon A [0, 0, 1, 1, 0, ...], bst=34.85 -> delete A
# pokemon B [0, 0, 1, 0, 0, ...], bst=43.58
我用numpy写了一个小片段。bst 的值和弱点是 随机选择。使用我的设置
n_pokemons = 1000
n_types = 18
n_min_weaknesses = 1 # number of minimal and maximal weaknesses for each Pokemon
n_max_weaknesses = 4
列表中只剩下大约 30-40 只口袋妖怪。我不确定这对于"真正的"口袋妖怪来说有多合理,但有了这样的数字,组合搜索就更可行了。
import numpy as np
# Generate pokemons
name_arr = np.array(['pikabra_{}'.format(i) for i in range(n_pokemons)])
# Random stats
bst_arr = np.random.random(n_pokemons) * 100
# Random weaknesses
weakness_array = np.zeros((n_pokemons, n_types), dtype=bool) # bool array indicating the weak types of each pokemon
for i in range(n_pokemons):
rnd_weaknesses = np.random.choice(np.arange(n_types), np.random.randint(n_min_weaknesses, n_max_weaknesses+1))
weakness_array[i, rnd_weaknesses] = True
# Remove unnecessary pokemons
i = 0
while i < n_pokemons:
j = i + 1
while j < n_pokemons:
del_idx = None
combined_weaknesses = np.logical_or(weakness_array[i], weakness_array[j])
if np.all(weakness_array[i] == weakness_array[j]):
if bst_arr[j] < bst_arr[i]:
del_idx = i
else:
del_idx = j
elif np.all(combined_weaknesses == weakness_array[i]) and bst_arr[j] < bst_arr[i]:
del_idx = i
elif np.all(combined_weaknesses == weakness_array[j]) and bst_arr[i] < bst_arr[j]:
del_idx = j
if del_idx is not None:
name_arr = np.delete(name_arr, del_idx, axis=0)
bst_arr = np.delete(bst_arr, del_idx, axis=0)
weakness_array = np.delete(weakness_array, del_idx, axis=0)
n_pokemons -= 1
if del_idx == i:
i -= 1
break
else:
j -= 1
j += 1
i += 1
print(n_pokemons)