数据科学 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 |
| "CS023414000088" | 8798 | 3.944409 |
| "CS016614000024" | 306 | 2.48643 |
| "CS015412000084" | 220 | 2.343409 |
| "CS002415000718" | 538 | 2.731186 |
| "CS019415000021" | 3294 | 3.51779 |
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 |
| "CS004412000219" | 2458 | 7.807307 |
| "CS032415000225" | 3363 | 8.120737 |
| "CS001514000168" | 1646 | 7.406407 |
| "CS011513000188" | 739 | 6.605974 |
| "CS035214000006" | 4264 | 8.35808 |
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 |
| "CS044512000014" | 2018-11-01 | 2017-02-02 | 637 |
| "CS040415000066" | 2017-03-05 | 2015-07-09 | 605 |
| "CS003413000163" | 2018-02-23 | 2015-03-05 | 1086 |
| "CS014513000201" | 2018-11-16 | 2015-05-29 | 1267 |
| "CS037414000122" | 2019-05-27 | 2015-05-13 | 1475 |