SQLのWHERE文を、pandas(python)のqueryメソッドを使ってデータの条件分岐を表現して見た

#はじめに
　最近、プライベートでデータ分析のツールを作成している関係でpandasというpython外部ライブラリを活用している。が、いざ使って見ると、「pandas?なにそれかわいいの？」と動物のパンダ🐼を連想させるヤバい思考に行きつつある状況になる。
　これはまずいと感じ、投稿者はpandasを探し求める旅に出る。
　この記事は、pandasを飼いならすために<b>pandasをSQLっぽく考えるというデータサイエンス初学者に向けた記事となります。</b>

#そもそもpandasとは何か
　pandasとは、構造化された（表形式、多次元、潜在的に不均質）データと時系列データを簡単かつ直感的に操作できるように設計された高速で柔軟な表現力のあるデータ構造を提供するPythonパッケージで、実際的な実世界のデータ分析を行うための基本的な高レベルのビルドを行う事が可能なツールです。
　<b>要は、表データをpythonを使っていい感じに処理して目的のデータ抽出するツールです。</b>

#実践
###準備
今回は下記の表データ【receipt】を用いてpandas攻略を行います。（表データはCSV形式）

![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681742/8ab25deb-8863-9255-b0f5-5c0b627e8128.png)
※データは長いので冒頭部分のみ表示

参考データ：データサイエンス100本ノック
https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess

また、今回はpandasを使用するため、コードは下記のように予め準備しておきます。

```python:python
import pandas as pd
df_receipt = pd.read_csv('receiptのCSVファイルのパス', sep=',')
```

###本題
タイトルにある通り、今回はSQLのWHERE文をpandasを使って再現します


問題：<b>レシート明細のデータフレーム（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の条件を満たすデータを抽出せよ。</b>

<b>顧客ID（customer_id）が"CS018205000001"
売上金額（amount）が1,000以上</b>



目的：<b>表から特定の条件を満たす行を抜き出す事</b>


解答
まず、解答を記述するとこんな感じになります。

```python:pandas(python)
df_receipt[['sales_ymd','customer_id','product_cd','amount']].query('customer_id == "CS018205000001" and amount >= 1000')
```
もしくは

```python:pandas(python)
df_receipt[['sales_ymd','customer_id','product_cd','amount']].query('customer_id == "CS018205000001" & amount >= 1000')
```
これをSQL文で表すとこんな感じになります。

```SQL:SQL
SELECT sales_ymd ,customer_id ,product_cd ,amount from receipt where customer_id 
='CS018205000001' and amount >= 1000;
```


そして、図に表すとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681742/43bc806a-ecbc-07f5-2020-f7ed269ed78e.png)


###解説
それでは、ここから解説していきます。

* SQLのWHERE文を、pandasのqueryメソッドを用いて表現する<br>
まず、pandasの二重リストを活用し、表全体から対象の列名を選択します。<br>
※補足：pandasの二重リストに関する記事は下記を参考にしてみて下さい。<br>
https://qiita.com/syuki-read/items/9fcb06ff56b868167f85

```python:pandas(python)
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']]
```
これをSQLで考えると、こんな感じになります。

```SQL:SQL
SELECT sales_ymd,customer_id,product_cd,amount FROM receipt;
```

FROM句：データベース内の指定する表を選択する
SELECT文：指定した表から抽出すべき列を選択する


図に現すとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681742/f261fc7d-f81f-626b-9457-6d1d33a31df2.png)


そしてここから、pandasのqueryメソッドを用いて、（SQLのWHERE文のように）特定の条件に合致する行の抽出を行います。
書き方は、

```python:pandas(python)
query('SQLのWHERE文的な条件式')
```
実際に書いてみると、

```python:pandas(python)
df_receipt[['sales_ymd','customer_id','product_cd','amount']].query('customer_id == "CS018205000001" and amount >= 1000')
```

今回の場合「customer_idがCS018205000001である行」と「amountが1000以上を満たす行」を[※1]AND演算子で、左右両方の条件を満たす行を抽出します。（ちなみに左右いずれかの条件を満たす場合は[※2]OR演算子を使用します）

※1：AND演算子は「&」で表記しても可
※2：OR演算子は「|」(パイプ)で表記しても可

そして、ここで注意して頂きたいのはこのqueryメソッドが、あくまでも「SQLのWHERE文的」な
立ち位置という事です。どういう事か、これをSQLで書くとこんな感じです。

```SQL:SQL
SELECT sales_ymd ,customer_id ,product_cd ,amount from receipt where customer_id 
='CS018205000001' and amount >= 1000;
```
　ここで注目して頂きたいのはWHERE文以降の条件文の部分です。SQLでは文字型（str型）のデータを抽出する時、「'文字列'」と表現し、文字列の前後を「'」(シングルコーテーション)で囲います。しかし、pandasのqueryメソッドでは条件文を書く時に文全体を「'」囲うため、条件文内に「'」を使用できず代わりに「"」(ダブルコーテーション)を行います。pandasでqueryメソッドを使う時、対象の列の文字型データを間違えて「'」で囲わないように注意しましょう。（囲ってしまうとエラーを出力します）

* 全体図<br>
全体をまとめると、こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681742/c7484d7b-79e2-8e16-d9cd-b0f74aed7aa0.png)


#まとめ
 pandasを使って、SQLのWHERE文の表現をpandasのqueryメソッドを使って行いました。pandasはデータベース及びSQLを意識したpythonライブラリなため、普段からSQLを意識するとかなり使いやすいツールだと改めて感じます。
 また、特定の命令文を指示する時、SQLがいくつものパターンがあるように、pandasにも多様なパターンが存在すると、pandasを活用して日々実感を持ちます。

#終わりに
　今回、利活用したデータはデータサイエンス協会（DS協会）の「データサイエンス100本ノック」を参考にしております。こちらはJupyter notebookを使用しているので、より見やすいデータが抽出されます。
　この記事を読んで、「実際に実装してみたい！！」という方がおりましたら、下記にその実装に関する記事を上げているので、良かったそちらの記事を参考に是非実装してみて下さい。

データサイエンス初学者にむけた、データサイエンス100本ノックを実装する方法：
https://qiita.com/syuki-read/items/714fe66bf5c16b8a7407