データサイエンス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 |
"CS025515000057" | 8013 | 3.903822 |
"CS013414000081" | 5343 | 3.727826 |
"CS010315000024" | 202 | 2.306425 |
"CS001515000463" | 784 | 2.894593 |
"CS007512000029" | 328 | 2.516535 |
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 |
"CS037615000085" | 202 | 5.31074 |
"CS030212000045" | 208 | 5.339939 |
"CS028415000215" | 4062 | 8.309554 |
"CS005214000025" | 4028 | 8.301149 |
"CS034513000213" | 2908 | 7.975393 |
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.24911389885177007
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 |
"CS020414000112" | 2019-02-04 | 2015-04-27 | 1379 |
"CS021515000011" | 2017-03-12 | 2015-06-29 | 622 |
"CS014514000085" | 2017-01-21 | 2015-06-06 | 595 |
"CS014415000088" | 2017-10-09 | 2015-12-21 | 658 |
"CS008514000055" | 2018-12-03 | 2015-02-12 | 1390 |