tynbl.github.io

实战案例3:宠物小精灵数据分析及展示

1. 项目描述:

精灵宝可梦系列是一套由日本GAME FREAK代表田尻智一同于1995年开发,日本任天堂株式会社于1996年推出的一款Game Boy(任天堂所推出之掌上型游戏机)游戏,其后发展为跨媒体制作的作品。

由于其独特的游戏系统广受大众的欢迎,年度产品销量近千万(红、绿二版本合计。全系列作目前累积已破亿)。任天堂趁此热潮,推出后续的一系列游戏、漫画、书籍、对战卡片及周边产品,还联合日本东京电视台推出电视动画,以及一年一度的剧场版动画电影,更在1998年成功进军美国,并拓展至世界各地(除了少数地方因为宗教等因素)。这套作品已成功打入全世界数十个国家,成为世界闻名的卡通形象和日本的国民动画。相关产品销售额达数十亿美元以上。因为各部分的成长,目前精灵宝可梦相关事业已经独立成一公司:精灵宝可梦股份有限公司(株式会社ポケモン),为任天堂旗下的子公司之一。

精灵宝可梦作品包括游戏、动画、漫画、卡片游戏及相关产品。宝可梦同时也是宝可梦世界所有虚构出来的物种所拥有的共同的名字。截至2017年10月,全系列的宝可梦共有805种。

基于此,我们可以对Pokémon的数据/变量进行统计分析,并从中发掘他们之间的关系,用可视化的方式进行直观的查看。

2. 数据集描述:

3. 项目任务:

4. 项目实现:

# 引入必要的包
import csv
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib notebook
# 解决matplotlib显示中文问题
# 仅适用于Windows
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

# MacOS请参考 http://wenda.chinahadoop.cn/question/5304 修改字体配置
# 指定数据集路径
dataset_path = '../data'
pokemon_datafile = os.path.join(dataset_path, 'pokemon.csv')
pokemon_data = pd.read_csv(pokemon_datafile)
pokemon_data.head()
Number Name Type_1 Type_2 Total HP Attack Defense Sp_Atk Sp_Def ... Color hasGender Pr_Male Egg_Group_1 Egg_Group_2 hasMegaEvolution Height_m Weight_kg Catch_Rate Body_Style
0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 ... Green True 0.875 Monster Grass False 0.71 6.9 45 quadruped
1 2 Ivysaur Grass Poison 405 60 62 63 80 80 ... Green True 0.875 Monster Grass False 0.99 13.0 45 quadruped
2 3 Venusaur Grass Poison 525 80 82 83 100 100 ... Green True 0.875 Monster Grass True 2.01 100.0 45 quadruped
3 4 Charmander Fire NaN 309 39 52 43 60 50 ... Red True 0.875 Monster Dragon False 0.61 8.5 45 bipedal_tailed
4 5 Charmeleon Fire NaN 405 58 64 58 80 65 ... Red True 0.875 Monster Dragon False 1.09 19.0 45 bipedal_tailed

5 rows × 23 columns

4.1 单变量分析

plt.figure(figsize=(10, 5))
# Type_1 的数量统计图
ax1 = plt.subplot(1, 2, 1)
sns.countplot(x='Type_1', data=pokemon_data)

plt.title('主要类别的数量统计')
plt.xticks(rotation='vertical')
plt.xlabel('主要类别')
plt.ylabel('数量')

# Type_2 的数量统计图
plt.subplot(1, 2, 2, sharey=ax1)
sns.countplot(x='Type_2', data=pokemon_data)

plt.title('副类别的数量统计')
plt.xticks(rotation='vertical')
plt.xlabel('副类别')
plt.ylabel('数量')

plt.tight_layout()
<IPython.core.display.Javascript object>

plt.figure(figsize=(10, 5))
# Egg_Group_1 的数量统计图
ax1 = plt.subplot(1, 2, 1)
sns.countplot(x='Egg_Group_1', data=pokemon_data)

plt.title('蛋群分组1的数量统计')
plt.xticks(rotation=60)
plt.xlabel('蛋群分组1')
plt.ylabel('数量')

# Egg_Group_2 的数量统计图
plt.subplot(1, 2, 2, sharey=ax1)
sns.countplot(x='Egg_Group_2', data=pokemon_data)

plt.title('蛋群分组2的数量统计')
plt.xticks(rotation=60)
plt.xlabel('蛋群分组2')
plt.ylabel('数量')

plt.tight_layout()
<IPython.core.display.Javascript object>

# 其余单变量数量统计

plt.figure(figsize=(10, 5))
# isLegendary 的数量统计图
ax1 = plt.subplot(2, 3, 1)
sns.countplot(x='isLegendary', data=pokemon_data)
plt.title('是否为传说类型的数量统计')
plt.xlabel('是否为“传说”')
plt.ylabel('数量')

# hasGender 的数量统计图
plt.subplot(2, 3, 2, sharey=ax1)
sns.countplot(x='hasGender', data=pokemon_data)
plt.title('是否有性别的数量统计')
plt.xlabel('是否有性别')
plt.ylabel('数量')

# hasMegaEvolution 的数量统计图
plt.subplot(2, 3, 3, sharey=ax1)
sns.countplot(x='hasMegaEvolution', data=pokemon_data)
plt.title('是否有Mega进化的数量统计')
plt.xlabel('是否有Mega进化')
plt.ylabel('数量')

# 颜色 的数量统计图
plt.subplot(2, 3, 4)
sns.countplot(x='Color', data=pokemon_data)
plt.xticks(rotation=60)
plt.title('颜色的数量统计')
plt.xlabel('颜色')
plt.ylabel('数量')

# 身形 的数量统计图
plt.subplot(2, 3, 5)
sns.countplot(x='Body_Style', data=pokemon_data)
plt.xticks(rotation=90)
plt.title('身形的数量统计')
plt.xlabel('身形')
plt.ylabel('数量')

# 第n代 的数量统计图
plt.subplot(2, 3, 6)
sns.countplot(x='Generation', data=pokemon_data)
plt.title('第n代的数量统计')
plt.xlabel('第n代')
plt.ylabel('数量')

plt.tight_layout()
<IPython.core.display.Javascript object>

# 数值型数据分布统计
plt.figure(figsize=(10, 5))

numeric_cols = ['Total', 'HP', 'Attack', 'Defense', 'Sp_Atk', 'Sp_Def', 'Speed', 'Pr_Male', 'Height_m', 'Weight_kg', 'Catch_Rate']

for i in range(len(numeric_cols)):
    plt.subplot(4, 3, i + 1)
    sns.distplot(pokemon_data[numeric_cols[i]].dropna())
    plt.xlabel(numeric_cols[i])
    
plt.tight_layout()
<IPython.core.display.Javascript object>

4.2 变量间关系分析

plt.figure()
sns.pairplot(pokemon_data.dropna(), vars=numeric_cols, size=1)
<IPython.core.display.Javascript object>

<seaborn.axisgrid.PairGrid at 0x1ba66c50>
# 计算变量间的相关系数,观察变量间的关系
corr_df = pokemon_data[numeric_cols].corr()
corr_df
Total HP Attack Defense Sp_Atk Sp_Def Speed Pr_Male Height_m Weight_kg Catch_Rate
Total 1.000000 0.642628 0.704164 0.605831 0.723737 0.706501 0.548890 0.113564 0.526813 0.535966 -0.738280
HP 0.642628 1.000000 0.431680 0.228834 0.368640 0.376006 0.170031 -0.066704 0.442872 0.431320 -0.478725
Attack 0.704164 0.431680 1.000000 0.433233 0.335205 0.207211 0.335013 0.213882 0.408590 0.469395 -0.525106
Defense 0.605831 0.228834 0.433233 1.000000 0.202519 0.483986 -0.008663 0.063899 0.354205 0.476983 -0.436558
Sp_Atk 0.723737 0.368640 0.335205 0.202519 1.000000 0.492861 0.443106 0.105893 0.330579 0.285048 -0.539114
Sp_Def 0.706501 0.376006 0.207211 0.483986 0.492861 1.000000 0.233487 0.017941 0.313196 0.328645 -0.513014
Speed 0.548890 0.170031 0.335013 -0.008663 0.443106 0.233487 1.000000 0.070098 0.224617 0.108637 -0.410557
Pr_Male 0.113564 -0.066704 0.213882 0.063899 0.105893 0.017941 0.070098 1.000000 0.040863 0.061196 -0.253645
Height_m 0.526813 0.442872 0.408590 0.354205 0.330579 0.313196 0.224617 0.040863 1.000000 0.661342 -0.382862
Weight_kg 0.535966 0.431320 0.469395 0.476983 0.285048 0.328645 0.108637 0.061196 0.661342 1.000000 -0.367798
Catch_Rate -0.738280 -0.478725 -0.525106 -0.436558 -0.539114 -0.513014 -0.410557 -0.253645 -0.382862 -0.367798 1.000000
plt.figure()

# 关闭格子线 (grid line)
ax = plt.gca()
ax.grid(False)

plt.imshow(corr_df, cmap='jet')
plt.xticks(range(len(numeric_cols)), numeric_cols, rotation='vertical')
plt.yticks(range(len(numeric_cols)), numeric_cols)
plt.colorbar()
plt.tight_layout()
<IPython.core.display.Javascript object>

5. 项目总结