硬核!宝可梦八大世代数据大揭秘

目标:利用Python对宝可梦八大世代做数据分析

一、各系数量分析

二、各世代宝可梦数量分析

三、种族值分析

四、传说宝可梦分析

五、各世代推荐宝可梦

六、特性分析:特性种类、隐藏特性种类、占比(待更新)


零、预备工作&指标解释

#导入三个Python常用数据分析的库

import numpy as np
import pandas as pd

#画图包导入
import matplotlib.pyplot as plt
plt.style.use(style="ggplot")
#import missingno as msno
import seaborn as sns
sns.set()    #设置画图空间为 Seaborn 默认风格

#将文件读取进来
pokemon = pd.read_excel("/Users/glenji/Desktop/pokemon (1).xlsx")


#指标解释
#abilities-1特性1,abilities-2特性2,abilities-x特性x
#classfication宝可梦分类、classfication-CN宝可梦中文分类
#type1属性1,type2属性2
#attack攻击
#defense防御
#hp血量
#sp_attack特攻
#sp_defense特防
#speed速度
#base_total种族值总数


一、各系数量分析

总结:以下分析仅为单系,双系的分析暂无。

各系中,水系、一般系、草系三个的数量比较多,其中水系占比13.56%,一般系占比12.02%,草系占比9.48%;

各系中,飞行系占比最少,仅0.37%(唯一一个低于1%的);


①各系的数量:先做个简单的计数统计,可以初步看到水系、一般系、草系三个的数量比较多。水系那么多,可能因为日本靠海,他们比较喜欢吃鱼吧哈哈哈。

#查看各系的数量

out = pokemon[['type1','is_legendary']].groupby('type1').count()
print(out)

②绘制一个柱形图来看看效果:

#柱形图查看各世代宝可梦不同种族数量

pokemon['type1-EN'].value_counts().plot.bar()


③绘制饼图看看效果:水系、一般系、草系为数量前三位,冰系、妖精系、飞行系为数量后三位,有点出乎意料,飞行系竟然是最少的,仅0.37%(唯一一个低于1%的)。水系占比13.56%,一般系占比12.02%,草系占比9.48%。

#查看各系的占比
#水系是最多的,为什么呢,可能是因为日本人靠海喜欢吃鱼吧哈哈哈

fig,ax = plt.subplots(2,1,figsize=(15,10))

pokemon['type1-EN'].value_counts().plot.pie(ax=ax[0],shadow=False,autopct='%1.2f%%')
ax[0].set_ylabel('')    #设置y轴标签
ax[0].set_xlabel('type1-EN')    #设置x轴标签

sns.countplot('type1-EN',data=pokemon,ax=ax[1])
ax[1].set_ylabel('')
ax[1].set_xlabel('type1-EN')
plt.show()



二、各世代宝可梦分析

总结:

第5世代是宝可梦数量最多的世代有156只,第6世代是宝可梦数量最少的世代,仅72只;


①先做个简单的计数统计(value_counts),可以看到第5世代是宝可梦数量最多的世代有156只,第一世代次之(第一世代的151手办现在已经很贵很贵很贵了);第6世代是宝可梦数量最少的世代,才72只。

#计算一下各世代的宝可梦数量

pokemon['generation'].value_counts()

②再画个柱形图看看效果:

#柱形图查看各世代宝可梦数量

pokemon['generation'].value_counts().plot.bar()



三、种族值解析

总结:

种族值6大属性中,血量hp的异常值较多;

整体种族值呈双峰分布,以300和500左右的分布较多;

龙系的种族值均值高达515,是最值得培育的种族,其次是钢系、超能力系;而虫系是最可怜的种族,平均种族值仅有378,草系、一般系也惨兮兮;

种族值均值为439,中位数是440,培育宝可梦如果在乎强度,那应该选择高于这两值的宝可梦,如果是真爱党的话,则无所谓了;


①绘制线箱图查看各种族值的大致情况:可以看到hp即血量的异常值较多。

#绘制线箱图
#可以看到hp的异常值较多

plt.figure(figsize=(10,5))    #设置画布大小
sns.boxplot(data=pokemon[['hp','attack','defense','sp_attack','sp_defense','speed']])


②查看种族值的分布图:有点类似双峰分布,最多种族值分布在300和500附近。之前世代种族值最高的是800左右,第八世代出了个无极汰那极巨化一下子将种族值上限提高到1000以上。

#种族值分布

plt.hist(pokemon['base_total'],bins=35)
plt.xlabel('total_stats')
plt.ylabel('Frequency')


③通过小提琴图观察各个种族的种族值特性:可以看到龙系的整体种族值是相对较高的。

#psychic超能力
#bug虫系
#fairy妖精系

#通过小提琴的厚度显示的分布
sns.set_style('whitegrid')

#小提琴图
plt.figure(figsize=(15,5))    #设置画布大小
sns.violinplot(x='type1-EN',y='base_total',data=pokemon)


④通过数据透视表,了解完整的各种族的平均种族值情况,得出什么种族是最值得培育的:得到的结论是龙系的种族值均值高达515,是最值得培育的种族,其次是钢系、超能力系;而虫系是最可怜的种族,平均种族值仅有378,草系、一般系也惨兮兮。

#建立数据透视表
#计算一下各系宝可梦种族值分布
#新建一个数据表格,用于保存世代generation与是否传说is_legendary两列数据

pokemon2=pokemon[['type1','base_total']]


pokemon_z=pokemon2.pivot_table(values='base_total',    #计算的值
                               index='type1',       #透视的行,分组的依据
                               aggfunc='mean')            #聚合函数

# 对透视表进行降序排列
pokemon_z = pokemon_z.sort_values(by='base_total',     # 排序依据
                        ascending=False                 # 是否升序排列
                       )

pokemon_z


⑤再看看各系种族值的描述型数据统计:种族值均值为439,中位数是440,各位小伙伴,低于这俩值的宝可梦你要是培育的话,那就真的是真爱了。

#各系种族值得描述性数据情况

pokemon_z.describe()


⑥推荐一些培育性价比比较高的宝可梦:种族值高于570,但非传说宝可梦的准神。

#找到非传说宝可梦但是种族值非常优秀,值得培育的宝可梦

pokemon[(pokemon['base_total'] >= 570) & (pokemon.is_legendary == 0)]['chinese_name'].head(100)


⑦还可以绘制一些种族值之间的关系图:可以看到attack和defense基本呈正相关,其他的你也可以再试试。

#查看HP和Attack的相关性

import scipy.stats as stats
from warnings import filterwarnings
filterwarnings('ignore')

sns.jointplot(x='defense',y='attack',data=pokemon).annotate(stats.pearsonr)
plt.show()



四、传说宝可梦分析

总结:

传说宝可梦最多的是第7世代,一共有25只,占比28%;最少的是第1世代,只有5只,占比3%;

越往后的世代传说宝可梦倾向于越多;

特攻值与是否为传说宝可梦相关度最高,而防御与是否为传说宝可梦的相关度最低;

传说宝可梦的种族值平均高达611,而非传说宝可梦的种族值平均为410;

种族与是否为传说宝可梦没有很强的相关性,相对来说超能力系psychic、龙系dragon是传说宝可梦的概率较高;


①通过数据透视表统计一下各世代传说宝可梦数量:可以看到传说宝可梦最多的是第7世代,一共有25只;最少的是第1世代,只有5只;有个比较明显的趋势是越往后的世代传说宝可梦倾向于越多。

#新建一个数据表格,用于保存世代generation与是否传说is_legendary两列数据
pokemon1=pokemon[['generation','is_legendary']]


#建立数据透视表
pokemon_p=pokemon1.pivot_table(values='is_legendary',    #计算的值
                               index='generation',       #透视的行,分组的依据
                               aggfunc='sum')            #聚合函数

pokemon_p


②对数据透视表进行数值降序排列:可以更明显的看清楚各世代传说宝可梦的数量排列。

# 对透视表进行降序排列
pokemon_p = pokemon_p.sort_values(by='is_legendary',     # 排序依据
                        ascending=False                 # 是否升序排列
                       )
pokemon_p


③对新的透视结果做折线图展示:

#对新的透视结果做折线图展示

x=[1,2,3,4,5,6,7,8]
y=pokemon_p['is_legendary']

plt.plot(x,y)
plt.show()


④各世代宝可梦数量及传说宝可梦对比图:

#查看各世代宝可梦数量

f,ax=plt.subplots(1,2,figsize=(18,5))    #新建画布
pokemon['generation'].value_counts().plot.bar(ax=ax[0])   #绘制世代宝可梦数量柱形图
ax[0].set_ylabel('countS')    #设置y轴标签
ax[0].set_title('Generation')    #设置x轴标签
sns.countplot('generation',hue='is_legendary',data=pokemon,ax=ax[1])    #绘制世代传说宝可梦数量对比柱形图
ax[1].set_title('Legendary VS Generation')    #设置标题
plt.show()


⑤计算各世代传说宝可梦占比:通过数据透视表操作。

#计算一下各世代传说宝可梦数量
#新建一个数据表格,用于保存世代generation与是否传说is_legendary两列数据

pokemon1=pokemon[['generation','is_legendary','pokedex_number']]

#建立数据透视表

pokemon_p=pokemon1.pivot_table(values='is_legendary',    #计算的值
                               index='generation',       #透视的行,分组的依据
                               aggfunc='sum')            #聚合函数

pokemon_q=pokemon1.pivot_table(values='pokedex_number',    #计算的值
                               index='generation',       #透视的行,分组的依据
                               aggfunc='count')            #聚合函数

pokemon_w = pd.concat([pokemon_p,pokemon_q],axis=1)    #用concat将两个表格连在一起
pokemon_w


可以看到第7世代的传说宝可梦占比最高,达到28%;而第1世代是最低的,只有3%。

#计算一下各世代传说宝可梦占比

pokemon_c = pokemon_w['is_legendary']/pokemon_w['pokedex_number']
pokemon_c


⑥查看6大能力值与是否传说、世代的相关关系:先用相关关系矩阵查看效果。

#查看六大能力值与是否传说、世代的相关关系

pokemonNew = pokemon[['hp','attack','defense','sp_attack','sp_defense','speed','generation','is_legendary']]

pokemonNewCorr=pokemonNew.corr()
                     
plt.figure(figsize=(10,10))    #设置画布
sns.heatmap(pokemonNewCorr,annot=True,cmap='RdGy')
plt.show()


查看各个能力值与是否为传说宝可梦的相关性排序:得到的结论是特攻值与是否为传说宝可梦相关度最高,也就是说传说宝可梦的特攻属性值一般是较高的。而防御与是否为传说宝可梦的相关度最低。

#查看各个特征与是否为传说宝可梦的相关性排序

pokemonNewCorr['is_legendary'].sort_values(ascending=False)


⑦传说宝可梦的平均种族值:传说宝可梦的种族值平均高达611,而非传说宝可梦的种族值平均为410。

pokemonchuanshuo = pokemon[['base_total','is_legendary']]    #先将种族值和是否传说两列数据取出

pokemonchuanshuo1=pokemonchuanshuo.pivot_table(values='base_total',    #计算的值
                               index='is_legendary',       #透视的行,分组的依据
                               aggfunc='mean')            #聚合函数

# 对透视表进行降序排列
pokemonchuanshuo1 = pokemonchuanshuo1.sort_values(by='base_total',     # 排序依据
                        ascending=False                 # 是否升序排列
                       )

pokemonchuanshuo1


⑧分析不同种族与传说宝可梦的相关关系:得出的结论是种族与是否为传说宝可梦没有很强的相关性,相对来说超能力系、龙系是传说宝可梦的概率较高。

#将种族type1做转码

type1Df = pd.DataFrame()    #存放提取后的特征
type1Df = pd.get_dummies(pokemon['type1'],prefix='type1')    #使用get_dummies进行one-hot编码,列名前缀是Embarked
type1Df.head(10)

#将转码后的数据连接到原来的数据表格

pokemon = pd.concat([pokemon,type1Df],axis=1)    #添加one-hot编码产生的虚拟变量(dummy variable)到pokemon中
pokemon.head()

#查看不同种族与是否传说、世代的相关关系

pokemonNew = pokemon[
    ['type1_Bug',
     'type1_Dark',
     'type1_Dragon',
     'type1_Electric',
     'type1_Fairy',
     'type1_Fighting',
     'type1_Fire',
     'type1_Flying',
     'type1_Ghost',
     'type1_Grass',
     'type1_Ground',
     'type1_Ice',
     'type1_Normal',
     'type1_Poison',
     'type1_Psychic',
     'type1_Rock',
     'type1_Steel',
     'type1_Water',
     'generation',
     'is_legendary']
]

pokemonNewCorr1=pokemonNew.corr()
                     
plt.figure(figsize=(20,20))    #设置画布
sns.heatmap(pokemonNewCorr1,annot=True,cmap='Blues')
plt.show()


#查看各个种族与是否为传说宝可梦的相关性排序

pokemonNewCorr1['is_legendary'].sort_values(ascending=False)


五、各世代推荐宝可梦

# 能力测评   属性值加起来×base_total
def ability_value(x, output_number):
    
    pokemon = x.copy()

    pokemon = pokemon[pokemon.is_legendary == 0] #因为是平民策略,把神兽都排除掉

    Xlist = []   # Xlist 是所有feature name,也就是宝可梦的所有属性名
    for line in pokemon:
        row = line.strip().split(",")
        Xlist.append(row)

    against_data = pokemon[Xlist[1]]
    Xlist = np.array(Xlist)
    for i in range(2, 18):
        # against_data 为所有的against_??权值加起来的总和,和战斗力成正相关
        against_data = against_data + np.array(pokemon[Xlist[i]])


    base_total_value = pokemon["base_total"]
    battle_value = against_data.mul(base_total_value, axis=0)

    rank_value = battle_value.sort_values(by=['against_bug'], ascending=False, na_position='first')
    rank_number = rank_value.axes[0].tolist()
    for i in range(0, output_number):
        print("【name】:  ", pokemon.chinese_name[rank_number[i]], " 【base total】: ", pokemon.base_total[rank_number[i]])
    return 0


def type_prefer(x):
    
    pokemon = x.copy()
    type_total = pokemon.type1.drop_duplicates(keep='first')
    type_total.reset_index(drop=True, inplace=True)

    for typenum in range(0, len(type_total)):
        each_type_pokemon1 = pokemon.loc[pokemon['type1'] == type_total[typenum]]
        each_type_pokemon2 = pokemon.loc[pokemon['type2'] == type_total[typenum]]
        each_type_pokemon = each_type_pokemon1.append(each_type_pokemon2)
        print("type name: ", type_total[typenum])
        ability_value(each_type_pokemon, 3)  # 每种属性输出最牛逼的3个
        print("------------------")


# 从培养难度考虑,培养经验值除以捕捉率,再乘以能力值,全部标准化
def training_hard_level(x, output_number):
    
    pokemon = x.copy()

    pokemon = pokemon[pokemon.is_legendary == 0]  # 因为是平民策略,把神兽都排除掉

    # monitor的捕捉率按255算,因为反正能力值都一样,算好抓的
    pokemon.capture_rate[773] = 255
    pokemon.capture_rate = pd.to_numeric(pokemon.capture_rate)

    normalization_base_total = (pokemon.base_total - pokemon.base_total.min()) / (
                pokemon.base_total.max() - pokemon.base_total.min())
    normalization_capture_rate = (pokemon.capture_rate - pokemon.capture_rate.min()) / (
                pokemon.capture_rate.max() - pokemon.capture_rate.min())
    normalization_experience_growth = (pokemon.experience_growth - pokemon.experience_growth.min()) / (
                pokemon.experience_growth.max() - pokemon.experience_growth.min())

    Difficulty_level = normalization_experience_growth / normalization_capture_rate * normalization_base_total
    Difficulty_level = Difficulty_level.sort_values(ascending=False, na_position='first')

    rank_number = Difficulty_level.axes[0].tolist()
    for i in range(0, output_number):
        print("【name】:  ", pokemon.chinese_name[rank_number[i]], " 【base total】: ", pokemon.base_total[rank_number[i]])
    return 0


if __name__ == '__main__':
    pokemon_Data = pd.read_excel("/Users/glenji/Desktop/pokemon.xlsx")
    # 首先要确定是哪一代的游戏 1-7代
    Xlist = []
    for line in pokemon_Data:
        row = line.strip().split(",")
        Xlist.append(row)

    generation_1 = pokemon_Data.iloc[0:151]
    generation_2 = pokemon_Data.iloc[0:251]
    generation_3 = pokemon_Data.iloc[0:386]
    generation_4 = pokemon_Data.iloc[0:493]
    generation_5 = pokemon_Data.iloc[0:649]
    generation_6 = pokemon_Data.iloc[0:721]
    generation_7 = pokemon_Data.iloc[0:801]

    print("以第2代为例:")
    print("===============纯从能力值考虑,前十名的宝可梦有:==================")
    ability_value(generation_2,10)
    print("==============考虑捕捉+训练难度,前十名的宝可梦有:===============")
    training_hard_level(generation_2, 10)
    print("============考虑属性多样爱好者,每个属性的前三甲宝可梦有:===========")
    type_prefer(generation_3)

展开阅读全文

页面更新:2024-05-18

标签:世代   数据   画布   水系   相关性   种族   透视   排列   属性   数量

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top