データサイエンス100本ノック（構造化データ加工編）ー ヒント集（P-001〜P-010）



# この記事ってなに？
[データサイエンスの100本ノック](https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess)に取り組んだ時、
**「答えを見るのは嫌だ!! でもヒントは欲しい...」** 的なヒトむけに向けた記事！



（ついでに私が取り組んだ時の回答も折り畳みで隠して記載しておくので、
　15分考えてダメなら、確認して次へ進もう）

| ページ内リンク |
|:-------------|
| [P-001ヒント](#p-001) |
| [P-002ヒント](#p-002) |
| [P-003ヒント](#p-003) |
| [P-004ヒント](#p-004) |
| [P-005ヒント](#p-005) |
| [P-006ヒント](#p-006) |
| [P-007ヒント](#p-007) |
| [P-008ヒント](#p-008) |
| [P-009ヒント](#p-009) |
| [P-010ヒント](#p-010) |

本記事以外のヒントをお探しの方はこちらから
|:-------------|
| [DS 100本ノック ヒント記事リスト](#ds-100本ノック-ヒント記事リスト) |

# 実施環境
google colabにて、下記演習のnotebookをコピーして取り組んだ！
（公式githubにある、Dockerがなんちゃらとかは実施していない）
![スクリーンショット 2023-01-29 19.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1990652/bc2b6312-b16c-dba8-21e4-dab73818951d.png)


Python公式演習:
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1990652/68c8da0e-add3-18c2-fa20-cdd7c9d7ec31.png)](https://colab.research.google.com/github/The-Japan-DataScientist-Society/100knocks-preprocess/blob/master/docker/work/preprocess_knock_Python.ipynb)

Python公式解答: 
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1990652/68c8da0e-add3-18c2-fa20-cdd7c9d7ec31.png)](https://colab.research.google.com/github/The-Japan-DataScientist-Society/100knocks-preprocess/blob/master/docker/work/answer/ans_preprocess_knock_Python.ipynb)

# P-001
### 問題
> P-001: レシート明細データ（df_receipt）から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。

### ヒント
dataframeで値を表示するときは頭を使うらしいが...
頭...head()...?
- 参考になるサイト

https://kino-code.com/python-pandas-head/

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_receipt.head(10)
# df_receipt[0:10] # 別解
```
</div></details>

---

# P-002
### 問題
> P-002: レシート明細データ（df_receipt）から売上年月日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示せよ。

### ヒント
df[['カラム名1', 'カラム名2'...]]で抽出可能らしいが...
（[]だとSerise型、[[]]だとDataFrame型で取得になるようだ）


- 参考になるサイト

https://aiacademy.jp/media/?p=651

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_receipt.head(10)[['sales_ymd','customer_id','product_cd','amount']]
# df_receipt[0:10][['sales_ymd','customer_id','product_cd','amount']]  # 別解
```
</div></details>

---
# P-003
### 問題
> P-003: レシート明細データ（df_receipt）から売上年月日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、10件表示せよ。ただし、sales_ymdをsales_dateに項目名を変更しながら抽出すること。

### ヒント
P-002の解答 + カラム名の変更はdf.renameが使えるらしいが...

- 参考になるサイト

https://note.nkmk.me/python-pandas-dataframe-rename/

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p003 = df_receipt[['sales_ymd','customer_id','product_cd','amount']] # 元データから該当カラム分だけコピー
df_p003.rename(columns={"sales_ymd": "sales_date"}, inplace=True)             # カラム名変更
df_p003.head(10)
```
</div></details>

---
# P-004
### 問題
> P-004: レシート明細データ（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の条件を満たすデータを抽出せよ。
> - 顧客ID（customer_id）が"CS018205000001"

### ヒント
データの抽出には df.query('抽出条件') で抽出できるようだが...

- 参考になるサイト

https://qiita.com/dox/items/bf6ce1c71d8d18723e74

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p004 = df_receipt[['sales_ymd','customer_id','product_cd','amount']] # 元データから該当カラム分だけコピー
df_p004.query('customer_id == "CS018205000001" ')                       # データ抽出
```
</div></details>

# P-005
### 問題
> P-005: レシート明細データ（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
> - 顧客ID（customer_id）が"CS018205000001"
> - 売上金額（amount）が1,000以上

### ヒント
P-004解答の抽出条件をand条件にすると...

- 参考になるサイト
特になし

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p005 = df_receipt[['sales_ymd','customer_id','product_cd','amount']] # 元データから該当カラム分だけコピー
df_p005.query('customer_id == "CS018205000001" and amount >= 1000 ')    # データ抽出
```
</div></details>

# P-006
### 問題
>P-006: レシート明細データ（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上数量（quantity）、売上金額（amount）の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
>- 顧客ID（customer_id）が"CS018205000001"
>- 売上金額（amount）が1,000以上または売上数量（quantity）が5以上

### ヒント
P-005解答の抽出条件を頑張って変える？
条件のイメージは A and ( B or C )...?

- 参考になるサイト
特になし

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p006 = df_receipt[['sales_ymd','customer_id','product_cd', 'quantity', 'amount']]    # 元データから該当カラム分だけコピー
df_p006.query('customer_id == "CS018205000001" and (amount >= 1000 or quantity <= 5) ') # データ抽出
```
</div></details>

# P-007
### 問題
> P-007: レシート明細データ（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
> - 顧客ID（customer_id）が"CS018205000001"
> - 売上金額（amount）が1,000以上2,000以下

### ヒント
P-006解答の抽出条件をもっと頑張って変える？
どうやら条件には 1000 <= 'カラム名' <= 2000 が使えるようだが...？

- 参考になるサイト
特になし


<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p007 = df_receipt[['sales_ymd','customer_id','product_cd','amount']]    # 元データから該当カラム分だけコピー
df_p007.query('customer_id == "CS018205000001" and 1000<= amount <= 2000') # データ抽出
```
</div></details>


# P-008
### 問題
> P-008: レシート明細データ（df_receipt）から売上日（sales_ymd）、顧客ID（customer_id）、商品コード（product_cd）、売上金額（amount）の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
> - 顧客ID（customer_id）が"CS018205000001"
> - 商品コード（product_cd）が"P071401019"以外

### ヒント
P-006解答の抽出条件をさらに頑張って変える？
not条件は '!=' だったはずであるが...

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_p008 = df_receipt[['sales_ymd','customer_id','product_cd','amount']]          # 元データから該当カラム分だけコピー
df_p008.query('customer_id == "CS018205000001" and product_cd != "P071401019" ') # データ抽出
```
</div></details>


# P-009
### 問題
> P-009: 以下の処理において、出力結果を変えずにORをANDに書き換えよ。
> 
> `df_store.query('not(prefecture_cd == "13" | floor_area > 900)')`

### ヒント
めっちゃ難しく（正式に）言うと、ド・モルガンの法則を使う...
なんやそれって思うかもしれないが、簡単に言うと"-"の展開でかっこの中身を反転させるように
（例：-(3+5)=(-3-5)） 、
下記式のように各抽出条件を反転させればいい！

![スクリーンショット 2023-01-30 2.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1990652/dff60c4d-fa8b-62ba-c8d0-a4c405183bca.png)

- 参考になるサイト

https://medium-company.com/%E3%83%89%E3%83%BB%E3%83%A2%E3%83%AB%E3%82%AC%E3%83%B3%E3%81%AE%E6%B3%95%E5%89%87/

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_store.query('prefecture_cd != "13" and floor_area <= 900')
```
</div></details>

# P-010
### 問題
> P-010: 店舗データ（df_store）から、店舗コード（store_cd）が"S14"で始まるものだけ全項目抽出し、10件表示せよ。

### ヒント
query関数では前方一致検索を使う方法あるようだ！

- 参考になるサイト

https://note.nkmk.me/python-pandas-query/

<details><summary>主の答え（▶︎をクリックして表示）</summary><div>

```python
df_store.query('store_cd.str.startswith("S14")', engine='python').head(10) # 前方一致検索
# df_store.query("store_cd.str.contains('^S14', regex=True)", engine='python').head(10) # 別解
```
</div></details>


# さいごに
ひとまずの10問、お疲れ様です。
これをやれば、ひとまずの基礎は身につきそうです！
次もよろしくお願いいたします！

# DS 100本ノック ヒント記事リスト

- DS 100本ノック（構造化データ加工編）ヒント集（P-001〜P010）👈 **イマココ!**
- [DS 100本ノック（構造化データ加工編）ヒント集（P-011〜P020）](https://qiita.com/nonono_copen/items/6a7cbe9dce700f1b6990)
- [DS 100本ノック（構造化データ加工編）ヒント集（P-021〜P030）](https://qiita.com/nonono_copen/items/5e0a911bdaaa6e3ca994)
- DS 100本ノック（構造化データ加工編）ヒント集（P-031〜P040）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-041〜P050）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-051〜P060）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-061〜P070）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-071〜P080）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-081〜P090）執筆予定
- DS 100本ノック（構造化データ加工編）ヒント集（P-091〜P100）執筆予定


# 参考文献 各種リンク

1. データサイエンスの100本ノック（構造化データ加工編）
https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess
1. 【毎日Python】Pythonでデータフレームの一部分を表示する方法｜head,tail,sample
https://kino-code.com/python-pandas-head/

1. Pandas DataFrameの[]と[[]]に関して カラム取得方法を理解しよう！
https://aiacademy.jp/media/?p=651

1. pandas.DataFrameの行名・列名の変更
https://note.nkmk.me/python-pandas-dataframe-rename/
1. pandas.DataFrame.queryによるデータ抽出10選
https://qiita.com/dox/items/bf6ce1c71d8d18723e74
1. ド・モルガンの法則とは
https://medium-company.com/%E3%83%89%E3%83%BB%E3%83%A2%E3%83%AB%E3%82%AC%E3%83%B3%E3%81%AE%E6%B3%95%E5%89%87/

1. pandas.DataFrameの行を条件で抽出するquery
https://note.nkmk.me/python-pandas-query/