GCIデータサイエンティスト育成講座の演習問題を解く Chapter6

#GCIデータサイエンティスト育成講座
「[GCIデータサイエンティスト育成講座](http://weblab.t.u-tokyo.ac.jp/gci_contents/)」は、東京大学(松尾研究室)が開講している"*<u>実践型のデータサイエンティスト育成講座およびDeep Learning講座</u>*"で、演習パートのコンテンツがJupyterNoteBook形式で公開(CC-BY-NC-ND)されています。
Chapter6は「**Pandasを使ったデータ加工処理**」で、データ解析をするための強力かつ高速なデータ操作ライブラリの使い方を学習していきます。
日本語で学べる貴重で素晴らしい教材を公開いただいていることへの「いいね！」ボタンの代わりに、解いてみた解答を載せてみます。間違っているところがあったらご指摘ください。

# Chapter6 Pandasを使ったデータ加工処理

## 6.1 Pandas

### 6.1.1 階層型インデックス

> **<練習問題 1>**
> 次のデータに対して、Kyotoの列だけ抜き出してみましょう。

> ```py3
> hier_data_frame1 = DataFrame(np.arange(12).reshape((3,4))
>                            ,index = [['c','d','d'],[1,2,1]]
>                            ,columns = [['Kyoto','Nagoya','Hokkaido','Kyoto']
>                                       ,['Yellow','Yellow','Red','Blue']]
>                            )
> 
> hier_data_frame1.index.names =['key1','key2']
> hier_data_frame1.columns.names =['city','color']
> hier_data_frame1
> ```
> 
> ![611-1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/67518f7c-5e2f-46ba-1fb2-f875991c5840.png)

```py3
hier_data_frame1["Kyoto"]
```

![611-1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/8fe95c44-c99e-bb05-067c-8089e0efdce7.png)

> **<練習問題 2>**
> 練習問題1のデータに対して、cityをまとめて列同士の平均値を出してください。

```py3
hier_data_frame1.mean(level = "city", axis = 1)
```

![611-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/3a2f789d-57c0-ae8b-45ec-834646eeec24.png)

> **<練習問題 3>**
> 練習問題1のデータに対して、key2ごとに行の合計値を算出してみましょう。

```py3
hier_data_frame1.sum(level = "key2")
```

![611-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/84e525f6-eef9-e5f0-dc12-795abede2b37.png)

### 6.1.2 データのマージ

> **<練習問題 1>**
> 下記の2つのデータテーブルに対して、内部結合してみましょう。

```py3
pd.merge(attri_data_frame4, attri_data_frame5, how = "inner")
```

![612-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/6bf70ebf-e2f1-2fb0-d117-ba0c9d628193.png)

> **<練習問題 2>**
> attri_data_frame4をベースにattri_data_frame5のテーブルを外部結合してみましょう。

```py3
pd.merge(attri_data_frame4, attri_data_frame5, how = "outer")
```

![612-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/8ad1274f-9583-a493-17d8-a5913b452302.png)

> **<練習問題 3>**
> attri_data_frame4に対して、以下のデータを縦結合してみましょう。

```py3
pd.concat([attri_data_frame4, attri_data_frame6])
```

![612-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/a8afef9b-37b7-d015-f9e4-0c47cdf5dedc.png)

### 6.1.3 データの操作と変換

> **<練習問題 1>**
> 以前の章で使用した「student-mat.csv」のデータを使います。ageを2倍にしたカラムを追加してみましょう。

```py3
student_data_math["2age"] = 2 * student_data_math["age"]
student_data_math[["age", "2age"]].head()
```

![613-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/065ab0fd-ea2c-243d-e350-be7a8480bbd5.png)

> **<練習問題 2>**
> 上記と同じデータで、「absences」のカラムについて、以下の3つのビンに分けてそれぞれの人数を数えてみましょう。なお、cutのオプション設定で、デフォルトは右側が閉区間になっていますが、今回は0が入るためのright=Falseを追加してください。

```py3
# pd.cut(student_data_math.absences, absences_bins, right=False)
pd.value_counts(pd.cut(student_data_math.absences, absences_bins, right=False))
```

```
> [5, 100)    151
> [1, 5)      129
> [0, 1)      115
> Name: absences, dtype: int64
```

> **<練習問題 3>**
> 上記と同じデータで、「absences」のカラムについて、qcutを用いて3つのビンに分けてみましょう。

```py3
# pd.qcut(student_data_math.absences, 3)
pd.value_counts(pd.qcut(student_data_math.absences, 3))
```

```
> (-0.001, 2.0]    183
> (6.0, 75.0]      115
> (2.0, 6.0]        97
> Name: absences, dtype: int64
```

### 6.1.4 データの集約とグループ演算

> **<練習問題 1>**
> 先ほど使用した「student-mat.csv」を使って「student-mat.csv」を使って、pandasの集計処理してみましょう。まずは、schoolを軸にして、G1の平均点をそれぞれ求めてみましょう。

```py3
student_data_math = pd.read_csv("student-mat.csv",sep=";")
student_data_math.groupby("school")["G1"].mean()
```

```
> school
> GP    10.939828
> MS    10.673913
> Name: G1, dtype: float64
```

> **<練習問題 2>**
> 次は、schoolと性別を軸にして、G1,G2,G3の平均点をそれぞれ求めてみましょう。

```py3
student_data_math.groupby(["school", "sex"])[["G1", "G2", "G3"]].mean()
```

![614-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/b3747fbb-3bf3-39c0-4364-c46ce5518847.png)

> **<練習問題 3>**
> 次は、schoolと性別を軸にして、G1,G2,G3の最大値、最小値をまとめて算出してみましょう。

```py3
student_data_math.groupby(["school", "sex"])[["G1", "G2", "G3"]].agg(["max", "min"])
```

![614-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/cd8ba4b6-3acc-b407-43eb-6d194fc334f9.png)

## 6.2 欠損データと異常値の取り扱いの基礎

### 6.2.1 欠損データの扱い方

> **<練習問題 1>**
> 以下のデータに対して、1列でもNaNがある場合は削除し、その結果を表示してください。

```py3
sample_data_frame2.dropna()
```

![621-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/e82b0dcf-bbe9-19eb-7a9f-6c43ff99234e.png)

> **<練習問題 2>**
> 上記で準備したデータに対して、NaNを0で埋めてください。

```py3
sample_data_frame2.fillna(0)
```

![621-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/cda58bb5-afc0-bbdc-2e31-c1b687fa8e88.png)

> **<練習問題 3>**
> 上記で準備したデータに対して、NaNをそれぞれの列の平均値で埋めてください。

```py3
sample_data_frame2.fillna(sample_data_frame2.mean())
```

![621-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55744/115da097-6eec-2d99-9cfd-f7c0b1eb81ec.png)

### 6.2.2 異常データの扱い方

## 6.3 総合問題

> **6.3.1 総合問題1**
> 以前使用した「student-mat.csv」を使って、以下の問いに答えてください。
> 
> (1) 上記のデータに対して、年齢×性別でG1の平均点を算出し、縦軸が年齢、横軸が性別となるような表（テーブル）を作成しましょう。
> 
> (2) (1)で表示した結果テーブルについて、NAになっている行(レコード)を全て削除した結果を表示しましょう。

```py3
student_data_math = pd.read_csv("student-mat.csv",sep=";")

# (1)
print("(1)")
print(student_data_math.groupby(["age", "sex"])["G1"].mean().unstack())

# (2)
print("\n(2)")
print(student_data_math.groupby(["age", "sex"])["G1"].mean().unstack().dropna())
```

```
> (1)
> sex          F          M
> age                      
> 15   10.052632  12.250000
> 16   10.203704  11.740000
> 17   11.103448  10.600000
> 18   10.883721  10.538462
> 19   10.642857   9.700000
> 20   15.000000  13.000000
> 21         NaN  10.000000
> 22         NaN   6.000000
> 
> (2)
> sex          F          M
> age                      
> 15   10.052632  12.250000
> 16   10.203704  11.740000
> 17   11.103448  10.600000
> 18   10.883721  10.538462
> 19   10.642857   9.700000
> 20   15.000000  13.000000
```