[Python] pandas データ加工

アウトプット＆メモ。

[pandas データ結合 編 ](https://qiita.com/hikaru_/items/e9c1356f674f2baa9e64)




# pandas読み込み

```python
import pandas as pd
from pandas import Series, DataFrame
```

# 条件で行を抽出

サンプルデータはこんな感じ。

```python
# データの準備
data = {'ID':['100','101','102','103','104']
        ,'city':['Kyoto','Osaka','Tokyo','Hokkaido','Okinawa']
        ,'birth_year':[1980,1999,1995,1970,1994]
        ,'name':['A','B','C','D','E']}

sample_data = pd.DataFrame(data)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/71570929-251e-80a0-b9fb-67d2ba541c93.png)

上記を例にデータ加工する。

## boolリストで返す。

```python
# 1990年より前に産まれた人
sample_data["birth_year"] < 1990
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/1cde0ee6-9d8d-0abd-09d8-d33e355e3066.png)

## boolリストを使って行を抽出
もちろん複数条件も可能。
あとは値を代入するなり、平均出したりするだけ。

```python
# sample_data[]の中にboolリストを突っ込んであげるだけ
sample_data[sample_data["birth_year"] < 1990]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/54d32f12-ae43-2107-5432-6ec2f93ade1d.png)

## loc
個人的にはこっちを一番使う。
loc[ 行の指定, 列の指定 ]

```python
# 1990より前に産まれた人の行と、全て(:)のカラムを抽出。
sample_data.loc[sample_data['birth_year'] < 1990, :]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/a3e0b04a-6dbf-79fe-2335-32509321f812.png)


## query()
こちらでも、条件で行を抽出できる。文字列は""で囲む必要があるので注意。

```python
sample_data.query('birth_year < 1990 & name == "A"')
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/a0d04b90-a3e7-0fca-4d39-a9414983d4ec.png)

## 文字列の部分一致で行を取得
str.contains()を使うと、特定の文字列を含む場合Trueになる。
NaNがある時に行を抽出するとエラーとなるので、引数にna=Flaseとしよう。

```python
sample_data[sample_data['city'].str.contains('Osa')]
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/ecc2a31a-6fed-135c-08ac-7883ae5b785b.png)

↓ 他にも以下の方法もできる。

|  |説明  |
|---|---|
|str.startswith()  |特定の文字列で始まる  |
|str.endswith()  |特定の文字列で終わる  |



# 列の要素を置換

## map()

cityを区域で置換して新しいカラム(region)に入れる。

```python
# 参照データ
map_data = {'Kyoto':'Kansai',
           'Osaka':'Kansai',
           'Tokyo':'Kanto',
           'Hokkaido':'Hokkaido'}

# 参照データで置換
sample_data ['region'] = sample_data ['city'].map(map_data)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/cdcb2b46-8860-b644-378d-3a1e1e07d232.png)

<b>置換できなかった要素はNaNになる。</b>

## replace()

map()と同じだが、置換後の値が異なる。

```python
# 参照データ
map_data = {'Kyoto':'Kansai',
           'Osaka':'Kansai',
           'Tokyo':'Kanto',
           'Hokkaido':'Hokkaido'}
# map()と同じ参照データで置換
sample_data ['region'] = sample_data ['city'].replace(map_data)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/16666c0e-7f9c-1fab-238e-8ab4cc31eb1f.png)

<b>置換できなかった要素は元の値を引き継ぐ</b>

# 要素の一部を取り出す

# map()と無名関数の組み合わせ技

ループなどを使って取り出すより、こちらの方が処理速度が優れているので、まとめて処理したい場合はこちらがおすすめ。

birth_yearの上3文字を取り出して、19〇0年産まれか分かるようにする。

```python
#　birth_year の上3つの数字・文字を取り出す
sample_data ['up_two_num'] = sample_data ['birth_year'].map(lambda x:str(x)[0:3])
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/dc277e40-b89d-8332-ed65-aa4777f7cca6.png)


# 指定した範囲でデータを分割

# cut()

birth_yearを指定範囲で分割する。

```python
# 分割の粒度
bins = [1970,1980,1990,2000]

# 分割実行。
birth_cut_data = pd.cut(sample_data.birth_year, bins)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/179d0269-b5f1-8c6e-a1cf-c1d4c64ef01b.png)

#### value_counts()
上記で分割した後にカウントをとる。

```python
pd.value_counts(birth_year_cut_data)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/a571e181-e137-87f6-f4ef-00ea0dc7646c.png)

### 文字列でも同じようにカウントしたい場合
可視化が捗る。

```python
sample_data.groupby["city"].size()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/f17f2c0e-9a39-74f8-97c0-64371e41a979.png)


分割数を指定することも可能。

```python
# birth_yearの (min + max) /2 の値を境に分割  =>  (1980 + 1999) / 2 = 1989.5
birth_cut_data = pd.cut(sample_data.birth_year, 2)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/0bfc5e21-78ab-4c2b-629f-c95f0b8d04db.png)


# qcut()

分位点での分割も可能

```python
# 分位点で分割、ここでは2を指定しているので中央値(1994)が境になる
birth_qcut_data = pd.qcut(sample_data.birth_year, 2)

# カウント
pd.value_counts(birth_qcut_data)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/78078bdd-f932-7363-192f-7cf0b4b6cbef.png)


# 重複判定

サンプルにするデータ

```python
# 重複データのサンプル
dupli_data = DataFrame({'column1':[1,2,2,3,4,4,6,6]
                       ,'column2':['a','b','b','c','c','c','b','b']})
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/83411fb7-68da-6320-0fe9-9a295d4c340f.png)

## duplicated()
重複行があるか判定する。重複している場合はTrue

```python
dupli_data.duplicated()
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/46ee8f32-a083-573c-3f3d-0ebcbe906906.png)


## drop_duplicates()
重複行の削除

```python
#　重複削除。Trueを削除
dupli_data.drop_duplicates()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/511dd393-8c40-2e7e-2a8c-fc3c37521147.png)



# [番外]統計関数
データ加工と組み合わせて使ったりするnumpyの関数おさらい。

```python
# numpy読み込み。
import numpy as np
```


| 関数 |説明  |
|---|---|
|min()  |最小値  |
|max()  |最大値  |
|median()|中央値  |
|mode()  |最頻値  |
|mean()  |平均  |
|sum()  |合計  |
|var()  |分散  |
|std()  |標準偏差  |