ポケモン種族値データを使って pandas の使いかたを学ぶ

pandas の使い方を学ぶために色々と触ってみました。
メモを残しておきます。

### この記事に書いたこと

* CSVの読み込み
* データの構造確認
* 範囲指定での表示
* 指定条件での抽出
* グループごとに集計
* ピボットテーブル
* グラフ描画

### 使用したデータ
ポケモンの種族値データを使用します。
スキーマの整ったきれいなデータかつ、データの中身に意味のあるものを使いたかったのが理由です。

ポケモンの種族値データはこちらで配布されているものを使用させていただきました。ありがとうございます。
[ポケモンの種族値データシートの配布【第7世代】]
(http://rikapoke.hatenablog.jp/entry/pokemon_datasheet_gne7)

# 準備

まずは、pandas を import します。

```python
import pandas as pd
```

# CSV の読み込み

```python
df = pd.read_csv("pokemon_status.csv")

# utf-8 でない場合は、エンコードを指定します。
df = pd.read_csv("pokemon_status.csv", encoding="shift-jis")
```

[参考] [pandasでread_csv時にUnicodeDecodeErrorが起きた時の対処 (pd.read_table())] (https://qiita.com/niwaringo/items/d2a30e04e08da8eaa643)

ちなみに df はデータフレームから取っています。

# カラム名の設定

のちの操作をしやすくするために、カラム名を設定します。

```python
df.columns = ["図鑑番号", "ポケモン名", "タイプ1", "タイプ2",\
    "通常特性1", "通常特性2", "夢特性",\
    "HP", "こうげき", "ぼうぎょ", "とくこう", "とくぼう", "すばやさ", "合計"]
```

# データの構造確認
```python
# 行数
len(df)

# 列名
df.columns

# 次元数 (行数、列数)
df.shape

# データフレームの情報サマリ (行数、列名と型、など)
df.info()

# サマリを表示
df.describe()
```
# 範囲指定での表示

```python
# 先頭 5 行を表示
df.head()

# ポケモン名の一覧
df["ポケモン名"]

# 指定列だけ表示
df.loc[:,["ポケモン名", "タイプ1", "タイプ2"]]
```
# 列の追加、削除

計算結果を新たな列として追加。

```python
# 以降の作業はコピーしたデータフレームに対して実施。
df2 = df.copy()
# 物理耐久最大値列を追加。（レベル 50 物理耐久特化時の HP × ぼうぎょの計算結果）
df2["物理耐久最大値"] = (df2["HP"] + 107 ) * (df2["ぼうぎょ"] + 52 * 1.1)
```

指定した列を削除。

```python
df3 = df.drop(["通常特性1", "通常特性2", "夢特性"], axis=1)
```

# ソート

```python
# 素早さの降順でソート
df.sort("すばやさ", ascending=False)
```

# 指定条件で抽出

```python
# でんきタイプの素早さ種族値 100 以上のポケモンを抽出し、素早さの降順にソートしてポケモン名と種族値を表示
df.query("タイプ1 == 'でんき' | タイプ2 == 'でんき'").\
query("すばやさ >= 100").\
sort("すばやさ", ascending=False).\
loc[:,["ポケモン名", "HP", "こうげき", "ぼうぎょ", "とくこう", "とくぼう", "すばやさ", "合計"]]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/2737f58c-89d5-861f-ee11-553f466304a3.png)

マルマインは第7世代から素早さ種族値が 140 から 150 に上がっています。

# グループごとに集計

タイプごとに種族値平均値を表示。

```python
# mean は平均、round は小数点以下 1 桁に丸める。
df.groupby("タイプ1").mean().round(1)
※簡略化のため、タイプ１のみで集計
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/f4df0993-2e16-e603-10f7-02830dbe359c.png)

# ピボットテーブル

行をタイプ1、列をタイプ2にしてカウント。

```python
# aggfunc はカウント、fill_value は NaN のセルを 0 にする。
pd.pivot_table(df, values="図鑑番号", index="タイプ1", columns="タイプ2", aggfunc=lambda x : len(x), fill_value = 0)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/babd39fb-f22b-d77e-2c61-42832c6f3fda.png)

ノーマル、ひこうの組み合わせが一番多いです。

# グラフ描画

### 準備

Jupyter Notebook で作業するときは、下記コマンドを入力しておいてください。

```
%matplotlib inline
```

[参考] [Jupyter Notebookでmatplotlibのグラフが表示されない]
(https://qiita.com/musaprg/items/347f201022a1d10d39df)

日本語を使えるようにしておきます。

[参考] [matplotlibの日本語フォント設定]
(https://qiita.com/creativewebjp/items/3fac25c2ffa316990d0c)

きれいに描画するためのおまじないだそうです。フォントはIPA明朝としています。

```python
import matplotlib
import matplotlib.pyplot as plt

plt.style.use("ggplot") 
font = {"family":"IPAMincho"}
matplotlib.rc("font", **font)
```

[参考] [JPythonでPandasのPlot機能を使えばデータ加工からグラフ作成までマジでシームレス]
(https://qiita.com/hik0107/items/de5785f680096df93efa)

## 散布図

攻撃と素早さの散布図。

```python
df.plot.scatter(x="こうげき", y="すばやさ")
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/b3b8feb8-6b5c-bbda-514f-2d8ae06faa1d.png)

## ヒストグラム

素早さのヒストグラム。

```python
# bins は分割数、アルファは透過度合い。
df.plot.hist(y="すばやさ", bins=30, alpha=0.6)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/f3cb7644-60d9-fec6-87ee-7d5c329ead6a.png)

でんきタイプといわタイプの素早さ分布比較。

```python
df_denki = df.query("タイプ1 == 'でんき' | タイプ2 == 'でんき'")
df_iwa = df.query("タイプ1 == 'いわ' | タイプ2 == 'いわ'")

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.hist([df_denki["すばやさ"], df_iwa["すばやさ"]], bins=15, alpha=0.6, label=["でんき", "いわ"])
ax.legend(loc="upper right")
fig.show()
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/48133/026573e0-a489-8fd6-0fb5-c38e7fa0b5d5.png)

でんきタイプには素早いポケモンが多く、いわタイプは鈍足が多いことがグラフからも読み取れます。