データサイエンス100本ノック~初心者未満の戦いpart1

これはデータサイエンティストの卵(産みたて)がわけもわからないまま100本ノックを行っていく奮闘録である。
完走できるかすら謎。~~途中で消えてもQiitaにあげてないだけと思ってください。~~

[100本ノックの記事](https://codezine.jp/article/detail/12456)
[100本ノックのガイド](https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess/blob/master/docker/doc/100knocks_guide.pdf)

[前回環境構築の参考にさせていただいたページ](https://qiita.com/rasyo/items/dd6f8dfc422511da25d6)

**ネタバレも含みますのでやろうとされている方は注意**

知らなかった書き方も多く、また「自分はこう書いたけど答えはこうだった」というものも多くあったのでメモ代わりに置いておきます。

コレは見づらい！この書き方は危険！等ありましたら教えていただきたいです。~~心にダメージを負いながら~~糧とさせていただきます。

この解き方は間違っている！この解釈の仕方は違う！等もありましたらコメントください。

| 目次| 問題番号|||||
|:----:|:----:|:----:|:----:|:----:|:----:|
| part1|１～９ |[part6](https://qiita.com/sola_wing529/items/173687974b57be5d0d1c)|３３～３５|[part11](https://qiita.com/sola_wing529/items/f99843a95d7d9b083eba)|５７～６２|
|[part2](https://qiita.com/sola_wing529/items/3c2d98da08345a879bae)|１０～１８|[part7](https://qiita.com/sola_wing529/items/7b0a55b174da433debef)|３６～４０|[part12]|未投稿|
|[part3](https://qiita.com/sola_wing529/items/06fc1f9458ddd043616e)|１９～２２|[part8](https://qiita.com/sola_wing529/items/9c32890f3177033692a4)|４１～４４|
|[part4](https://qiita.com/sola_wing529/items/97bfd1c09e68b5aa51bf)|２３～２８|[part9](https://qiita.com/sola_wing529/items/785a33645f0749ecf5bc)|４５～５１|
|[part5](https://qiita.com/sola_wing529/items/378c719b9a56dbd5a615)|２９～３２|[part10](https://qiita.com/sola_wing529/items/69491a132151539e7044)|５２～５６|



#1本目
さすがにこれは書ける。
予習しても頭に入らない鳥頭でもコレが書けないと支障をきたすので。

```mine01.py
df_receipt.head(10)
```

#2本目
~~いきなりエラーをかます~~
そうだった。複数列を射影するときは`[['列A','列B']]`と書くんだった。エラーを吐くのは日常茶飯事です。

```mine02.py
df_receipt[['sales_ymd','customer_id','product_cd','amount']].head(10)
```

#3本目
早くも答えと違う回答をする。
自分が書いたのが

```mine03.py
df=df_receipt[['sales_ymd','customer_id','product_cd','amount']]
df.columns=['sales_date','customer_id','product_cd','amount']
df.head(10)
```

こんな簡単なことに3行使うのはバカらしいのかもしれないが、頭の中を整理しながら解いていたのでこうなった。
というか、`｛ ｝`とかpythonやりはじめてからほぼ使わないので、単純にrenameを知らなかった。

>**模範解答**
`df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].rename(columns={'sales_ymd': 'sales_date'}).head(10)`

#4本目
ここも違う回答をしました。

```mine04.py
df=df_receipt[['sales_ymd','customer_id','product_cd','amount']]
df=df[df['customer_id']=='CS018205000001']
df
```


>模範解答
df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']].query('customer_id == "CS018205000001"')

`query`が文字列として書くという部分に抵抗を覚えるのは自分だけでしょうか。~~文字列……WAF……正規表現マッチング……うっ頭が~~
文字列型入力だと内部で入力ミスしてもエラーが分からないんですよね。`query`のほうが動作が早かったりするのでしょうか？

#5本目
```mine05.py
#df=df_receipt[['sales_ymd','customer_id','product_cd','amount']]
#df=df[df['customer_id']=='CS018205000001']
df[df['amount']>=1000]
```
>模範解答
`df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']] \
            .query('customer_id == "CS018205000001" & amount >= 1000')`

4本目と前提条件が同じだったのでそのまま`df`を流用しました。
ここでも模範解答は`query`。書きながら思ったのですが、`ix`みたいな非推奨な書き方だったりするのかな？

##余談
`df=df[df['customer_id']=='CS018205000001']
df[df['amount']>=1000]`
の二行をつなげて
`df=df[df['customer_id']=='CS018205000001'][df['amount']>=1000]`

としても同じ結果は出ますが、`/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:2: UserWarning: Boolean Series key will be reindexed to match DataFrame index.`
というWarningをします。
df=df[条件]でdfになるのだからdf[条件1][条件2]も行けるだろうと思ったら怒られました。

#6本目
```mine06.py
df=df_receipt[['sales_ymd','customer_id','product_cd','quantity','amount']]
df=df[df['customer_id']=='CS018205000001']
df=df[(1000<=df['amount'])|(5<=df['quantity'])]
df
```
>模範解答
`df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'quantity', 'amount']].query('customer_id == "CS018205000001" & (amount >= 1000 | quantity >=5)')`

条件が長くなってきたので更に分割。特にAND条件は分割したほうが分かりやすいと思い。レスポンスは下がるのか？

#7本目
```mine07.py
df=df_receipt[['sales_ymd','customer_id','product_cd','amount']]
df=df[df['customer_id']=='CS018205000001']
df=df[(1000<=df['amount'])&(df['amount']<=2000)]
df
```
>模範解答
`df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']] \
    .query('customer_id == "CS018205000001" & 1000 <= amount <= 2000')`

Between条件を一言で書けるのは魅力的である。ちなみにこれくらいからひたすらに「SQLで書きてぇ……」って思ってました。

#8本目
```mine08.py
df=df_receipt[['sales_ymd','customer_id','product_cd','amount']]
df=df[df['customer_id']=='CS018205000001']
df=df[df['product_cd'] != 'P071401019']
df
```
>模範解答
`df_receipt[['sales_ymd', 'customer_id', 'product_cd', 'amount']] \
    .query('customer_id == "CS018205000001" & product_cd != "P071401019"')`

これくらいの条件なら中で条件を結ぶべきか迷うところ。

#9本目
```mine09.py
df_store.query('prefecture_cd != "13" & not (floor_area > 900)')
```
>模範解答
`df_store.query('prefecture_cd != "13" & floor_area <= 900')`

ついにqueryに~~屈する~~
ではなく、書き換え問題なので。notを使う必要性があったかは不明。というか、ない。


#今回はここまで
正直、自分が調べずにいけたのはココまで。次回からは分からないことを無理やり書こうとして玉砕する図を書いていこうと思う。