Pythonによるデータ処理: pandasの基礎

# Pythonによるデータ処理: pandasの基礎
これまでデータ分析の際に使ってきたpandasの基本機能を紹介する. 
Pythonの機械学習テンプレートは[こちら](https://qiita.com/birdwatcher/items/8b9b9f87e7074e1663ab).


## 前準備
今回対象とする[サンプルデータ](https://raw.githubusercontent.com/birdwatcherYT/pandas_test/master/data.csv). 

```data.csv
id,name,age,height,weight,sex,time
0,A,20,160,50,F,2018/11/23
1,B,25,170,60,M,2018/11/21
2,C,30,165,55,M,2018/11/20
3,D,,150,45,F,2018/11/22
```
<img width="252" alt="data.png" src="https://qiita-image-store.s3.amazonaws.com/0/294661/db421afc-a958-30ad-f0a1-198b9f76aecb.png">

importするパッケージ

```python
import numpy as np
import json
import pandas as pd
```

## pandasの基本機能
以下の処理は, 順番に実行されているものとして, pandasの基本機能の使用例を書いていく. 
実際に実行したい方は[こちら](https://github.com/birdwatcherYT/pandas_test) (github). 
実行結果を見たい人は[こちら](https://github.com/birdwatcherYT/pandas_test/blob/master/pandas_test.ipynb). 

### csvロード
```python
df = pd.read_csv("data.csv")
```
### indexの設定
```python
df = df.set_index("id")
```
`"id"`の列を`index`として設定する. 
### mapによる要素置換
```python
df["sex"] = df["sex"].map({"F":0, "M":1})
```
map関数に辞書を入れるとその通り置換される. 
### 日付の処理
```python
df["time"]=pd.to_datetime(df["time"])
```
日付の型へ変更. 
### mapで各要素へ任意の処理
```python
df['day'] = df['time'].map(lambda x: x.day)
df['weekday'] = df['time'].map(lambda x: x.weekday())
```
map関数のは, 関数も入力できる. ここでは, lambda式で記述. 
### NaNの数集計
```python
df.isna().sum()
```
各列でのNaNの数を得る. `isna()`でNaNのTrue/False行列が得られる. 
### NaNを埋める
```python
df["age"] = df["age"].fillna(df["age"].mean())
```
この例では, NaNを平均で埋めている. 
### 要素アクセス
```python
df.loc[0, "name"] = "Ａ"
```
`index`が`0`で, 列が`"name"`の位置へアクセスする. 
### 文字列の標準化
```python
df["name"] = df["name"].str.normalize("NFKC")
```
文字列を標準化できる. この例では, `Ａ`が`A`になる. 詳細は[こちら](https://japandas.readthedocs.io/en/latest/jpstrings.html). 
### 列名の変更
```python
df.columns = [c.upper() for c in df.columns]
```
df.columnsに直接, 列名のリストを渡すだけ. 
### onehot特徴の追加
```python
onehot = lambda target, num: np.eye(num,dtype=int)[target]
df[["weekday_"+str(i) for i in range(7)]] = pd.DataFrame(onehot(df["WEEKDAY"], 7))
```
weekdayをonehotしてみた例. 
### データフレーム同士の連結
```python
df = pd.concat([df, pd.DataFrame([[1,2],[3,4],[5,6],[7,8]], columns=["x", "y"])], axis=1)
```
`axis=1`では, 横方向の結合. `axis=0`で, 縦方向の結合. 
それぞれmatlabでいうところの, [A,B]と[A;B]. 
### 列追加
```python
df["z"] = [1,2,3,4]
```
1列追加するだけなら, 任意の列名に直接リストを代入するだけでよい. 
### 条件による抜き出し
```python
df[df["SEX"]==1]
```
性別が1のユーザを抽出. 
### 転置
```python
df.T
```
向きを変えて表示. 
### データフレームの各要素に対する任意の処理
```python
df[["xx","yy"]] = df[["x","y"]].applymap(lambda x: x*x)
```
mapのデータフレーム版がapplymap. 
### 列削除
```python
del df["x"]
df = df[[c for c in df.columns if not c=="y"]]
df = df.drop("z", axis=1)
```
`del`や`drop`でも消せるし, 必要な列だけを選ぶということで削除を実現することもできる. 
### 辞書へ変換
```python
df.to_dict()
```
### 集計処理
```python
df.groupby(["SEX"]).mean()
```
性別でグループ分けして, 平均をみる. 
`mean()`以外に, `count()`, `max()`, `min()`など. 
### 種類の確認
```python
df["SEX"].unique()
```
性別の種類(集合)を確認. 
### 結合
```python
week = pd.DataFrame([[0,"月"],[1,"火"],[2,"水"]],columns=["WEEKDAY","曜日"])
df = pd.merge(df, week, on="WEEKDAY", how="left")
```
SQLでいうところのLEFT JOIN. 
`on`: 2つのデータフレームで比較する列
`how`: 結合方法. `left`, `right`, `inner`, `outer`
2つの表の列名が違うものをキーに結合したい場合は, `left_on=`, `right_on=`を代わりに使う. 

### csvで保存
```python
df.to_csv("__result__.csv",index=False)
```
### jsonで保存
```python
df.to_json("__result__.json")
```
### jsonロード
```python
df = pd.read_json('__result__.json')
# 表形式で表現できない場合のjsonのロード
f = open('__result__.json', 'r', encoding="utf-8")
dic = json.loads(f.read())
f.close()
```
jsonファイルもpandasでロード可能. 
表形式で表現できない場合, `json.loads`を使う. 

### 縦形式へ変換
```python
df=df.melt(id_vars=["NAME", "AGE"], value_vars=["xx","yy"], var_name="xx or yy", value_name="square")
```
ロングフォーマットへ変換できる. 

### 横形式へ変換

```python
df=df.pivot(index='NAME', columns='xx or yy', values=['square'])
```