pandasでデータ加工をおこなうには

# はじめに
始めまして、株式会社ジール所属の@hiroaki_yoshidaです。
普段はAWSやPythonを使った開発を行っています。
開発に携わるにあたり、現場で学んだ事をアウトプットしていこうと思います。

今回の記事は前回の続きでPythonの __pandas__ というライブラリについて書いていこうかと思っており、データ加工の手段について基本的なSQL文と比較しながら説明したいと思います。

前回の記事がまだの方はこちらから↓
[データ分析ライブラリのpandasについて](https://qiita.com/hiroaki_yoshida/items/d295dce3ccda979a7ba7)

# 実行環境
pyhonバージョン：3.7.6
pandasバージョン：1.0.1

# SQLとは？
今回比較対象とされるSQLとはいったいなんぞやという方がいらっしゃるかと思いますので、簡単にご説明します。
 __SQL__ とは「 __Structure Query Language__ 」の略です。日本語だと構造化問い合わせ言語です。
データベース（以下DB）から必要なデータを取得する際に、どういうデータが必要なのか？といった問い合わせを行うためにSQLを使います。
例えば、顧客データの中から、20歳以上の男性のデータが欲しい場合、「 __20歳以上の男性__ 」が問合せ内容になります。

SQLはデータ加工を行う際には必ず出てくる単語ですので覚えておくといいと思います。

# データ準備
今回は下記データを使って説明していこうかと思います。

 __detailテーブル__
| id | item | shop_id | amount | date |
| :----: | :----: | :----: | :----: | :----: |
| 1 | ショベルカー | 2 | 2 | 2022-09-09 |
| 2 | ダンプカー | 1 | 3 | 2022-09-10 |
| 3 | ロードローラー | 3 | 4 | 2022-09-11 |
| 4 | ショベルカー | 2 | 5 | 2022-09-12 |

 __shop_infoテーブル__
| id | shop_name | status |
| :----: | :----: | :----: |
| 1 | 東京支店 | 2 |
| 2 | 名古屋支店 | 1 |
| 3 | 大阪支店 | 3 |

__statusテーブル__
| id | status |
| :----: | :----: |
| 1 | 開店 |
| 2 | 閉店 |
| 3 | 移転中 |
| 4 | 休業中 |


# SELECT
__SELECT文とはデータの選択を行うために使われる構文です。__

## SQLの場合

shop_infoテーブルのデータを __全列選択する場合__ は下記の様に記載します。
```sql
SELECT * FROM shop_info;
```
↓実行結果↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/2cd99000-ad6e-f3dd-9692-54e779d87407.png)


 __列を選択したい場合__ は下記のように記載します。
```sql
SELECT shop_name FROM shop_info; --単一列の出力の場合
SELECT shop_name, id FROM shop_info; --複数列の出力の場合
```
↓実行結果↓
__単一列の場合__ 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/a0f44e16-c58d-c43a-ca50-9236c0b5b48e.png)
__複数列の場合__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/929b6383-ee8e-9d40-41ea-38795734f198.png)



__行を絞りたい場合__ は下記のように記載します。
```sql
SELECT shop_name FROM shop_info WHERE id = 1; --単一行の出力の場合
SELECT shop_name FROM shop_info where id = 1 or id = 2; --複数行の出力の場合
```
↓実行結果↓
__単一行の出力の場合__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/8892a859-b0f8-7281-4b0c-d6df1f8221a5.png)
__複数行の出力の場合__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/6be9389b-2237-d88d-bc73-56bd4fd731d9.png)



## pandasの場合
__全列選択の場合__
```python
import pandas as pd

shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

shop_info
```
↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/20e2282a-d016-2cfd-c8f9-6f0be5315d9f.png)


__列を選択したい場合__ はdfの後に __[ ]__　を付け、出力したいカラムを記載します。
複数記載する場合はリストとして記載します。 
```python
import pandas as pd

shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

shop_info['shop_name'] #単一列の出力の場合
shop_info[['shop_name','id']] #複数列の出力の場合
```
↓実行結果↓
__単一列の場合__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/bdd0f1d1-4d80-6564-bba0-746d270d1520.png)
__複数列の場合__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/09a300d6-23ca-e0bb-f4fb-e701234db382.png)


__行を絞りたい場合__ も同じくdfの後に __[]__ を付けなかに条件を記載していくような形になります。
複数記載する場合は __「and」__ や __「or」__ ではなく __「&」__ と __「|」__　を使います。
```python
import pandas as pd

shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

shop_info[shop_info['id'] == 1] #単一条件の場合
shop_info[(shop_info['id'] == 1) | (shop_info['id'] == 2)] #複数条件の場合
```
↓実行結果↓
__単一条件の場合__ 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/78732924-beb0-cd68-4e46-15938a452905.png)

__複数条件の場合__ 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/61810719-9174-18fd-4ffb-8bc39d9ec606.png)


上記の記述を利用すると、DBから欲しいデータを抽出することができます。
続いては結合です。

# JOIN
__JOINとは読んで字のごとく、結合を意味しています。__
__JOINを使う事でテーブルとテーブルを結合させることができます。__
__ここではよく使うLEFT JOIN・RIGHT JOIN・INNER JOIN・FULL OUTER JOINの書き方の違いを紹介します__

## SQLの場合
__LEFT JOINの場合__
```SQL
SELECT *
FROM detail
LEFT JOIN shop_info
ON detail.shop_id = shop_info.id;
```

↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/069b827b-c8d4-11e8-83db-e84db050a795.png)


__RIGHT JOINの場合__
```SQL
SELECT *
FROM detail
RIGHT JOIN shop_info
ON detail.shop_id = shop_info.id;
```

↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/1ed0d67b-0694-7a42-7e2c-c6c90989f60e.png)


__INNER JOINの場合__

INNER JOINの動きが分かるようにdetailテーブルとshop_infoに新たに1レコード追加します。

 __detailテーブル__
| id | item | shop_id | amount | date |
| :----: | :----: | :----: | :----: | :----: |
| 1 | ショベルカー | 2 | 2 | 2022-09-09 |
| 2 | ダンプカー | 1 | 3 | 2022-09-10 |
| 3 | ロードローラー | 3 | 4 | 2022-09-11 |
| 4 | ショベルカー | 2 | 5 | 2022-09-12 |
| 5 | ショベルカー | 5 | 5 | 2022-09-15 |

 __shop_infoテーブル__
| id | shop_name | status |
| :----: | :----: | :----: |
| 1 | 東京支店 | 2 |
| 2 | 名古屋支店 | 1 |
| 3 | 大阪支店 | 3 |
| 4 | 石川支店 | 2 |

この状態で下記クエリを実行します。

```SQL
SELECT *
FROM detail
INNER JOIN shop_info
ON detail.shop_id = shop_info.id;
```

↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/3017388f-375d-efde-d38e-b5ab476d51ca.png)


__FULL OUTER JOINの場合__

こちらでも先ほどとINNER JOINで利用したテーブルを利用します。

```SQL
SELECT *
FROM detail
FULL OUTER JOIN shop_info
ON detail.shop_id = shop_info.id;
```

↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/140d0760-8590-17f4-6e95-37b971f29181.png)

## pandasの場合
pandasではjoinする場合、 __marge__ という関数を使います。
渡す引数としては下記になります。
```python
pd.merge(左テーブル, 右テーブル, left_on='左テーブルの結合キー', right_on='右テーブルの結合キー', how='結合方法')
```
もしキー項目が同じ名称な場合は下記のように書くこともできます。
```python
pd.merge(左テーブル, 右テーブル, on='結合キー', how='結合方法')
```
それでは各結合についてみていきます。


__LEFT JOINの場合__
```python
import pandas as pd

detail = pd.read_csv(r'C:\table\detail.csv',index_col=None)
shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

left_join_df = pd.merge(detail, shop_info, left_on='shop_id', right_on='id', how='left')
left_join_df
```
↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/177d8d4f-7a43-918f-71c6-36d99fed7dd4.png)

__RIGHT JOINの場合__
```python
import pandas as pd

detail = pd.read_csv(r'C:\table\detail.csv',index_col=None)
shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

right_join_df = pd.merge(detail, shop_info, left_on='shop_id', right_on='id', how='right')
right_join_df
```
↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/e0879e30-2522-6f9d-9695-c9a33b63776b.png)


__INNER JOINの場合__
```python
import pandas as pd

ddetail = pd.read_csv(r'C:\table\detail.csv',index_col=None)
shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

#DataFrameに追加する行を作っています
detail_addd = pd.DataFrame([[5,'ショベルカー',5,5,'2022/9/15']],columns=['id','item','shop_id','amount','date'])
sho_info_add = pd.DataFrame([[4,'石川',2]],columns=['id','shop_name','status'])

#行を追加しています
detail = pd.concat([detail,detail_addd])
shop_info = pd.concat([shop_info,sho_info_add])

inner_join_df = pd.merge(detail, shop_info, left_on='shop_id', right_on='id', how='inner')
inner_join_df

```
↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/edeb8680-a19f-bd94-bd1e-703f2b4b62d8.png)


__FULL OUTER JOINの場合__
```python
import pandas as pd

detail = pd.read_csv(r'C:\table\detail.csv',index_col=None)
shop_info = pd.read_csv(r'C:\table\shop_info.csv',index_col=None)

#DataFrameに追加する行を作っています
detail_addd = pd.DataFrame([[5,'ショベルカー',5,5,'2022/9/15']],columns=['id','item','shop_id','amount','date'])
sho_info_add = pd.DataFrame([[4,'石川',2]],columns=['id','shop_name','status'])

#行を追加しています
detail = pd.concat([detail,detail_addd])
shop_info = pd.concat([shop_info,sho_info_add])

outer_join_df = pd.merge(detail, shop_info, left_on='shop_id', right_on='id', how='outer')
outer_join_df

```
↓実行結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166184/6f522cf4-b5f7-d6ba-168c-ba5aad6ec4ec.png)


# まとめ
以上が基本的なSQLとpandasの書き方の違いになります。
pandasを使うメリットとしてはPythonの他のライブラリを利用するなどで、__より複雑なデータ加工や分析ができるようになる__ 事です。

pandasの利用例としては、AWSサービスであるS3上のファイルを一次加工するのに利用することもできますし、ライブラリを組み合わせればDBへそのままDataFrameをinsertすることもできます。
もちろんDBのデータをDataFlameへ格納することもできます。
SQLを使わずPandasだけで処理を作成することもできてしまいます。

とても奥が深いライブラリなので、是非みなさんもpandasを活用してみてください。