データサイエンス100本ノック 61~70#
import polars as pl
from helper.polars import load_100knocks_data
pl.Config.set_fmt_str_lengths(100)
df_customer, df_category, df_product, df_receipt, df_store, df_geocode = load_100knocks_data()
P-061#
レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を常用対数化(底10)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
(
df_receipt
.group_by('customer_id')
.agg(
pl.col.amount.sum().alias('sum_amount'),
(pl.col.amount.sum() + 0.5).log10().alias('log_amount')
)
.head()
)
| customer_id | sum_amount | log_amount |
|---|---|---|
| str | i64 | f64 |
| "CS011415000164" | 5583 | 3.746907 |
| "CS023415000050" | 4377 | 3.641226 |
| "CS025314000025" | 3726 | 3.571301 |
| "CS020414000031" | 5443 | 3.735878 |
| "CS002214000043" | 8073 | 3.907062 |
P-062#
レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を自然対数化(底e)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
(
df_receipt
.group_by('customer_id')
.agg(
pl.col.amount.sum().alias('sum_amount'),
(pl.col.amount.sum() + 0.5).log().alias('log_amount')
)
.head()
)
| customer_id | sum_amount | log_amount |
|---|---|---|
| str | i64 | f64 |
| "CS004515000166" | 1144 | 7.042723 |
| "CS013304000006" | 2167 | 7.68133 |
| "CS009513000059" | 1664 | 7.41728 |
| "CS030304000002" | 6095 | 8.715306 |
| "CS037515000033" | 2279 | 7.731711 |
P-063#
商品データ(df_product)の単価(unit_price)と原価(unit_cost)から各商品の利益額を算出し、結果を10件表示せよ。
(
df_product
.select(
pl.col.product_cd,
pl.col.unit_price,
pl.col.unit_cost,
(pl.col.unit_price - pl.col.unit_cost).alias('unit_profit')
)
.head()
)
| product_cd | unit_price | unit_cost | unit_profit |
|---|---|---|---|
| str | i64 | i64 | i64 |
| "P040101001" | 198 | 149 | 49 |
| "P040101002" | 218 | 164 | 54 |
| "P040101003" | 230 | 173 | 57 |
| "P040101004" | 248 | 186 | 62 |
| "P040101005" | 268 | 201 | 67 |
P-064#
商品データ(df_product)の単価(unit_price)と原価(unit_cost)から、各商品の利益率の全体平均を算出せよ。ただし、単価と原価には欠損が生じていることに注意せよ。
(
df_product
.select(
((pl.col.unit_price - pl.col.unit_cost) / pl.col.unit_price).mean()
)
.item()
)
0.24911389885177
P-065#
商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
(
df_product
.select(
pl.col.product_cd,
pl.col.unit_price,
pl.col.unit_cost,
(pl.col.unit_cost / 0.7).floor().cast(pl.Int32).alias('new_price')
)
.with_columns(
new_profit_rate=(pl.col.new_price - pl.col.unit_cost) / pl.col.new_price
)
.head(10)
)
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| str | i64 | i64 | i32 | f64 |
| "P040101001" | 198 | 149 | 212 | 0.29717 |
| "P040101002" | 218 | 164 | 234 | 0.299145 |
| "P040101003" | 230 | 173 | 247 | 0.299595 |
| "P040101004" | 248 | 186 | 265 | 0.298113 |
| "P040101005" | 268 | 201 | 287 | 0.299652 |
| "P040101006" | 298 | 224 | 320 | 0.3 |
| "P040101007" | 338 | 254 | 362 | 0.298343 |
| "P040101008" | 420 | 315 | 450 | 0.3 |
| "P040101009" | 498 | 374 | 534 | 0.299625 |
| "P040101010" | 580 | 435 | 621 | 0.299517 |
P-066#
商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を丸めること(四捨五入または偶数への丸めで良い)。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
(
df_product
.select(
pl.col.product_cd,
pl.col.unit_price,
pl.col.unit_cost,
(pl.col.unit_cost / 0.7)
.round()
.cast(pl.Int32)
.alias('new_price')
)
.with_columns(
new_profit_rate=(pl.col.new_price - pl.col.unit_cost) / pl.col.new_price
)
.head(10)
)
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| str | i64 | i64 | i32 | f64 |
| "P040101001" | 198 | 149 | 213 | 0.300469 |
| "P040101002" | 218 | 164 | 234 | 0.299145 |
| "P040101003" | 230 | 173 | 247 | 0.299595 |
| "P040101004" | 248 | 186 | 266 | 0.300752 |
| "P040101005" | 268 | 201 | 287 | 0.299652 |
| "P040101006" | 298 | 224 | 320 | 0.3 |
| "P040101007" | 338 | 254 | 363 | 0.300275 |
| "P040101008" | 420 | 315 | 450 | 0.3 |
| "P040101009" | 498 | 374 | 534 | 0.299625 |
| "P040101010" | 580 | 435 | 621 | 0.299517 |
P-067#
商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を切り上げること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
(
df_product
.select(
pl.col.product_cd,
pl.col.unit_price,
pl.col.unit_cost,
(pl.col.unit_cost / 0.7)
.ceil()
.cast(pl.Int32)
.alias('new_price')
)
.with_columns(
new_profit_rate=(pl.col.new_price - pl.col.unit_cost) / pl.col.new_price
)
.head(10)
)
| product_cd | unit_price | unit_cost | new_price | new_profit_rate |
|---|---|---|---|---|
| str | i64 | i64 | i32 | f64 |
| "P040101001" | 198 | 149 | 213 | 0.300469 |
| "P040101002" | 218 | 164 | 235 | 0.302128 |
| "P040101003" | 230 | 173 | 248 | 0.302419 |
| "P040101004" | 248 | 186 | 266 | 0.300752 |
| "P040101005" | 268 | 201 | 288 | 0.302083 |
| "P040101006" | 298 | 224 | 320 | 0.3 |
| "P040101007" | 338 | 254 | 363 | 0.300275 |
| "P040101008" | 420 | 315 | 450 | 0.3 |
| "P040101009" | 498 | 374 | 535 | 0.300935 |
| "P040101010" | 580 | 435 | 622 | 0.300643 |
P-068#
商品データ(df_product)の各商品について、消費税率10%の税込み金額を求めよ。1円未満の端数は切り捨てとし、結果を10件表示せよ。ただし、単価(unit_price)には欠損が生じていることに注意せよ。
(
df_product
.select(
pl.col.product_cd,
pl.col.unit_price,
(pl.col.unit_price * 1.1)
.floor()
.cast(pl.Int32)
.alias('tex_price')
)
.head(10)
)
| product_cd | unit_price | tex_price |
|---|---|---|
| str | i64 | i32 |
| "P040101001" | 198 | 217 |
| "P040101002" | 218 | 239 |
| "P040101003" | 230 | 253 |
| "P040101004" | 248 | 272 |
| "P040101005" | 268 | 294 |
| "P040101006" | 298 | 327 |
| "P040101007" | 338 | 371 |
| "P040101008" | 420 | 462 |
| "P040101009" | 498 | 547 |
| "P040101010" | 580 | 638 |
P-069#
レシート明細データ(df_receipt)と商品データ(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、結果を10件表示せよ。
(
df_receipt
.join(df_product, on='product_cd', how='left')
.group_by('customer_id', maintain_order=True)
.agg(
sum_all=pl.col.amount.sum(),
sum_07=pl.col.amount
.filter(pl.col.category_major_cd == '07')
.sum()
)
.with_columns(
sales_rate=pl.col.sum_07 / pl.col.sum_all
)
.head(10)
)
| customer_id | sum_all | sum_07 | sales_rate |
|---|---|---|---|
| str | i64 | i64 | f64 |
| "CS006214000001" | 7364 | 4713 | 0.640005 |
| "CS008415000097" | 1895 | 1337 | 0.705541 |
| "CS028414000014" | 6222 | 3701 | 0.594825 |
| "ZZ000000000000" | 12395003 | 6943009 | 0.560146 |
| "CS025415000050" | 5736 | 3536 | 0.616457 |
| "CS003515000195" | 5412 | 4581 | 0.846452 |
| "CS024514000042" | 533 | 0 | 0.0 |
| "CS040415000178" | 6149 | 4802 | 0.78094 |
| "CS027514000015" | 2788 | 1475 | 0.529053 |
| "CS025415000134" | 4902 | 3430 | 0.699714 |
P-070#
レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、顧客データ(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。
(
df_receipt
.select('customer_id', 'sales_ymd')
.unique()
.join(df_customer, on='customer_id')
.select(
pl.col.customer_id,
pl.col.sales_ymd.cast(str).str.strptime(pl.Date, '%Y%m%d'),
pl.col.application_date.cast(str).str.strptime(pl.Date, '%Y%m%d')
)
.with_columns(
elapsed_days=(pl.col.sales_ymd - pl.col.application_date).dt.total_days()
)
.head()
)
| customer_id | sales_ymd | application_date | elapsed_days |
|---|---|---|---|
| str | date | date | i64 |
| "CS012415000083" | 2019-04-09 | 2015-06-02 | 1407 |
| "CS013815000018" | 2019-10-19 | 2015-05-23 | 1610 |
| "CS029515000107" | 2019-07-02 | 2015-01-22 | 1622 |
| "CS013415000041" | 2017-01-23 | 2015-05-04 | 630 |
| "CS006605000009" | 2017-09-19 | 2015-03-23 | 911 |