【Python】データサイエンス100本ノック（構造化データ加工編） 013 解説

- データサイエンス100本ノックをやりきる会を作りました🎉
- こちらの[Slack招待URL](https://join.slack.com/t/data-science-100nocks/shared_invite/zt-gfncg9vm-8W8b3UrDg8R~TKaqUkQpgw)からご参加ください！！
- ぜひ一緒に励まし合いながら、データサイエンス100本ノックをやり切りたいと思っています！

##Youtube
[動画解説](https://youtu.be/8MCbzyCo7hY)もしています。

##問題
P-013: 顧客データフレーム（df_customer）から、ステータスコード（status_cd）の先頭がアルファベットのA〜Fで始まるデータを全項目抽出し、10件だけ表示せよ。

##解答
```:コード
df_customer.query("status_cd.str.contains('^A|^B|^C|^D|^E|^F')", engine='python').head(10)
```

##出力
|  | customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd |
|--:|:--|:--|--:|:--|:--|--:|:--|:--|:--|--:|:--|
| 2 | CS031415000172 | 宇多田 貴美子 | 1 | 女性 | 1976-10-04 | 42 | 151-0053 | 東京都渋谷区代々木********** | S13031 | 20150529 | D-20100325-C |
| 6 | CS015414000103 | 奥野 陽子 | 1 | 女性 | 1977-08-09 | 41 | 136-0073 | 東京都江東区北砂********** | S13015 | 20150722 | B-20100609-B |
| 12 | CS011215000048 | 芦田 沙耶 | 1 | 女性 | 1992-02-01 | 27 | 223-0062 | 神奈川県横浜市港北区日吉本町********** | S14011 | 20150228 | C-20100421-9 |
| 15 | CS029415000023 | 梅田 里穂 | 1 | 女性 | 1976-01-17 | 43 | 279-0043 | 千葉県浦安市富士見********** | S12029 | 20150610 | D-20100918-E |
| 21 | CS035415000029 | 寺沢 真希 | 9 | 不明 | 1977-09-27 | 41 | 158-0096 | 東京都世田谷区玉川台********** | S13035 | 20141220 | F-20101029-F |
| 32 | CS031415000106 | 宇野 由美子 | 1 | 女性 | 1970-02-26 | 49 | 151-0053 | 東京都渋谷区代々木********** | S13031 | 20150201 | F-20100511-E |
| 33 | CS029215000025 | 石倉 美帆 | 1 | 女性 | 1993-09-28 | 25 | 279-0022 | 千葉県浦安市今川********** | S12029 | 20150708 | B-20100820-C |
| 40 | CS033605000005 | 猪股 雄太 | 0 | 男性 | 1955-12-05 | 63 | 246-0031 | 神奈川県横浜市瀬谷区瀬谷********** | S14033 | 20150425 | F-20100917-E |
| 44 | CS033415000229 | 板垣 菜々美 | 1 | 女性 | 1977-11-07 | 41 | 246-0021 | 神奈川県横浜市瀬谷区二ツ橋町********** | S14033 | 20150712 | F-20100326-E |
| 53 | CS008415000145 | 黒谷 麻緒 | 1 | 女性 | 1977-06-27 | 41 | 157-0067 | 東京都世田谷区喜多見********** | S13008 | 20150829 | F-20100622-F |

##解説
・PandasのDataFrame/Seriesにて、条件に当てはまる先頭データを確認する方法です。  
・条件に当てはまる情報を確認したい時に使用します。
・**'contains(<文字列>)'は、指定した文字列が含まれているどうかを判定する関数**であり、含まれる場合はTrue、含まれない場合はFalseを返します。
・ただし、**'.query('---.str.contains(<文字列>))'は、指定した文字列が含まれることを条件として指定します**。
・今回の場合、status_cd を文字列に置換するために'status_cd.str'とし、'.contains('^A|^B|^C|^D|^E|^F')'を続けることで、「A or B or C or D or E or F」が先頭にある status_cd を指定しています。（'^'は先頭文字であることを表す正規表現です。正規表現とは、「複数の文字列を1つの記号で表す方法」のことを指します。） 
・'engine = 'python''について、query の引数である engine には'python'か、'numexpr'かを選択することができますが、strを用いる場合は、'python'を指定してあげないとエラーが発生してしまいます。  

※正解を見ると、以下のような表現になっています。確かに'^[A-F]'については、先頭を表す正規表現'^'と、範囲を表す'[A-F]'で表した方が、より簡単に表現することができます。
※'regex=True'は、正規表現を扱う際に必要とされていました。以下の解答例では'^''-'が正規表現として扱われています。現在は、書かなくても正規表現として扱われるようになっているので、なくても問題ないです  

```:コード
df_customer.query("status_cd.str.contains('^[A-F]', regex=True)", engine='python').head(10)
```

※先頭文字なんだから'str.startswith'を使うんじゃないか、と思われた方もいるかもしれませんが、以下のコードを実行しても何も抽出できません。なぜなら、'str.startswith'は正規表現を処理することができず、'|'を読み取ることができないためです。

```:コード
df_customer.query("status_cd.str.startswith('A|B|C|D|E|F')", engine='python').head(10)
```

※正規表現については、[こちら](https://qiita.com/hiroyuki_mrp/items/29e87bf5fe46de62983c)の記事が参考になります。