LoginSignup
9
14

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-06-23

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

100本ノックの記事
100本ノックのガイド

前回環境構築の参考にさせていただいたページ

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

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

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

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

目次 問題番号
part1 1~9 part6 33~35 part11 57~62
part2 10~18 part7 36~40 [part12] 未投稿
part3 19~22 part8 41~44
part4 23~28 part9 45~51
part5 29~32 part10 52~56

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を使う必要性があったかは不明。というか、ない。

今回はここまで

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

9
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
14