LoginSignup
8
10

Polarsは速いだけじゃなくて可読性もいいぞ

Last updated at Posted at 2023-10-27

2024-06-12 polars 1.0.0-alpha.1 でWarningが出ないよう修正しました。

先駆者

本文

データサイエンス100本ノック(構造化データ加工編) P-069

レシート明細データ(df_receipt)と商品データ(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、結果を10件表示せよ。

問題文の逐語訳レベルで書ける!!!

Polars
(
    # レシート明細データ(df_receipt)と商品データ(df_product)を結合し、
    df_receipt
    .join(df_product, on="product_cd", how="inner")
    # 顧客毎に
    .group_by("customer_id").agg(
        # 全商品の売上金額合計と、
        sum_all=pl.sum("amount"),
        # カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、
        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")))
    # 抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、
    .filter(pl.col("sum_07") > 0)
    .sort("customer_id")  # pandas版と合わせる
    # 結果を10件表示せよ。
    .head(10)
)
Pandas: データサイエンス100本ノック(構造化データ加工編) コード例1より引用&コメント追記
# 顧客毎に全商品の売上金額合計と、
df_tmp_1 = df_receipt.groupby('customer_id').agg({'amount':'sum'}). \
                reset_index().rename(columns={'amount':'sum_all'})

# カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、
df_tmp_2 = pd.merge(df_receipt, df_product.query('category_major_cd == "07"'), 
                how='inner', on='product_cd').groupby('customer_id').\
                agg({'amount':'sum'}).reset_index().\
                rename(columns={'amount':'sum_07'})

# レシート明細データ(df_receipt)と商品データ(df_product)を結合し、
# 抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、
df_tmp_3 = pd.merge(df_tmp_1, df_tmp_2, how='inner', on='customer_id')

# 両者の比率を求めよ。
df_tmp_3['sales_rate'] = df_tmp_3['sum_07'] / df_tmp_3['sum_all']

# 結果を10件表示せよ。
df_tmp_3.head(10)
Pandas: メソッドチェーンで書いた場合
(
    # レシート明細データ(df_receipt)と商品データ(df_product)を結合し、
    df_receipt
    .merge(df_product, on="product_cd", how="inner")
    # カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計
    .assign(amount_07=lambda df: df["amount"] * (df["category_major_cd"] == "07"))
    # 顧客毎に
    .groupby("customer_id").agg(
        # 全商品の売上金額合計と、
        sum_all=("amount", "sum"),
        # カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、
        sum_07=("amount_07", "sum"),
    )
    # 両者の比率を求めよ。
    .assign(sales_rate=lambda df: df["sum_07"] / df["sum_all"])
    # 抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、
    .query("sum_07 > 0")
    # 結果を10件表示せよ。
    .head(10)
)

notebook

8
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10