データサイエンス100本ノック　31～40

# データサイエンス100本ノック（構造化データ加工編）
https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess

GitHubにColaboratoryが用意されているので、自分のドライブにコピーするだけで簡単に始められます。

※協会が出している解答の書き方と異なる箇所もありますが、出力としては同じになっています。協会の解答はGitHubから確認してください。解説本も販売されています。

# 解答
### P031
> レシート明細データ（df_receipt）に対し、店舗コード（store_cd）ごとに売上金額（amount）の標準偏差を計算し、降順で5件表示せよ。
```Python:P031
df_receipt.groupby('store_cd').agg({'amount':'std'}).reset_index().sort_values('amount',ascending = False).rename(columns ={'amount':'amount_std'}).head()
```

### P032
>レシート明細データ（df_receipt）の売上金額（amount）について、25％刻みでパーセンタイル値を求めよ。
```Python:P032
df_receipt['amount'].quantile([0, 0.25, 0.5, 0.75, 1.0])
```
[DataFrame.quantile()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.quantile.html)でパーセントタイルを取得できます。

### P033
>レシート明細データ（df_receipt）に対し、店舗コード（store_cd）ごとに売上金額（amount）の平均を計算し、330以上のものを抽出せよ。
```Python:P033
df_receipt.groupby('store_cd').agg({'amount':'mean'}).reset_index().rename(columns = {'amount':'amount_mean'}).query('amount_mean >= 330')
```

### P034
>レシート明細データ（df_receipt）に対し、顧客ID（customer_id）ごとに売上金額（amount）を合計して全顧客の平均を求めよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
```Python:P034
df_receipt_customer_sum = df_receipt.query('~customer_id.str.startswith("Z")', engine = 'python').groupby('customer_id').agg({'amount':'sum'}).reset_index().rename(columns = {'amount':'amount_sum'})
df_receipt_customer_sum['amount_sum'].mean()
```

### P035
>レシート明細データ（df_receipt）に対し、顧客ID（customer_id）ごとに売上金額（amount）を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出し、10件表示せよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
```Python:P035
df_receipt_customer_sum = df_receipt.query('~customer_id.str.startswith("Z")', engine = 'python').groupby('customer_id').agg({'amount':'sum'}).reset_index().rename(columns = {'amount':'amount_sum'})
amount_mean = df_receipt_customer_sum['amount_sum'].mean()
df_receipt_customer_sum.query("amount_sum >= @amount_mean").head(10)
```
query()の中で変数を使うときは`@変数`とすることで、定義された変数にアクセス可能になる。

### P036
>レシート明細データ（df_receipt）と店舗データ（df_store）を内部結合し、レシート明細データの全項目と店舗データの店舗名（store_name）を10件表示せよ。
```Python:P036
df_receipt.merge(df_store[['store_cd','store_name']],on = 'store_cd').head(10)
```

### P037
>商品データ（df_product）とカテゴリデータ（df_category）を内部結合し、商品データの全項目とカテゴリデータのカテゴリ小区分名（category_small_name）を10件表示せよ。
```Python:P037
df_product.merge(df_category[['category_small_cd','category_small_name']],on = 'category_small_cd').head(10)
```
- 結合方法の指定: 引数how
- 結合方法は引数howに文字列で指定。デフォルトはhow='inner'

### P038
>顧客データ（df_customer）とレシート明細データ（df_receipt）から、顧客ごとの売上金額合計を求め、10件表示せよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード（gender_cd）が女性（1）であるものを対象とし、非会員（顧客IDが"Z"から始まるもの）は除外すること。
```Python:P038
df_receipt_sum = df_receipt.groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_customer_women = df_customer.query('gender_cd == "1" & ~customer_id.str.startswith("Z")', engine = 'python')
df_merge = df_customer_women.merge(df_receipt_sum, on='customer_id', how='left').fillna(0)
df_merge[['customer_id','amount']].head(10)
```

### P039
>レシート明細データ（df_receipt）から、売上日数の多い顧客の上位20件を抽出したデータと、売上金額合計の多い顧客の上位20件を抽出したデータをそれぞれ作成し、さらにその2つを完全外部結合せよ。ただし、非会員（顧客IDが"Z"から始まるもの）は除外すること。
```Python:P039
df_receipt_notZ = df_receipt.query('~customer_id.str.startswith("Z")', engine = 'python')
# 売り上げ日数
df_receipt_ymd = df_receipt_notZ[['sales_ymd','customer_id']].groupby('customer_id')['sales_ymd'].nunique().sort_values(ascending=False).reset_index().rename(columns = {'sales_ymd':'sales_ymd_count'}) 
df_receipt_ymd_20 = df_receipt_ymd.head(20)

# 売り上げ金額
df_amount_sum = df_receipt_notZ.groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_amount_sum_20 = df_amount_sum.sort_values(by = 'amount',ascending=False).reset_index(drop=True).head(20)

pd.merge(df_receipt_ymd_20,df_amount_sum_20, how='outer')

```

### P040
>全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ（df_store）と商品データ（df_product）を直積し、件数を計算せよ。
```Python:P040
len(pd.merge(df_store,df_product,how='cross'))
```
全要素の組み合わせ総当たりをさせたいときに直積をとる。